diff --git a/.bun-local/_bun b/.bun-local/_bun deleted file mode 100644 index 34940fef1103..000000000000 --- a/.bun-local/_bun +++ /dev/null @@ -1,1038 +0,0 @@ -#compdef bun - -_bun_add_completion() { - _arguments -s -C \ - '1: :->cmd1' \ - '*: :->package' \ - '--config[Load config(bunfig.toml)]: :->config' \ - '-c[Load config(bunfig.toml)]: :->config' \ - '--yarn[Write a yarn.lock file (yarn v1)]' \ - '-y[Write a yarn.lock file (yarn v1)]' \ - '--production[Don'"'"'t install devDependencies]' \ - '-p[Don'"'"'t install devDependencies]' \ - '--no-save[Don'"'"'t save a lockfile]' \ - '--save[Save to package.json]' \ - '--dry-run[Don'"'"'t install anything]' \ - '--frozen-lockfile[Disallow changes to lockfile]' \ - '--force[Always request the latest versions from the registry & reinstall all dependencies]' \ - '-f[Always request the latest versions from the registry & reinstall all dependencies]' \ - '--cache-dir[Store & load cached data from a specific directory path]:cache-dir' \ - '--no-cache[Ignore manifest cache entirely]' \ - '--silent[Don'"'"'t log anything]' \ - '--verbose[Excessively verbose logging]' \ - '--no-progress[Disable the progress bar]' \ - '--no-summary[Don'"'"'t print a summary]' \ - '--no-verify[Skip verifying integrity of newly downloaded packages]' \ - '--ignore-scripts[Skip lifecycle scripts in the package.json (dependency scripts are never run)]' \ - '--global[Add a package globally]' \ - '-g[Add a package globally]' \ - '--cwd[Set a specific cwd]:cwd' \ - '--backend[Platform-specific optimizations for installing dependencies]:backend:("copyfile" "hardlink" "symlink")' \ - '--link-native-bins[Link "bin" from a matching platform-specific dependency instead. Default: esbuild, turbo]:link-native-bins' \ - '--help[Print this help menu]' \ - '--dev[Add dependence to "devDependencies]' \ - '-d[Add dependence to "devDependencies]' \ - '-D[]' \ - '--development[]' \ - '--optional[Add dependency to "optionalDependencies]' \ - '--peer[Add dependency to "peerDependencies]' \ - '--exact[Add the exact version instead of the ^range]' && - ret=0 - - case $state in - config) - _bun_list_bunfig_toml - - ;; - package) - _bun_add_param_package_completion - - ;; - esac -} - -_bun_unlink_completion() { - _arguments -s -C \ - '1: :->cmd1' \ - '*: :->package' \ - '--config[Load config(bunfig.toml)]: :->config' \ - '-c[Load config(bunfig.toml)]: :->config' \ - '--yarn[Write a yarn.lock file (yarn v1)]' \ - '-y[Write a yarn.lock file (yarn v1)]' \ - '--production[Don'"'"'t install devDependencies]' \ - '-p[Don'"'"'t install devDependencies]' \ - '--no-save[Don'"'"'t save a lockfile]' \ - '--save[Save to package.json]' \ - '--dry-run[Don'"'"'t install anything]' \ - '--frozen-lockfile[Disallow changes to lockfile]' \ - '--force[Always request the latest versions from the registry & reinstall all dependencies]' \ - '-f[Always request the latest versions from the registry & reinstall all dependencies]' \ - '--cache-dir[Store & load cached data from a specific directory path]:cache-dir' \ - '--no-cache[Ignore manifest cache entirely]' \ - '--silent[Don'"'"'t log anything]' \ - '--verbose[Excessively verbose logging]' \ - '--no-progress[Disable the progress bar]' \ - '--no-summary[Don'"'"'t print a summary]' \ - '--no-verify[Skip verifying integrity of newly downloaded packages]' \ - '--ignore-scripts[Skip lifecycle scripts in the package.json (dependency scripts are never run)]' \ - '--global[Add a package globally]' \ - '-g[Add a package globally]' \ - '--cwd[Set a specific cwd]:cwd' \ - '--backend[Platform-specific optimizations for installing dependencies]:backend:("copyfile" "hardlink" "symlink")' \ - '--link-native-bins[Link "bin" from a matching platform-specific dependency instead. Default: esbuild, turbo]:link-native-bins' \ - '--help[Print this help menu]' && - ret=0 - - case $state in - config) - _bun_list_bunfig_toml - - ;; - package) - # TODO: error: bun unlink {packageName} not implemented yet - - ;; - esac -} - -_bun_link_completion() { - _arguments -s -C \ - '1: :->cmd1' \ - '*: :->package' \ - '--config[Load config(bunfig.toml)]: :->config' \ - '-c[Load config(bunfig.toml)]: :->config' \ - '--yarn[Write a yarn.lock file (yarn v1)]' \ - '-y[Write a yarn.lock file (yarn v1)]' \ - '--production[Don'"'"'t install devDependencies]' \ - '-p[Don'"'"'t install devDependencies]' \ - '--no-save[Don'"'"'t save a lockfile]' \ - '--save[Save to package.json]' \ - '--dry-run[Don'"'"'t install anything]' \ - '--frozen-lockfile[Disallow changes to lockfile]' \ - '--force[Always request the latest versions from the registry & reinstall all dependencies]' \ - '-f[Always request the latest versions from the registry & reinstall all dependencies]' \ - '--cache-dir[Store & load cached data from a specific directory path]:cache-dir' \ - '--no-cache[Ignore manifest cache entirely]' \ - '--silent[Don'"'"'t log anything]' \ - '--verbose[Excessively verbose logging]' \ - '--no-progress[Disable the progress bar]' \ - '--no-summary[Don'"'"'t print a summary]' \ - '--no-verify[Skip verifying integrity of newly downloaded packages]' \ - '--ignore-scripts[Skip lifecycle scripts in the package.json (dependency scripts are never run)]' \ - '--global[Add a package globally]' \ - '-g[Add a package globally]' \ - '--cwd[Set a specific cwd]:cwd' \ - '--backend[Platform-specific optimizations for installing dependencies]:backend:("copyfile" "hardlink" "symlink")' \ - '--link-native-bins[Link "bin" from a matching platform-specific dependency instead. Default: esbuild, turbo]:link-native-bins' \ - '--help[Print this help menu]' && - ret=0 - - case $state in - config) - _bun_list_bunfig_toml - - ;; - package) - _bun_link_param_package_completion - - ;; - esac -} - -_bun_bun_completion() { - _arguments -s -C \ - '1: :->cmd' \ - '*: :->file' \ - '--version[Show version and exit]' \ - '-V[Show version and exit]' \ - '--cwd[Change directory]:cwd' \ - '--help[Show command help]' \ - '-h[Show command help]' \ - '--use[Use a framework, e.g. "next"]:use' && - ret=0 - - case $state in - file) - _files - - ;; - esac -} - -_bun_init_completion() { - _arguments -s -C \ - '1: :->cmd' \ - '-y[Answer yes to all prompts]:' \ - '--yes[Answer yes to all prompts]:' && - ret=0 - -} - -_bun_create_completion() { - _arguments -s -C \ - '1: :->cmd' \ - '2: :->cmd2' \ - '*: :->args' && - ret=0 - - case $state in - cmd2) - _alternative 'args:create:((next-app\:"Next.js app" react-app\:"React app"))' - - ;; - args) - case $line[2] in - next) - pmargs=( - '1: :->cmd' - '2: :->cmd2' - '3: :->file' - '--force[Overwrite existing files]' - '--no-install[Don'"'"'t install node_modules]' - '--no-git[Don'"'"'t create a git repository]' - '--verbose[verbose]' - '--no-package-json[Disable package.json transforms]' - '--open[On finish, start bun & open in-browser]' - ) - - # ---- Command: create next - _arguments -s -C \ - $pmargs && - ret=0 - - case $state in - file) - _files - - ;; - esac - - ;; - react) - - # ---- Command: create react - _arguments -s -C \ - $pmargs && - ret=0 - - case $state in - file) - _files - - ;; - esac - - ;; - *) - - # ---- Command: create from other template - _arguments -s -C \ - $pmargs && - ret=0 - - case $state in - file) - _files - - ;; - esac - - ;; - esac - - ;; - - esac -} - -_bun_pm_completion() { - _arguments -s -C \ - '1: :->cmd' \ - '2: :->cmd2' \ - '*: :->args' && - ret=0 - - case $state in - cmd2) - sub_commands=( - 'bin\:"print the path to bin folder" ' - 'ls\:"list the dependency tree according to the current lockfile" ' - 'hash\:"generate & print the hash of the current lockfile" ' - 'hash-string\:"print the string used to hash the lockfile" ' - 'hash-print\:"print the hash stored in the current lockfile" ' - 'cache\:"print the path to the cache folder" ' - 'version\:"bump the version in package.json and create a git tag" ' - ) - - _alternative "args:cmd3:(($sub_commands))" - - ;; - args) - case $line[2] in - cache) - _arguments -s -C \ - '1: :->cmd' \ - '2: :->cmd2' \ - ':::(rm)' && - ret=0 - - ;; - bin) - pmargs=( - "-g[print the global path to bin folder]" - ) - - _arguments -s -C \ - '1: :->cmd' \ - '2: :->cmd2' \ - $pmargs && - ret=0 - - ;; - ls) - pmargs=( - "--all[list the entire dependency tree according to the current lockfile]" - ) - - _arguments -s -C \ - '1: :->cmd' \ - '2: :->cmd2' \ - $pmargs && - ret=0 - - ;; - version) - version_args=( - "patch[increment patch version]" - "minor[increment minor version]" - "major[increment major version]" - "prepatch[increment patch version and add pre-release]" - "preminor[increment minor version and add pre-release]" - "premajor[increment major version and add pre-release]" - "prerelease[increment pre-release version]" - "from-git[use version from latest git tag]" - ) - - pmargs=( - "--no-git-tag-version[don't create a git commit and tag]" - "--allow-same-version[allow bumping to the same version]" - "-m[use the given message for the commit]:message" - "--message[use the given message for the commit]:message" - "--preid[identifier to prefix pre-release versions]:preid" - ) - - _arguments -s -C \ - '1: :->cmd' \ - '2: :->cmd2' \ - '3: :->increment' \ - $pmargs && - ret=0 - - case $state in - increment) - _alternative "args:increment:(($version_args))" - ;; - esac - - ;; - esac - - ;; - esac -} - -_bun_install_completion() { - _arguments -s -C \ - '1: :->cmd1' \ - '--config[Load config(bunfig.toml)]: :->config' \ - '-c[Load config(bunfig.toml)]: :->config' \ - '--yarn[Write a yarn.lock file (yarn v1)]' \ - '-y[Write a yarn.lock file (yarn v1)]' \ - '--production[Don'"'"'t install devDependencies]' \ - '-p[Don'"'"'t install devDependencies]' \ - '--no-save[Don'"'"'t save a lockfile]' \ - '--save[Save to package.json]' \ - '--dry-run[Don'"'"'t install anything]' \ - '--frozen-lockfile[Disallow changes to lockfile]' \ - '--force[Always request the latest versions from the registry & reinstall all dependencies]' \ - '-f[Always request the latest versions from the registry & reinstall all dependencies]' \ - '--cache-dir[Store & load cached data from a specific directory path]:cache-dir' \ - '--no-cache[Ignore manifest cache entirely]' \ - '--silent[Don'"'"'t log anything]' \ - '--verbose[Excessively verbose logging]' \ - '--no-progress[Disable the progress bar]' \ - '--no-summary[Don'"'"'t print a summary]' \ - '--no-verify[Skip verifying integrity of newly downloaded packages]' \ - '--ignore-scripts[Skip lifecycle scripts in the package.json (dependency scripts are never run)]' \ - '--global[Add a package globally]' \ - '-g[Add a package globally]' \ - '--cwd[Set a specific cwd]:cwd' \ - '--backend[Platform-specific optimizations for installing dependencies]:backend:("copyfile" "hardlink" "symlink")' \ - '--link-native-bins[Link "bin" from a matching platform-specific dependency instead. Default: esbuild, turbo]:link-native-bins' \ - '--help[Print this help menu]' \ - '--dev[Add dependence to "devDependencies]' \ - '-d[Add dependence to "devDependencies]' \ - '--development[]' \ - '-D[]' \ - '--optional[Add dependency to "optionalDependencies]' \ - '--peer[Add dependency to "peerDependencies]' \ - '--exact[Add the exact version instead of the ^range]' && - ret=0 - - case $state in - config) - _bun_list_bunfig_toml - - ;; - esac -} - -_bun_remove_completion() { - _arguments -s -C \ - '1: :->cmd1' \ - '*: :->package' \ - '--config[Load config(bunfig.toml)]: :->config' \ - '-c[Load config(bunfig.toml)]: :->config' \ - '--yarn[Write a yarn.lock file (yarn v1)]' \ - '-y[Write a yarn.lock file (yarn v1)]' \ - '--production[Don'"'"'t install devDependencies]' \ - '-p[Don'"'"'t install devDependencies]' \ - '--no-save[Don'"'"'t save a lockfile]' \ - '--save[Save to package.json]' \ - '--dry-run[Don'"'"'t install anything]' \ - '--frozen-lockfile[Disallow changes to lockfile]' \ - '--force[Always request the latest versions from the registry & reinstall all dependencies]' \ - '-f[Always request the latest versions from the registry & reinstall all dependencies]' \ - '--cache-dir[Store & load cached data from a specific directory path]:cache-dir' \ - '--no-cache[Ignore manifest cache entirely]' \ - '--silent[Don'"'"'t log anything]' \ - '--verbose[Excessively verbose logging]' \ - '--no-progress[Disable the progress bar]' \ - '--no-summary[Don'"'"'t print a summary]' \ - '--no-verify[Skip verifying integrity of newly downloaded packages]' \ - '--ignore-scripts[Skip lifecycle scripts in the package.json (dependency scripts are never run)]' \ - '--global[Add a package globally]' \ - '-g[Add a package globally]' \ - '--cwd[Set a specific cwd]:cwd' \ - '--backend[Platform-specific optimizations for installing dependencies]:backend:("copyfile" "hardlink" "symlink")' \ - '--link-native-bins[Link "bin" from a matching platform-specific dependency instead. Default: esbuild, turbo]:link-native-bins' \ - '--help[Print this help menu]' && - ret=0 - - case $state in - config) - _bun_list_bunfig_toml - - ;; - package) - _bun_remove_param_package_completion - - ;; - esac -} - -_bun_run_completion() { - _arguments -s -C \ - '1: :->cmd' \ - '2: :->script' \ - '*: :->other' \ - '--help[Display this help and exit]' \ - '-h[Display this help and exit]' \ - '--bun[Force a script or package to use Bun'"'"'s runtime instead of Node.js (via symlinking node)]' \ - '-b[Force a script or package to use Bun'"'"'s runtime instead of Node.js (via symlinking node)]' \ - '--cwd[Absolute path to resolve files & entry points from. This just changes the process cwd]:cwd' \ - '--config[Config file to load bun from (e.g. -c bunfig.toml]: :->config' \ - '-c[Config file to load bun from (e.g. -c bunfig.toml]: :->config' \ - '--env-file[Load environment variables from the specified file(s)]:env-file' \ - '--extension-order[Defaults to: .tsx,.ts,.jsx,.js,.json]:extension-order' \ - '--jsx-factory[Changes the function called when compiling JSX elements using the classic JSX runtime]:jsx-factory' \ - '--jsx-fragment[Changes the function called when compiling JSX fragments]:jsx-fragment' \ - '--jsx-import-source[Declares the module specifier to be used for importing the jsx and jsxs factory functions. Default: "react"]:jsx-import-source' \ - '--jsx-runtime["automatic" (default) or "classic"]: :->jsx-runtime' \ - '--preload[Import a module before other modules are loaded]:preload' \ - '-r[Import a module before other modules are loaded]:preload' \ - '--main-fields[Main fields to lookup in package.json. Defaults to --target dependent]:main-fields' \ - '--no-summary[Don'"'"'t print a summary]' \ - '--version[Print version and exit]' \ - '-v[Print version and exit]' \ - '--revision[Print version with revision and exit]' \ - '--tsconfig-override[Load tsconfig from path instead of cwd/tsconfig.json]:tsconfig-override' \ - '--define[Substitute K:V while parsing, e.g. --define process.env.NODE_ENV:"development". Values are parsed as JSON.]:define' \ - '-d[Substitute K:V while parsing, e.g. --define process.env.NODE_ENV:"development". Values are parsed as JSON.]:define' \ - '--external[Exclude module from transpilation (can use * wildcards). ex: -e react]:external' \ - '-e[Exclude module from transpilation (can use * wildcards). ex: -e react]:external' \ - '--loader[Parse files with .ext:loader, e.g. --loader .js:jsx. Valid loaders: js, jsx, ts, tsx, json, toml, text, file, wasm, napi]:loader' \ - '--packages[Exclude dependencies from bundle, e.g. --packages external. Valid options: bundle, external]:packages' \ - '-l[Parse files with .ext:loader, e.g. --loader .js:jsx. Valid loaders: js, jsx, ts, tsx, json, toml, text, file, wasm, napi]:loader' \ - '--origin[Rewrite import URLs to start with --origin. Default: ""]:origin' \ - '-u[Rewrite import URLs to start with --origin. Default: ""]:origin' \ - '--port[Port to serve bun'"'"'s dev server on. Default: '"'"'3000'"'"']:port' \ - '-p[Port to serve bun'"'"'s dev server on. Default: '"'"'3000'"'"']:port' \ - '--smol[Use less memory, but run garbage collection more often]' \ - '--minify[Minify (experimental)]' \ - '--minify-syntax[Minify syntax and inline data (experimental)]' \ - '--minify-whitespace[Minify Whitespace (experimental)]' \ - '--minify-identifiers[Minify identifiers]' \ - '--no-macros[Disable macros from being executed in the bundler, transpiler and runtime]' \ - '--target[The intended execution environment for the bundle. "browser", "bun" or "node"]: :->target' \ - '--inspect[Activate Bun'"'"'s Debugger]:inspect' \ - '--inspect-wait[Activate Bun'"'"'s Debugger, wait for a connection before executing]:inspect-wait' \ - '--inspect-brk[Activate Bun'"'"'s Debugger, set breakpoint on first line of code and wait]:inspect-brk' \ - '--hot[Enable auto reload in bun'"'"'s JavaScript runtime]' \ - '--watch[Automatically restart bun'"'"'s JavaScript runtime on file change]' \ - '--no-install[Disable auto install in bun'"'"'s JavaScript runtime]' \ - '--install[Install dependencies automatically when no node_modules are present, default: "auto". "force" to ignore node_modules, fallback to install any missing]: :->install_' \ - '-i[Automatically install dependencies and use global cache in bun'"'"'s runtime, equivalent to --install=fallback'] \ - '--prefer-offline[Skip staleness checks for packages in bun'"'"'s JavaScript runtime and resolve from disk]' \ - '--prefer-latest[Use the latest matching versions of packages in bun'"'"'s JavaScript runtime, always checking npm]' \ - '--silent[Don'"'"'t repeat the command for bun run]' \ - '--dump-environment-variables[Dump environment variables from .env and process as JSON and quit. Useful for debugging]' \ - '--dump-limits[Dump system limits. Userful for debugging]' && - ret=0 - - case $state in - script) - curcontext="${curcontext%:*:*}:bun-grouped" - _bun_run_param_script_completion - - ;; - jsx-runtime) - _alternative 'args:cmd3:((classic automatic))' - - ;; - target) - _alternative 'args:cmd3:((browser bun node))' - - ;; - install_) - _alternative 'args:cmd3:((auto force fallback))' - - ;; - other) - _files - - ;; - esac - -} - -_bun_upgrade_completion() { - _arguments -s -C \ - '1: :->cmd' \ - '--canary[Upgrade to canary build]' && - ret=0 - -} - -_bun_repl_completion() { - _arguments -s -C \ - '1: :->cmd' \ - '--help[Print this help menu]' \ - '-h[Print this help menu]' \ - '(-p --print)--eval[Evaluate argument as a script, then exit]:script' \ - '(-p --print)-e[Evaluate argument as a script, then exit]:script' \ - '(-e --eval)--print[Evaluate argument as a script, print the result, then exit]:script' \ - '(-e --eval)-p[Evaluate argument as a script, print the result, then exit]:script' \ - '--preload[Import a module before other modules are loaded]:preload' \ - '-r[Import a module before other modules are loaded]:preload' \ - '--smol[Use less memory, but run garbage collection more often]' \ - '--config[Specify path to Bun config file]: :->config' \ - '-c[Specify path to Bun config file]: :->config' \ - '--cwd[Absolute path to resolve files & entry points from]:cwd' \ - '--env-file[Load environment variables from the specified file(s)]:env-file' \ - '--no-env-file[Disable automatic loading of .env files]' && - ret=0 - - case $state in - config) - _bun_list_bunfig_toml - - ;; - esac -} - -_bun_build_completion() { - _arguments -s -C \ - '1: :->cmd' \ - '*: :->file' \ - '--outfile[Write the output to a specific file (default: stdout)]:outfile' \ - '--outdir[Write the output to a directory (required for splitting)]:outdir' \ - '--minify[Enable all minification flags]' \ - '--minify-whitespace[Remove unneeded whitespace]' \ - '--minify-syntax[Transform code to use less syntax]' \ - '--minify-identifiers[Shorten variable names]' \ - '--sourcemap[Generate sourcemaps]: :->sourcemap' \ - '--target[The intended execution environment for the bundle. "browser", "bun" or "node"]: :->target' \ - '--splitting[Whether to enable code splitting (requires --outdir)]' \ - '--compile[generating a standalone binary from a TypeScript or JavaScript file]' \ - '--format[Specifies the module format to be used in the generated bundles]: :->format' && - ret=0 - - case $state in - file) - _files - - ;; - target) - _alternative 'args:cmd3:((browser bun node))' - - ;; - sourcemap) - _alternative 'args:cmd3:((none external inline))' - - ;; - format) - - _alternative 'args:cmd3:((esm cjs iife))' - ;; - esac -} - -_bun_update_completion() { - _arguments -s -C \ - '1: :->cmd1' \ - '-c[Load config(bunfig.toml)]: :->config' \ - '--config[Load config(bunfig.toml)]: :->config' \ - '-y[Write a yarn.lock file (yarn v1)]' \ - '--yarn[Write a yarn.lock file (yarn v1)]' \ - '-p[Don'"'"'t install devDependencies]' \ - '--production[Don'"'"'t install devDependencies]' \ - '--no-save[Don'"'"'t save a lockfile]' \ - '--save[Save to package.json]' \ - '--dry-run[Don'"'"'t install anything]' \ - '--frozen-lockfile[Disallow changes to lockfile]' \ - '--latest[Updates dependencies to latest version, regardless of compatibility]' \ - '-f[Always request the latest versions from the registry & reinstall all dependencies]' \ - '--force[Always request the latest versions from the registry & reinstall all dependencies]' \ - '--cache-dir[Store & load cached data from a specific directory path]:cache-dir' \ - '--no-cache[Ignore manifest cache entirely]' \ - '--silent[Don'"'"'t log anything]' \ - '--verbose[Excessively verbose logging]' \ - '--no-progress[Disable the progress bar]' \ - '--no-summary[Don'"'"'t print a summary]' \ - '--no-verify[Skip verifying integrity of newly downloaded packages]' \ - '--ignore-scripts[Skip lifecycle scripts in the package.json (dependency scripts are never run)]' \ - '-g[Add a package globally]' \ - '--global[Add a package globally]' \ - '--cwd[Set a specific cwd]:cwd' \ - '--backend[Platform-specific optimizations for installing dependencies]:backend:("copyfile" "hardlink" "symlink")' \ - '--link-native-bins[Link "bin" from a matching platform-specific dependency instead. Default: esbuild, turbo]:link-native-bins' \ - '--help[Print this help menu]' && - ret=0 - - case $state in - config) - _bun_list_bunfig_toml - - ;; - esac -} - -_bun_outdated_completion() { - _arguments -s -C \ - '--cwd[Set a specific cwd]:cwd' \ - '--verbose[Excessively verbose logging]' \ - '--no-progress[Disable the progress bar]' \ - '--help[Print this help menu]' && - ret=0 - - case $state in - config) - _bun_list_bunfig_toml - - ;; - esac -} - -_bun_test_completion() { - _arguments -s -C \ - '1: :->cmd1' \ - '*: :->file' \ - '-h[Display this help and exit]' \ - '--help[Display this help and exit]' \ - '-b[Force a script or package to use Bun.js instead of Node.js (via symlinking node)]' \ - '--bun[Force a script or package to use Bun.js instead of Node.js (via symlinking node)]' \ - '--cwd[Set a specific cwd]:cwd' \ - '-c[Load config(bunfig.toml)]: :->config' \ - '--config[Load config(bunfig.toml)]: :->config' \ - '--env-file[Load environment variables from the specified file(s)]:env-file' \ - '--extension-order[Defaults to: .tsx,.ts,.jsx,.js,.json]:extension-order' \ - '--jsx-factory[Changes the function called when compiling JSX elements using the classic JSX runtime]:jsx-factory' \ - '--jsx-fragment[Changes the function called when compiling JSX fragments]:jsx-fragment' \ - '--jsx-import-source[Declares the module specifier to be used for importing the jsx and jsxs factory functions. Default: "react"]:jsx-import-source' \ - '--jsx-runtime["automatic" (default) or "classic"]: :->jsx-runtime' \ - '--preload[Import a module before other modules are loaded]:preload' \ - '-r[Import a module before other modules are loaded]:preload' \ - '--main-fields[Main fields to lookup in package.json. Defaults to --target dependent]:main-fields' \ - '--no-summary[Don'"'"'t print a summary]' \ - '--version[Print version and exit]' \ - '-v[Print version and exit]' \ - '--revision[Print version with revision and exit]' \ - '--tsconfig-override[Load tsconfig from path instead of cwd/tsconfig.json]:tsconfig-override' \ - '--define[Substitute K:V while parsing, e.g. --define process.env.NODE_ENV:"development". Values are parsed as JSON.]:define' \ - '-d[Substitute K:V while parsing, e.g. --define process.env.NODE_ENV:"development". Values are parsed as JSON.]:define' \ - '--external[Exclude module from transpilation (can use * wildcards). ex: -e react]:external' \ - '-e[Exclude module from transpilation (can use * wildcards). ex: -e react]:external' \ - '--loader[Parse files with .ext:loader, e.g. --loader .js:jsx. Valid loaders: js, jsx, ts, tsx, json, toml, text, file, wasm, napi]:loader' \ - '-l[Parse files with .ext:loader, e.g. --loader .js:jsx. Valid loaders: js, jsx, ts, tsx, json, toml, text, file, wasm, napi]:loader' \ - '--origin[Rewrite import URLs to start with --origin. Default: ""]:origin' \ - '-u[Rewrite import URLs to start with --origin. Default: ""]:origin' \ - '--port[Port to serve bun'"'"'s dev server on. Default: '"'"'3000'"'"']:port' \ - '-p[Port to serve bun'"'"'s dev server on. Default: '"'"'3000'"'"']:port' \ - '--smol[Use less memory, but run garbage collection more often]' \ - '--minify[Minify (experimental)]' \ - '--minify-syntax[Minify syntax and inline data (experimental)]' \ - '--minify-identifiers[Minify identifiers]' \ - '--no-macros[Disable macros from being executed in the bundler, transpiler and runtime]' \ - '--target[The intended execution environment for the bundle. "browser", "bun" or "node"]: :->target' \ - '--inspect[Activate Bun'"'"'s Debugger]:inspect' \ - '--inspect-wait[Activate Bun'"'"'s Debugger, wait for a connection before executing]:inspect-wait' \ - '--inspect-brk[Activate Bun'"'"'s Debugger, set breakpoint on first line of code and wait]:inspect-brk' \ - '--watch[Automatically restart bun'"'"'s JavaScript runtime on file change]' \ - '--timeout[Set the per-test timeout in milliseconds, default is 5000.]:timeout' \ - '--update-snapshots[Update snapshot files]' \ - '--rerun-each[Re-run each test file times, helps catch certain bugs]:rerun' \ - '--retry[Default retry count for all tests]:retry' \ - '--todo[Include tests that are marked with "test.todo()"]' \ - '--coverage[Generate a coverage profile]' \ - '--bail[Exit the test suite after failures. If you do not specify a number, it defaults to 1.]:bail' \ - '--shard[Run a subset of test files, e.g. 1/3. Useful for splitting tests across CI jobs.]:shard' \ - '--test-name-pattern[Run only tests with a name that matches the given regex]:pattern' \ - '-t[Run only tests with a name that matches the given regex]:pattern' && - ret=0 - - case $state in - file) - _bun_test_param_script_completion - - ;; - config) - _files - - ;; - - esac - -} - -_bun() { - zstyle ':completion:*:*:bun:*' group-name '' - zstyle ':completion:*:*:bun-grouped:*' group-name '' - - zstyle ':completion:*:*:bun::descriptions' format '%F{green}-- %d --%f' - zstyle ':completion:*:*:bun-grouped:*' format '%F{green}-- %d --%f' - # zstyle ':completion:*:options' list-colors '=^(-- *)=34' - - local program=bun - typeset -A opt_args - local curcontext="$curcontext" state line context - - # ---- Command: - _arguments -s \ - '1: :->cmd' \ - '*: :->args' && - ret=0 - - case $state in - cmd) - local -a scripts_list - IFS=$'\n' scripts_list=($(SHELL=zsh bun getcompletes i)) - scripts="scripts:scripts:((${scripts_list//:/\\\\:}))" - IFS=$'\n' files_list=($(SHELL=zsh bun getcompletes j)) - - main_commands=( - 'run\:"Run JavaScript with Bun, a package.json script, or a bin" ' - 'test\:"Run unit tests with Bun" ' - 'x\:"Install and execute a package bin (bunx)" ' - 'repl\:"Start a REPL session with Bun" ' - 'init\:"Start an empty Bun project from a blank template" ' - 'create\:"Create a new project from a template (bun c)" ' - 'install\:"Install dependencies for a package.json (bun i)" ' - 'add\:"Add a dependency to package.json (bun a)" ' - 'remove\:"Remove a dependency from package.json (bun rm)" ' - 'update\:"Update outdated dependencies & save to package.json" ' - 'outdated\:"Display the latest versions of outdated dependencies" ' - 'link\:"Link an npm package globally" ' - 'unlink\:"Globally unlink an npm package" ' - 'pm\:"More commands for managing packages" ' - 'build\:"Bundle TypeScript & JavaScript into a single file" ' - 'upgrade\:"Get the latest version of bun" ' - 'help\:"Show all supported flags and commands" ' - ) - main_commands=($main_commands) - _alternative "$scripts" "args:command:(($main_commands))" "files:files:(($files_list))" - - ;; - args) - case $line[1] in - add|a) - _bun_add_completion - - ;; - unlink) - _bun_unlink_completion - - ;; - link) - _bun_link_completion - - ;; - bun) - _bun_bun_completion - - ;; - init) - _bun_init_completion - - ;; - create|c) - _bun_create_completion - - ;; - x) - _arguments -s -C \ - '1: :->cmd' \ - '2: :->cmd2' \ - '*: :->args' && - ret=0 - ;; - pm) - _bun_pm_completion - - ;; - install|i) - _bun_install_completion - - ;; - remove|rm) - _bun_remove_completion - - ;; - run) - _bun_run_completion - - ;; - upgrade) - _bun_upgrade_completion - - ;; - repl) - _bun_repl_completion - - ;; - build) - _bun_build_completion - - ;; - update) - _bun_update_completion - - ;; - outdated) - _bun_outdated_completion - - ;; - 'test') - _bun_test_completion - - ;; - help) - # ---- Command: help - _arguments -s -C \ - '1: :->cmd' \ - '2: :->cmd2' \ - '*: :->args' && - ret=0 - - case $state in - cmd2) - curcontext="${curcontext%:*:*}:bun-grouped" - _alternative "args:command:(($main_commands))" - - ;; - args) - case $line[2] in - add) - _bun_add_completion - - ;; - unlink) - _bun_unlink_completion - - ;; - link) - _bun_link_completion - - ;; - bun) - _bun_bun_completion - - ;; - init) - _bun_init_completion - - ;; - create) - _bun_create_completion - - ;; - x) - _arguments -s -C \ - '1: :->cmd' \ - '2: :->cmd2' \ - '*: :->args' && - ret=0 - ;; - pm) - _bun_pm_completion - - ;; - install) - _bun_install_completion - - ;; - remove) - _bun_remove_completion - - ;; - run) - _bun_run_completion - - ;; - upgrade) - _bun_upgrade_completion - - ;; - repl) - _bun_repl_completion - - ;; - build) - _bun_build_completion - - ;; - update) - _bun_update_completion - - ;; - outdated) - _bun_outdated_completion - - ;; - 'test') - _bun_test_completion - - ;; - esac - - ;; - esac - - ;; - esac - - ;; - esac -} - -_bun_list_bunfig_toml() { - # _alternative "files:file:_files -g '*.toml'" - _files -} - -_bun_run_param_script_completion() { - local -a scripts_list - IFS=$'\n' scripts_list=($(SHELL=zsh bun getcompletes s)) - IFS=$'\n' bins=($(SHELL=zsh bun getcompletes b)) - - _alternative "scripts:scripts:((${scripts_list//:/\\\\:}))" - _alternative "bin:bin:((${bins//:/\\\\:}))" - _alternative "files:file:_files -g '*.(js|ts|jsx|tsx|wasm)'" -} - -_bun_link_param_package_completion() { - # Read packages from ~/.bun/install/global/node_modules - install_env=$BUN_INSTALL - install_dir=${(P)install_env:-$HOME/.bun} - global_node_modules=$install_dir/install/global/node_modules - - local -a packages_full_path=(${global_node_modules}/*(N)) - packages=$(echo $packages_full_path | tr ' ' '\n' | xargs basename) - _alternative "dirs:directory:(($packages))" -} - -_bun_remove_param_package_completion() { - if ! command -v jq &>/dev/null; then - return - fi - - # TODO: move to "bun getcompletes" - if [ -f "package.json" ]; then - local dependencies=$(jq -r '.dependencies | keys[]' package.json) - local dev_dependencies=$(jq -r '.devDependencies | keys[]' package.json) - _alternative "deps:dependency:(($dependencies))" - _alternative "deps:dependency:(($dev_dependencies))" - fi -} - -_bun_test_param_script_completion() { - local -a scripts_list - - _alternative "files:file:_files -g '*(_|.)(test|spec).(js|ts|jsx|tsx)'" -} - -_set_remove() { - comm -23 <(echo $1 | sort | tr " " "\n") <(echo $2 | sort | tr " " "\n") 2>/dev/null -} - -_bun_add_param_package_completion() { - - IFS=$'\n' inexact=($(history -n bun | grep -E "^bun add " | cut -c 9- | uniq)) - IFS=$'\n' exact=($($inexact | grep -E "^$words[$CURRENT]")) - IFS=$'\n' packages=($(SHELL=zsh bun getcompletes a $words[$CURRENT])) - - to_print=$inexact - if [ ! -z "$exact" -a "$exact" != " " ]; then - to_print=$exact - fi - - if [ ! -z "$to_print" -a "$to_print" != " " ]; then - if [ ! -z "$packages" -a "$packages" != " " ]; then - _describe -1 -t to_print 'History' to_print - _describe -1 -t packages "Popular" packages - return - fi - - _describe -1 -t to_print 'History' to_print - return - fi - - if [ ! -z "$packages" -a "$packages" != " " ]; then - _describe -1 -t packages "Popular" packages - return - fi - -} - -__bun_dynamic_comp() { - local comp="" - - for arg in scripts; do - local line - while read -r line; do - local name="$line" - local desc="$line" - name="${name%$'\t'*}" - desc="${desc/*$'\t'/}" - echo - done <<<"$arg" - done - - return $comp -} - -if ! command -v compinit >/dev/null; then - autoload -U compinit && compinit -fi - -compdef _bun bun diff --git a/.bun-local/bin/bun b/.bun-local/bin/bun deleted file mode 100755 index 7c4664d9aec1..000000000000 Binary files a/.bun-local/bin/bun and /dev/null differ diff --git a/.bun-local/bin/bunx b/.bun-local/bin/bunx deleted file mode 120000 index df224c532938..000000000000 --- a/.bun-local/bin/bunx +++ /dev/null @@ -1 +0,0 @@ -/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/.bun-local/bin/bun \ No newline at end of file diff --git a/.env.example b/.env.example index 20fc3186b8ff..067aad9cc6ea 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,5 @@ -# Optional: T3 Cloud source builds -# Leave these unset to disable optional T3 Cloud features in local source builds. +# Optional: T3 Connect source builds +# Leave these unset to disable optional T3 Connect features in local source builds. # Release builds inject their public values at build time. Do not add server-side # secrets to this file. @@ -10,3 +10,8 @@ # Get this from your relay deployment. `infra/relay` deploys update it automatically. # T3CODE_RELAY_URL=https://relay.example.com + +# Public, ingest-only mobile OpenTelemetry configuration. +# T3CODE_MOBILE_OTLP_TRACES_URL=https://api.axiom.co/v1/traces +# T3CODE_MOBILE_OTLP_TRACES_DATASET=t3-code-mobile-traces-dev +# T3CODE_MOBILE_OTLP_TRACES_TOKEN=xaat-... diff --git a/.github/workflows/deploy-relay.yml b/.github/workflows/deploy-relay.yml index 1f777ed2911c..94d4af17e41a 100644 --- a/.github/workflows/deploy-relay.yml +++ b/.github/workflows/deploy-relay.yml @@ -1,4 +1,4 @@ -name: Deploy T3 Cloud relay +name: Deploy T3 Connect relay on: push: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 67e6aeb51adf..e1fb92163bfd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -167,7 +167,7 @@ jobs: --github-output relay_public_config: - name: Resolve T3 Cloud public config + name: Resolve T3 Connect public config needs: preflight if: ${{ !failure() && !cancelled() && needs.preflight.result == 'success' }} runs-on: blacksmith-8vcpu-ubuntu-2404 diff --git a/.t3-home/caches/claudeAgent.json b/.t3-home/caches/claudeAgent.json deleted file mode 100644 index f3bf9ead4215..000000000000 --- a/.t3-home/caches/claudeAgent.json +++ /dev/null @@ -1,257 +0,0 @@ -{ - "displayName": "Claude", - "showInteractionModeToggle": true, - "enabled": true, - "installed": false, - "version": null, - "status": "error", - "auth": { - "status": "unknown" - }, - "checkedAt": "2026-05-21T08:52:00.394Z", - "message": "Claude Agent CLI (`claude`) is not installed or not on PATH.", - "models": [ - { - "slug": "claude-opus-4-7", - "name": "Claude Opus 4.7", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "effort", - "label": "Reasoning", - "type": "select", - "options": [ - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium" - }, - { - "id": "high", - "label": "High" - }, - { - "id": "xhigh", - "label": "Extra High", - "isDefault": true - }, - { - "id": "max", - "label": "Max" - }, - { - "id": "ultrathink", - "label": "Ultrathink" - } - ], - "currentValue": "xhigh", - "promptInjectedValues": ["ultrathink"] - }, - { - "id": "contextWindow", - "label": "Context Window", - "type": "select", - "options": [ - { - "id": "200k", - "label": "200k", - "isDefault": true - }, - { - "id": "1m", - "label": "1M" - } - ], - "currentValue": "200k" - } - ] - } - }, - { - "slug": "claude-opus-4-6", - "name": "Claude Opus 4.6", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "effort", - "label": "Reasoning", - "type": "select", - "options": [ - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium" - }, - { - "id": "high", - "label": "High", - "isDefault": true - }, - { - "id": "max", - "label": "Max" - }, - { - "id": "ultrathink", - "label": "Ultrathink" - } - ], - "currentValue": "high", - "promptInjectedValues": ["ultrathink"] - }, - { - "id": "fastMode", - "label": "Fast Mode", - "type": "boolean" - }, - { - "id": "contextWindow", - "label": "Context Window", - "type": "select", - "options": [ - { - "id": "200k", - "label": "200k", - "isDefault": true - }, - { - "id": "1m", - "label": "1M" - } - ], - "currentValue": "200k" - } - ] - } - }, - { - "slug": "claude-opus-4-5", - "name": "Claude Opus 4.5", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "effort", - "label": "Reasoning", - "type": "select", - "options": [ - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium" - }, - { - "id": "high", - "label": "High", - "isDefault": true - }, - { - "id": "max", - "label": "Max" - } - ], - "currentValue": "high" - }, - { - "id": "fastMode", - "label": "Fast Mode", - "type": "boolean" - } - ] - } - }, - { - "slug": "claude-sonnet-4-6", - "name": "Claude Sonnet 4.6", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "effort", - "label": "Reasoning", - "type": "select", - "options": [ - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium" - }, - { - "id": "high", - "label": "High", - "isDefault": true - }, - { - "id": "ultrathink", - "label": "Ultrathink" - } - ], - "currentValue": "high", - "promptInjectedValues": ["ultrathink"] - }, - { - "id": "contextWindow", - "label": "Context Window", - "type": "select", - "options": [ - { - "id": "200k", - "label": "200k", - "isDefault": true - }, - { - "id": "1m", - "label": "1M" - } - ], - "currentValue": "200k" - } - ] - } - }, - { - "slug": "claude-haiku-4-5", - "name": "Claude Haiku 4.5", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "thinking", - "label": "Thinking", - "type": "boolean" - } - ] - } - } - ], - "slashCommands": [], - "skills": [], - "instanceId": "claudeAgent", - "driver": "claudeAgent", - "continuation": { - "groupKey": "claude:home:/Users/harrydawson" - }, - "versionAdvisory": { - "status": "unknown", - "currentVersion": null, - "latestVersion": null, - "updateCommand": "npm install -g @anthropic-ai/claude-code@latest", - "canUpdate": true, - "checkedAt": "2026-05-21T08:52:00.394Z", - "message": null - } -} diff --git a/.t3-home/caches/codex.json b/.t3-home/caches/codex.json deleted file mode 100644 index a66fb8f3db1f..000000000000 --- a/.t3-home/caches/codex.json +++ /dev/null @@ -1,463 +0,0 @@ -{ - "displayName": "Codex", - "showInteractionModeToggle": true, - "enabled": true, - "installed": true, - "version": "0.130.0", - "status": "ready", - "auth": { - "status": "authenticated", - "type": "chatgpt", - "label": "ChatGPT Plus Subscription", - "email": "hdawson97@gmail.com" - }, - "checkedAt": "2026-05-21T08:52:01.153Z", - "models": [ - { - "slug": "gpt-5.5", - "name": "GPT-5.5", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "reasoningEffort", - "label": "Reasoning", - "type": "select", - "options": [ - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - }, - { - "id": "xhigh", - "label": "Extra High" - } - ], - "currentValue": "medium" - }, - { - "id": "fastMode", - "label": "Fast Mode", - "type": "boolean" - } - ] - } - }, - { - "slug": "gpt-5.4", - "name": "GPT-5.4", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "reasoningEffort", - "label": "Reasoning", - "type": "select", - "options": [ - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - }, - { - "id": "xhigh", - "label": "Extra High" - } - ], - "currentValue": "medium" - }, - { - "id": "fastMode", - "label": "Fast Mode", - "type": "boolean" - } - ] - } - }, - { - "slug": "gpt-5.4-mini", - "name": "GPT-5.4-Mini", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "reasoningEffort", - "label": "Reasoning", - "type": "select", - "options": [ - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - }, - { - "id": "xhigh", - "label": "Extra High" - } - ], - "currentValue": "medium" - } - ] - } - }, - { - "slug": "gpt-5.3-codex", - "name": "GPT-5.3-Codex", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "reasoningEffort", - "label": "Reasoning", - "type": "select", - "options": [ - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - }, - { - "id": "xhigh", - "label": "Extra High" - } - ], - "currentValue": "medium" - } - ] - } - }, - { - "slug": "gpt-5.2", - "name": "GPT-5.2", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "reasoningEffort", - "label": "Reasoning", - "type": "select", - "options": [ - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - }, - { - "id": "xhigh", - "label": "Extra High" - } - ], - "currentValue": "medium" - } - ] - } - } - ], - "slashCommands": [], - "skills": [ - { - "name": "caveman", - "path": "/Users/harrydawson/.agents/skills/caveman/SKILL.md", - "enabled": true, - "description": "Ultra-compressed communication mode. Cuts token usage ~75% by dropping filler, articles, and pleasantries while keeping full technical accuracy. Use when user says \"caveman mode\", \"talk like caveman\", \"use caveman\", \"less tokens\", \"be brief\", or invokes /caveman.", - "scope": "user" - }, - { - "name": "diagnose", - "path": "/Users/harrydawson/.agents/skills/diagnose/SKILL.md", - "enabled": true, - "description": "Disciplined diagnosis loop for hard bugs and performance regressions. Reproduce → minimise → hypothesise → instrument → fix → regression-test. Use when user says \"diagnose this\" / \"debug this\", reports a bug, says something is broken/throwing/failing, or describes a performance regression.", - "scope": "user" - }, - { - "name": "find-skills", - "path": "/Users/harrydawson/.agents/skills/find-skills/SKILL.md", - "enabled": true, - "description": "Helps users discover and install agent skills when they ask questions like \"how do I do X\", \"find a skill for X\", \"is there a skill that can...\", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.", - "scope": "user" - }, - { - "name": "github:gh-address-comments", - "path": "/Users/harrydawson/.codex/plugins/cache/openai-curated/github/0d4f5414/skills/gh-address-comments/SKILL.md", - "enabled": true, - "description": "Address actionable GitHub pull request review feedback. Use when the user wants to inspect unresolved review threads, requested changes, or inline review comments on a PR, then implement selected fixes. Use the GitHub app for PR metadata and flat comment reads, and use the bundled GraphQL script via `gh` whenever thread-level state, resolution status, or inline review context matters.", - "scope": "user", - "displayName": "Review Follow-up", - "shortDescription": "Address actionable PR feedback" - }, - { - "name": "github:gh-fix-ci", - "path": "/Users/harrydawson/.codex/plugins/cache/openai-curated/github/0d4f5414/skills/gh-fix-ci/SKILL.md", - "enabled": true, - "description": "Use when a user asks to debug or fix failing GitHub PR checks that run in GitHub Actions. Use the GitHub app from this plugin for PR metadata and patch context, and use `gh` for Actions check and log inspection before implementing any approved fix.", - "scope": "user", - "displayName": "CI Debug", - "shortDescription": "Debug failing GitHub Actions checks" - }, - { - "name": "github:github", - "path": "/Users/harrydawson/.codex/plugins/cache/openai-curated/github/0d4f5414/skills/github/SKILL.md", - "enabled": true, - "description": "Triage and orient GitHub repository, pull request, and issue work through the connected GitHub app. Use when the user asks for general GitHub help, wants PR or issue summaries, or needs repository context before choosing a more specific GitHub workflow.", - "scope": "user", - "displayName": "GitHub", - "shortDescription": "Inspect PRs, issues, CI, and publish flows" - }, - { - "name": "github:yeet", - "path": "/Users/harrydawson/.codex/plugins/cache/openai-curated/github/0d4f5414/skills/yeet/SKILL.md", - "enabled": true, - "description": "Publish local changes to GitHub by confirming scope, committing intentionally, pushing the branch, and opening a draft PR through the GitHub app from this plugin, with `gh` used only as a fallback where connector coverage is insufficient.", - "scope": "user", - "displayName": "Publish Changes", - "shortDescription": "Commit, push, and open a PR" - }, - { - "name": "gmail:gmail", - "path": "/Users/harrydawson/.codex/plugins/cache/openai-curated/gmail/0d4f5414/skills/gmail/SKILL.md", - "enabled": true, - "description": "Manage Gmail inbox triage, mailbox search, thread summaries, action extraction, reply drafting, and email forwarding through connected Gmail data. Use when the user wants to inspect a mailbox or thread, search email with Gmail query syntax, summarize messages, extract decisions and follow-ups, prepare replies or forwarded messages, or organize messages with explicit confirmation before send, archive, delete, or label actions.", - "scope": "user", - "displayName": "Gmail", - "shortDescription": "Summarize threads and draft replies" - }, - { - "name": "gmail:gmail-inbox-triage", - "path": "/Users/harrydawson/.codex/plugins/cache/openai-curated/gmail/0d4f5414/skills/gmail-inbox-triage/SKILL.md", - "enabled": true, - "description": "Triage a Gmail inbox into actionable buckets such as urgent, needs reply soon, waiting, and FYI using connected Gmail data. Use when the user asks to triage the inbox, rank what needs attention, find what still needs a reply, or separate important mail from noise.", - "scope": "user", - "displayName": "Inbox Triage", - "shortDescription": "Triage an inbox into action buckets" - }, - { - "name": "google-drive:google-docs", - "path": "/Users/harrydawson/.codex/plugins/cache/openai-curated/google-drive/0d4f5414/skills/google-docs/SKILL.md", - "enabled": true, - "description": "Documents-first net-new Google Docs creation plus connector-first Google Docs editing in local Codex plugin sessions, with target-document checks, connector-readback verification, and reference routing for formatting, citations, tables, and write-safety.", - "scope": "user", - "displayName": "Google Docs", - "shortDescription": "Read, edit, and create Google Docs files." - }, - { - "name": "google-drive:google-drive", - "path": "/Users/harrydawson/.codex/plugins/cache/openai-curated/google-drive/0d4f5414/skills/google-drive/SKILL.md", - "enabled": true, - "description": "Use connected Google Drive as the single entrypoint for Drive, Docs, Sheets, and Slides work. Use when the user wants to find, fetch, organize, share, export, copy, or delete Drive files, or summarize and edit Google Docs, Google Sheets, and Google Slides through one unified Google Drive plugin.", - "scope": "user", - "displayName": "Google Drive", - "shortDescription": "One entrypoint for Drive, Docs, Sheets, and Slides" - }, - { - "name": "google-drive:google-drive-comments", - "path": "/Users/harrydawson/.codex/plugins/cache/openai-curated/google-drive/0d4f5414/skills/google-drive-comments/SKILL.md", - "enabled": true, - "description": "Write, reply to, and resolve Google Drive comments on Docs, Sheets, Slides, and Drive files with evidence-backed location context. Use when the user asks to leave comments, review a file with comments, respond to comment threads, or resolve Drive comments.", - "scope": "user", - "displayName": "Google Drive Comments", - "shortDescription": "Write, reply to, and resolve Drive comments" - }, - { - "name": "google-drive:google-sheets", - "path": "/Users/harrydawson/.codex/plugins/cache/openai-curated/google-drive/0d4f5414/skills/google-sheets/SKILL.md", - "enabled": true, - "description": "Analyze and edit connected Google Sheets with range precision. Use when the user wants to create Google Sheets, find a spreadsheet, inspect tabs or ranges, search rows, plan formulas, create or repair charts, clean or restructure tables, write concise summaries, or make explicit cell-range updates.", - "scope": "user", - "displayName": "Google Sheets", - "shortDescription": "Find sheets, inspect ranges, and plan batch updates" - }, - { - "name": "google-drive:google-slides", - "path": "/Users/harrydawson/.codex/plugins/cache/openai-curated/google-drive/0d4f5414/skills/google-slides/SKILL.md", - "enabled": true, - "description": "Google Slides work for finding, reading, summarizing, creating, importing, visual cleanup, template migration, structural repair, and content edits in native Slides decks.", - "scope": "user", - "displayName": "Google Slides", - "shortDescription": "Inspect decks and handle Slides content edits" - }, - { - "name": "grill-me", - "path": "/Users/harrydawson/.agents/skills/grill-me/SKILL.md", - "enabled": true, - "description": "Interview the user relentlessly about a plan or design until reaching shared understanding, resolving each branch of the decision tree. Use when user wants to stress-test a plan, get grilled on their design, or mentions \"grill me\".", - "scope": "user" - }, - { - "name": "grill-with-docs", - "path": "/Users/harrydawson/.agents/skills/grill-with-docs/SKILL.md", - "enabled": true, - "description": "Grilling session that challenges your plan against the existing domain model, sharpens terminology, and updates documentation (CONTEXT.md, ADRs) inline as decisions crystallise. Use when user wants to stress-test a plan against their project's language and documented decisions.", - "scope": "user" - }, - { - "name": "handoff", - "path": "/Users/harrydawson/.agents/skills/handoff/SKILL.md", - "enabled": true, - "description": "Compact the current conversation into a handoff document for another agent to pick up.", - "scope": "user" - }, - { - "name": "improve-codebase-architecture", - "path": "/Users/harrydawson/.agents/skills/improve-codebase-architecture/SKILL.md", - "enabled": true, - "description": "Find deepening opportunities in a codebase, informed by the domain language in CONTEXT.md and the decisions in docs/adr/. Use when the user wants to improve architecture, find refactoring opportunities, consolidate tightly-coupled modules, or make a codebase more testable and AI-navigable.", - "scope": "user" - }, - { - "name": "prototype", - "path": "/Users/harrydawson/.agents/skills/prototype/SKILL.md", - "enabled": true, - "description": "Build a throwaway prototype to flesh out a design before committing to it. Routes between two branches — a runnable terminal app for state/business-logic questions, or several radically different UI variations toggleable from one route. Use when the user wants to prototype, sanity-check a data model or state machine, mock up a UI, explore design options, or says \"prototype this\", \"let me play with it\", \"try a few designs\".", - "scope": "user" - }, - { - "name": "setup-matt-pocock-skills", - "path": "/Users/harrydawson/.agents/skills/setup-matt-pocock-skills/SKILL.md", - "enabled": true, - "description": "Sets up an `## Agent skills` block in AGENTS.md/CLAUDE.md and `docs/agents/` so the engineering skills know this repo's issue tracker (GitHub or local markdown), triage label vocabulary, and domain doc layout. Run before first use of `to-issues`, `to-prd`, `triage`, `diagnose`, `tdd`, `improve-codebase-architecture`, or `zoom-out` — or if those skills appear to be missing context about the issue tracker, triage labels, or domain docs.", - "scope": "user" - }, - { - "name": "tdd", - "path": "/Users/harrydawson/.agents/skills/tdd/SKILL.md", - "enabled": true, - "description": "Test-driven development with red-green-refactor loop. Use when user wants to build features or fix bugs using TDD, mentions \"red-green-refactor\", wants integration tests, or asks for test-first development.", - "scope": "user" - }, - { - "name": "to-issues", - "path": "/Users/harrydawson/.agents/skills/to-issues/SKILL.md", - "enabled": true, - "description": "Break a plan, spec, or PRD into independently-grabbable issues on the project issue tracker using tracer-bullet vertical slices. Use when user wants to convert a plan into issues, create implementation tickets, or break down work into issues.", - "scope": "user" - }, - { - "name": "to-prd", - "path": "/Users/harrydawson/.agents/skills/to-prd/SKILL.md", - "enabled": true, - "description": "Turn the current conversation context into a PRD and publish it to the project issue tracker. Use when user wants to create a PRD from the current context.", - "scope": "user" - }, - { - "name": "triage", - "path": "/Users/harrydawson/.agents/skills/triage/SKILL.md", - "enabled": true, - "description": "Triage issues through a state machine driven by triage roles. Use when user wants to create an issue, triage issues, review incoming bugs or feature requests, prepare issues for an AFK agent, or manage issue workflow.", - "scope": "user" - }, - { - "name": "write-a-skill", - "path": "/Users/harrydawson/.agents/skills/write-a-skill/SKILL.md", - "enabled": true, - "description": "Create new agent skills with proper structure, progressive disclosure, and bundled resources. Use when user wants to create, write, or build a new skill.", - "scope": "user" - }, - { - "name": "zoom-out", - "path": "/Users/harrydawson/.agents/skills/zoom-out/SKILL.md", - "enabled": true, - "description": "Tell the agent to zoom out and give broader context or a higher-level perspective. Use when you're unfamiliar with a section of code or need to understand how it fits into the bigger picture.", - "scope": "user" - }, - { - "name": "imagegen", - "path": "/Users/harrydawson/.codex/skills/.system/imagegen/SKILL.md", - "enabled": true, - "description": "Generate or edit raster images when the task benefits from AI-created bitmap visuals such as photos, illustrations, textures, sprites, mockups, or transparent-background cutouts. Use when Codex should create a brand-new image, transform an existing image, or derive visual variants from references, and the output should be a bitmap asset rather than repo-native code or vector. Do not use when the task is better handled by editing existing SVG/vector/code-native assets, extending an established icon or logo system, or building the visual directly in HTML/CSS/canvas.", - "scope": "system", - "displayName": "Image Gen", - "shortDescription": "Generate or edit images for websites, games, and more" - }, - { - "name": "openai-docs", - "path": "/Users/harrydawson/.codex/skills/.system/openai-docs/SKILL.md", - "enabled": true, - "description": "Use when the user asks how to build with OpenAI products or APIs and needs up-to-date official documentation with citations, help choosing the latest model for a use case, or model upgrade and prompt-upgrade guidance; prioritize OpenAI docs MCP tools, use bundled references only as helper context, and restrict any fallback browsing to official OpenAI domains.", - "scope": "system", - "displayName": "OpenAI Docs", - "shortDescription": "Reference docs, choose models, and migrate OpenAI API integrations" - }, - { - "name": "plugin-creator", - "path": "/Users/harrydawson/.codex/skills/.system/plugin-creator/SKILL.md", - "enabled": true, - "description": "Create and scaffold plugin directories for Codex with a required `.codex-plugin/plugin.json`, optional plugin folders/files, and baseline placeholders you can edit before publishing or testing. Use when Codex needs to create a new local plugin, add optional plugin structure, or generate or update repo-root `.agents/plugins/marketplace.json` entries for plugin ordering and availability metadata.", - "scope": "system", - "displayName": "Plugin Creator", - "shortDescription": "Scaffold plugins and marketplace entries" - }, - { - "name": "skill-creator", - "path": "/Users/harrydawson/.codex/skills/.system/skill-creator/SKILL.md", - "enabled": true, - "description": "Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Codex's capabilities with specialized knowledge, workflows, or tool integrations.", - "scope": "system", - "displayName": "Skill Creator", - "shortDescription": "Create or update a skill" - }, - { - "name": "skill-installer", - "path": "/Users/harrydawson/.codex/skills/.system/skill-installer/SKILL.md", - "enabled": true, - "description": "Install Codex skills into $CODEX_HOME/skills from a curated list or a GitHub repo path. Use when a user asks to list installable skills, install a curated skill, or install a skill from another repo (including private repos).", - "scope": "system", - "displayName": "Skill Installer", - "shortDescription": "Install curated skills from openai/skills or other repos" - } - ], - "instanceId": "codex", - "driver": "codex", - "continuation": { - "groupKey": "codex:home:/Users/harrydawson/.codex" - }, - "versionAdvisory": { - "status": "behind_latest", - "currentVersion": "0.130.0", - "latestVersion": "0.132.0", - "updateCommand": "brew upgrade codex", - "canUpdate": true, - "checkedAt": "2026-05-21T08:52:01.548Z", - "message": "Install the update now or review provider settings." - } -} diff --git a/.t3-home/caches/cursor.json b/.t3-home/caches/cursor.json deleted file mode 100644 index c7a110768c18..000000000000 --- a/.t3-home/caches/cursor.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "displayName": "Cursor", - "badgeLabel": "Early Access", - "showInteractionModeToggle": true, - "enabled": false, - "installed": false, - "version": null, - "status": "disabled", - "auth": { - "status": "unknown" - }, - "checkedAt": "2026-05-21T08:52:00.401Z", - "message": "Cursor is disabled in T3 Code settings.", - "models": [], - "slashCommands": [], - "skills": [], - "instanceId": "cursor", - "driver": "cursor", - "continuation": { - "groupKey": "cursor:instance:cursor" - }, - "versionAdvisory": { - "status": "unknown", - "currentVersion": null, - "latestVersion": null, - "updateCommand": "agent update", - "canUpdate": true, - "checkedAt": "2026-05-21T08:52:00.401Z", - "message": null - } -} diff --git a/.t3-home/caches/opencode.json b/.t3-home/caches/opencode.json deleted file mode 100644 index ad3e90c2b198..000000000000 --- a/.t3-home/caches/opencode.json +++ /dev/null @@ -1,3879 +0,0 @@ -{ - "displayName": "OpenCode", - "showInteractionModeToggle": false, - "enabled": true, - "installed": true, - "version": "1.15.3", - "status": "ready", - "auth": { - "status": "authenticated", - "type": "opencode" - }, - "checkedAt": "2026-05-21T08:52:10.773Z", - "message": "2 upstream providers connected through OpenCode.", - "models": [ - { - "slug": "opencode/big-pickle", - "name": "Big Pickle", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/claude-haiku-4-5", - "name": "Claude Haiku 4.5", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "high", - "label": "High", - "isDefault": true - }, - { - "id": "max", - "label": "Max" - } - ], - "currentValue": "high" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/claude-opus-4-1", - "name": "Claude Opus 4.1", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "high", - "label": "High", - "isDefault": true - }, - { - "id": "max", - "label": "Max" - } - ], - "currentValue": "high" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/claude-opus-4-5", - "name": "Claude Opus 4.5", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/claude-opus-4-6", - "name": "Claude Opus 4.6", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - }, - { - "id": "max", - "label": "Max" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/claude-opus-4-7", - "name": "Claude Opus 4.7", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - }, - { - "id": "xhigh", - "label": "Xhigh" - }, - { - "id": "max", - "label": "Max" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/claude-sonnet-4", - "name": "Claude Sonnet 4", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "high", - "label": "High", - "isDefault": true - }, - { - "id": "max", - "label": "Max" - } - ], - "currentValue": "high" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/claude-sonnet-4-5", - "name": "Claude Sonnet 4.5", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "high", - "label": "High", - "isDefault": true - }, - { - "id": "max", - "label": "Max" - } - ], - "currentValue": "high" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/claude-sonnet-4-6", - "name": "Claude Sonnet 4.6", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - }, - { - "id": "max", - "label": "Max" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/deepseek-v4-flash-free", - "name": "DeepSeek V4 Flash Free", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - }, - { - "id": "max", - "label": "Max" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/gemini-3-flash", - "name": "Gemini 3 Flash", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "minimal", - "label": "Minimal" - }, - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/gemini-3.1-pro", - "name": "Gemini 3.1 Pro Preview", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/gemini-3.5-flash", - "name": "Gemini 3.5 Flash", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "minimal", - "label": "Minimal" - }, - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/glm-5", - "name": "GLM-5", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/glm-5.1", - "name": "GLM-5.1", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "openai/gpt-5.1-codex-high", - "name": "GPT 5.1 Codex High (OAuth)", - "subProvider": "OpenAI", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "openai/gpt-5.1-codex-low", - "name": "GPT 5.1 Codex Low (OAuth)", - "subProvider": "OpenAI", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "openai/gpt-5.1-codex-max-xhigh", - "name": "GPT 5.1 Codex Max Extra High (OAuth)", - "subProvider": "OpenAI", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "openai/gpt-5.1-codex-max-high", - "name": "GPT 5.1 Codex Max High (OAuth)", - "subProvider": "OpenAI", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "openai/gpt-5.1-codex-max-low", - "name": "GPT 5.1 Codex Max Low (OAuth)", - "subProvider": "OpenAI", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "openai/gpt-5.1-codex-max-medium", - "name": "GPT 5.1 Codex Max Medium (OAuth)", - "subProvider": "OpenAI", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "openai/gpt-5.1-codex-medium", - "name": "GPT 5.1 Codex Medium (OAuth)", - "subProvider": "OpenAI", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "openai/gpt-5.1-codex-mini-high", - "name": "GPT 5.1 Codex Mini High (OAuth)", - "subProvider": "OpenAI", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "openai/gpt-5.1-codex-mini-medium", - "name": "GPT 5.1 Codex Mini Medium (OAuth)", - "subProvider": "OpenAI", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "openai/gpt-5.1-high", - "name": "GPT 5.1 High (OAuth)", - "subProvider": "OpenAI", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "openai/gpt-5.1-low", - "name": "GPT 5.1 Low (OAuth)", - "subProvider": "OpenAI", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "openai/gpt-5.1-medium", - "name": "GPT 5.1 Medium (OAuth)", - "subProvider": "OpenAI", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "openai/gpt-5.1-none", - "name": "GPT 5.1 None (OAuth)", - "subProvider": "OpenAI", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "openai/gpt-5.2-codex-xhigh", - "name": "GPT 5.2 Codex Extra High (OAuth)", - "subProvider": "OpenAI", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "openai/gpt-5.2-codex-high", - "name": "GPT 5.2 Codex High (OAuth)", - "subProvider": "OpenAI", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "openai/gpt-5.2-codex-low", - "name": "GPT 5.2 Codex Low (OAuth)", - "subProvider": "OpenAI", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "openai/gpt-5.2-codex-medium", - "name": "GPT 5.2 Codex Medium (OAuth)", - "subProvider": "OpenAI", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "openai/gpt-5.2-xhigh", - "name": "GPT 5.2 Extra High (OAuth)", - "subProvider": "OpenAI", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "openai/gpt-5.2-high", - "name": "GPT 5.2 High (OAuth)", - "subProvider": "OpenAI", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "openai/gpt-5.2-low", - "name": "GPT 5.2 Low (OAuth)", - "subProvider": "OpenAI", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "openai/gpt-5.2-medium", - "name": "GPT 5.2 Medium (OAuth)", - "subProvider": "OpenAI", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "openai/gpt-5.2-none", - "name": "GPT 5.2 None (OAuth)", - "subProvider": "OpenAI", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/gpt-5", - "name": "GPT-5", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "minimal", - "label": "Minimal" - }, - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/gpt-5-codex", - "name": "GPT-5 Codex", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/gpt-5-nano", - "name": "GPT-5 Nano", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "minimal", - "label": "Minimal" - }, - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/gpt-5.1", - "name": "GPT-5.1", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "none", - "label": "None" - }, - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/gpt-5.1-codex", - "name": "GPT-5.1 Codex", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/gpt-5.1-codex-max", - "name": "GPT-5.1 Codex Max", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - }, - { - "id": "xhigh", - "label": "Xhigh" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/gpt-5.1-codex-mini", - "name": "GPT-5.1 Codex Mini", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "openai/gpt-5.2", - "name": "GPT-5.2", - "subProvider": "OpenAI", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "none", - "label": "None" - }, - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - }, - { - "id": "xhigh", - "label": "Xhigh" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/gpt-5.2", - "name": "GPT-5.2", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "none", - "label": "None" - }, - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - }, - { - "id": "xhigh", - "label": "Xhigh" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/gpt-5.2-codex", - "name": "GPT-5.2 Codex", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - }, - { - "id": "xhigh", - "label": "Xhigh" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "openai/gpt-5.3-codex", - "name": "GPT-5.3 Codex", - "subProvider": "OpenAI", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "none", - "label": "None" - }, - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - }, - { - "id": "xhigh", - "label": "Xhigh" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/gpt-5.3-codex", - "name": "GPT-5.3 Codex", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "none", - "label": "None" - }, - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - }, - { - "id": "xhigh", - "label": "Xhigh" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "openai/gpt-5.3-codex-spark", - "name": "GPT-5.3 Codex Spark", - "subProvider": "OpenAI", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "none", - "label": "None" - }, - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - }, - { - "id": "xhigh", - "label": "Xhigh" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/gpt-5.3-codex-spark", - "name": "GPT-5.3 Codex Spark", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "none", - "label": "None" - }, - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - }, - { - "id": "xhigh", - "label": "Xhigh" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "openai/gpt-5.4", - "name": "GPT-5.4", - "subProvider": "OpenAI", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "none", - "label": "None" - }, - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - }, - { - "id": "xhigh", - "label": "Xhigh" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/gpt-5.4", - "name": "GPT-5.4", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "none", - "label": "None" - }, - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - }, - { - "id": "xhigh", - "label": "Xhigh" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "openai/gpt-5.4-fast", - "name": "GPT-5.4 Fast", - "subProvider": "OpenAI", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "none", - "label": "None" - }, - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - }, - { - "id": "xhigh", - "label": "Xhigh" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "openai/gpt-5.4-mini", - "name": "GPT-5.4 mini", - "subProvider": "OpenAI", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "none", - "label": "None" - }, - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - }, - { - "id": "xhigh", - "label": "Xhigh" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/gpt-5.4-mini", - "name": "GPT-5.4 Mini", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "none", - "label": "None" - }, - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - }, - { - "id": "xhigh", - "label": "Xhigh" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "openai/gpt-5.4-mini-fast", - "name": "GPT-5.4 mini Fast", - "subProvider": "OpenAI", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "none", - "label": "None" - }, - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - }, - { - "id": "xhigh", - "label": "Xhigh" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/gpt-5.4-nano", - "name": "GPT-5.4 Nano", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "none", - "label": "None" - }, - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - }, - { - "id": "xhigh", - "label": "Xhigh" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/gpt-5.4-pro", - "name": "GPT-5.4 Pro", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - }, - { - "id": "xhigh", - "label": "Xhigh" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "openai/gpt-5.5", - "name": "GPT-5.5", - "subProvider": "OpenAI", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "none", - "label": "None" - }, - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - }, - { - "id": "xhigh", - "label": "Xhigh" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/gpt-5.5", - "name": "GPT-5.5", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "none", - "label": "None" - }, - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - }, - { - "id": "xhigh", - "label": "Xhigh" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "openai/gpt-5.5-fast", - "name": "GPT-5.5 Fast", - "subProvider": "OpenAI", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "none", - "label": "None" - }, - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - }, - { - "id": "xhigh", - "label": "Xhigh" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "openai/gpt-5.5-pro", - "name": "GPT-5.5 Pro", - "subProvider": "OpenAI", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - }, - { - "id": "xhigh", - "label": "Xhigh" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/gpt-5.5-pro", - "name": "GPT-5.5 Pro", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - }, - { - "id": "xhigh", - "label": "Xhigh" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/grok-build-0.1", - "name": "Grok Build 0.1", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/kimi-k2.5", - "name": "Kimi K2.5", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/kimi-k2.6", - "name": "Kimi K2.6", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/minimax-m2.5", - "name": "MiniMax M2.5", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/minimax-m2.7", - "name": "MiniMax M2.7", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/nemotron-3-super-free", - "name": "Nemotron 3 Super Free", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "variant", - "label": "Variant", - "type": "select", - "options": [ - { - "id": "low", - "label": "Low" - }, - { - "id": "medium", - "label": "Medium", - "isDefault": true - }, - { - "id": "high", - "label": "High" - } - ], - "currentValue": "medium" - }, - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/qwen3.5-plus", - "name": "Qwen3.5 Plus", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/qwen3.6-plus", - "name": "Qwen3.6 Plus", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - }, - { - "slug": "opencode/qwen3.6-plus-free", - "name": "Qwen3.6 Plus Free", - "subProvider": "OpenCode Zen", - "isCustom": false, - "capabilities": { - "optionDescriptors": [ - { - "id": "agent", - "label": "Agent", - "type": "select", - "options": [ - { - "id": "build", - "label": "Build", - "isDefault": true - }, - { - "id": "learn", - "label": "Learn" - }, - { - "id": "learn-lite", - "label": "Learn Lite" - }, - { - "id": "plan", - "label": "Plan" - }, - { - "id": "teacher", - "label": "Teacher" - } - ], - "currentValue": "build" - } - ] - } - } - ], - "slashCommands": [], - "skills": [], - "instanceId": "opencode", - "driver": "opencode", - "continuation": { - "groupKey": "opencode:instance:opencode" - }, - "versionAdvisory": { - "status": "behind_latest", - "currentVersion": "1.15.3", - "latestVersion": "1.15.6", - "updateCommand": "opencode upgrade", - "canUpdate": true, - "checkedAt": "2026-05-21T08:52:12.807Z", - "message": "Install the update now or review provider settings." - } -} diff --git a/.t3-home/dev/environment-id b/.t3-home/dev/environment-id deleted file mode 100644 index 7905c47bc34b..000000000000 --- a/.t3-home/dev/environment-id +++ /dev/null @@ -1 +0,0 @@ -c3c533c1-415d-4b3b-ab05-63bdf7135dc7 diff --git a/.t3-home/dev/keybindings.json b/.t3-home/dev/keybindings.json deleted file mode 100644 index 4aa0e6ac1113..000000000000 --- a/.t3-home/dev/keybindings.json +++ /dev/null @@ -1,144 +0,0 @@ -[ - { - "key": "mod+j", - "command": "terminal.toggle" - }, - { - "key": "mod+d", - "command": "terminal.split", - "when": "terminalFocus" - }, - { - "key": "mod+n", - "command": "terminal.new", - "when": "terminalFocus" - }, - { - "key": "mod+w", - "command": "terminal.close", - "when": "terminalFocus" - }, - { - "key": "mod+d", - "command": "diff.toggle", - "when": "!terminalFocus" - }, - { - "key": "mod+k", - "command": "commandPalette.toggle", - "when": "!terminalFocus" - }, - { - "key": "mod+n", - "command": "chat.new", - "when": "!terminalFocus" - }, - { - "key": "mod+shift+o", - "command": "chat.new", - "when": "!terminalFocus" - }, - { - "key": "mod+shift+n", - "command": "chat.newLocal", - "when": "!terminalFocus" - }, - { - "key": "mod+shift+m", - "command": "modelPicker.toggle", - "when": "!terminalFocus" - }, - { - "key": "mod+o", - "command": "editor.openFavorite" - }, - { - "key": "mod+shift+[", - "command": "thread.previous" - }, - { - "key": "mod+shift+]", - "command": "thread.next" - }, - { - "key": "mod+1", - "command": "thread.jump.1" - }, - { - "key": "mod+2", - "command": "thread.jump.2" - }, - { - "key": "mod+3", - "command": "thread.jump.3" - }, - { - "key": "mod+4", - "command": "thread.jump.4" - }, - { - "key": "mod+5", - "command": "thread.jump.5" - }, - { - "key": "mod+6", - "command": "thread.jump.6" - }, - { - "key": "mod+7", - "command": "thread.jump.7" - }, - { - "key": "mod+8", - "command": "thread.jump.8" - }, - { - "key": "mod+9", - "command": "thread.jump.9" - }, - { - "key": "mod+1", - "command": "modelPicker.jump.1", - "when": "modelPickerOpen" - }, - { - "key": "mod+2", - "command": "modelPicker.jump.2", - "when": "modelPickerOpen" - }, - { - "key": "mod+3", - "command": "modelPicker.jump.3", - "when": "modelPickerOpen" - }, - { - "key": "mod+4", - "command": "modelPicker.jump.4", - "when": "modelPickerOpen" - }, - { - "key": "mod+5", - "command": "modelPicker.jump.5", - "when": "modelPickerOpen" - }, - { - "key": "mod+6", - "command": "modelPicker.jump.6", - "when": "modelPickerOpen" - }, - { - "key": "mod+7", - "command": "modelPicker.jump.7", - "when": "modelPickerOpen" - }, - { - "key": "mod+8", - "command": "modelPicker.jump.8", - "when": "modelPickerOpen" - }, - { - "key": "mod+9", - "command": "modelPicker.jump.9", - "when": "modelPickerOpen" - } -] diff --git a/.t3-home/dev/logs/desktop.trace.ndjson b/.t3-home/dev/logs/desktop.trace.ndjson deleted file mode 100644 index 49c76f80ae57..000000000000 --- a/.t3-home/dev/logs/desktop.trace.ndjson +++ /dev/null @@ -1,300 +0,0 @@ -{"type":"effect-span","name":"makeDesktopBackendManager","traceId":"89162937465dd7ed21fdd25ffc90ba19","spanId":"3f9f56521ebf8493","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719002304875","endTimeUnixNano":"1779351719002428250","durationMs":0.123375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.sshPasswordPrompts.make","traceId":"40b86701badc374f5357123a5fda1758","spanId":"6d7f6fbd4b0ada8e","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719002932792","endTimeUnixNano":"1779351719002983709","durationMs":0.050917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ssh/tunnel.SshEnvironmentManager.make","traceId":"bfa8a360a5167f722c271dfeff1e21fd","spanId":"860dcc5cc0a7e949","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719003064875","endTimeUnixNano":"1779351719003157375","durationMs":0.0925,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.shellEnvironment.runCommandOutput","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"9a8f002a7a714bdd","parentSpanId":"a73a2025a0c20409","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719003700500","endTimeUnixNano":"1779351719274775125","durationMs":271.074625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.shellEnvironment.installPosixEnvironment","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"a73a2025a0c20409","parentSpanId":"1a698257de83a716","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719003595750","endTimeUnixNano":"1779351719275041709","durationMs":271.445959,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.shellEnvironment.installIntoProcess","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"1a698257de83a716","parentSpanId":"c4a8f6f0503d9f3e","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719003584000","endTimeUnixNano":"1779351719275053959","durationMs":271.469959,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.appIdentity.resolveUserDataPath","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"2cad9cdb9bb2607a","parentSpanId":"c4a8f6f0503d9f3e","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719275066500","endTimeUnixNano":"1779351719275245917","durationMs":0.179417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.settings.load","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"90f9162b00ba4ca4","parentSpanId":"c4a8f6f0503d9f3e","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719275904667","endTimeUnixNano":"1779351719276213209","durationMs":0.308542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.appIdentity.configure","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"d09365ad949b2d3a","parentSpanId":"c4a8f6f0503d9f3e","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719276227834","endTimeUnixNano":"1779351719467969750","durationMs":191.741916,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.lifecycle.register","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"1df71f533ffab481","parentSpanId":"c4a8f6f0503d9f3e","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719468051584","endTimeUnixNano":"1779351719468278959","durationMs":0.227375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.electron.whenReady","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"a0b5bd1e09f66660","parentSpanId":"c4a8f6f0503d9f3e","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719468309875","endTimeUnixNano":"1779351719468354584","durationMs":0.044709,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.appIdentity.configure","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"9112bebf2e1edd32","parentSpanId":"c4a8f6f0503d9f3e","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719468507500","endTimeUnixNano":"1779351719670195292","durationMs":201.687792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.menu.configure","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"284c6697feae26c4","parentSpanId":"c4a8f6f0503d9f3e","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719670240459","endTimeUnixNano":"1779351719671626875","durationMs":1.386416,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.electron.protocol.registerDesktopFileProtocol","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"bc44824370fd951e","parentSpanId":"c4a8f6f0503d9f3e","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719671641834","endTimeUnixNano":"1779351719671699459","durationMs":0.057625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.updates.configure","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"0d250ec59f531f70","parentSpanId":"c4a8f6f0503d9f3e","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719671706250","endTimeUnixNano":"1779351719675774792","durationMs":4.068542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveDesktopBackendPort","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"add318186197d6ba","parentSpanId":"4c31135efaf00278","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719676017375","endTimeUnixNano":"1779351719676059709","durationMs":0.042334,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.serverExposure.configureFromSettings","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"bd53d6338da7ec0d","parentSpanId":"4c31135efaf00278","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719676280792","endTimeUnixNano":"1779351719676490667","durationMs":0.209875,"attributes":{"port":14124},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.registerSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"6f3457a6f04012cb","parentSpanId":"e11cdbca639eadf3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719676682667","endTimeUnixNano":"1779351719676763959","durationMs":0.081292,"attributes":{"channel":"desktop:get-app-branding"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.registerSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"f65bdd3f87c006c4","parentSpanId":"e11cdbca639eadf3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719676778000","endTimeUnixNano":"1779351719676791417","durationMs":0.013417,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.registerInvoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"5fe2aab63144790d","parentSpanId":"e11cdbca639eadf3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719676801542","endTimeUnixNano":"1779351719676842125","durationMs":0.040583,"attributes":{"channel":"desktop:get-client-settings"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.registerInvoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"2af355f7485953c2","parentSpanId":"e11cdbca639eadf3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719676858334","endTimeUnixNano":"1779351719676874709","durationMs":0.016375,"attributes":{"channel":"desktop:set-client-settings"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.registerInvoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"8c22ac865ab97f74","parentSpanId":"e11cdbca639eadf3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719676884375","endTimeUnixNano":"1779351719676895917","durationMs":0.011542,"attributes":{"channel":"desktop:get-saved-environment-registry"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.registerInvoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"2225b5e809cd6c8b","parentSpanId":"e11cdbca639eadf3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719676904375","endTimeUnixNano":"1779351719676913834","durationMs":0.009459,"attributes":{"channel":"desktop:set-saved-environment-registry"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.registerInvoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"3c654a3ecc9bcca4","parentSpanId":"e11cdbca639eadf3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719676922709","endTimeUnixNano":"1779351719676933084","durationMs":0.010375,"attributes":{"channel":"desktop:get-saved-environment-secret"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.registerInvoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"4277e5fe85f65253","parentSpanId":"e11cdbca639eadf3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719676940792","endTimeUnixNano":"1779351719676958500","durationMs":0.017708,"attributes":{"channel":"desktop:set-saved-environment-secret"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.registerInvoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"df0a6b88943dcc01","parentSpanId":"e11cdbca639eadf3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719676967084","endTimeUnixNano":"1779351719676980875","durationMs":0.013791,"attributes":{"channel":"desktop:remove-saved-environment-secret"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.registerInvoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"3a91881ba391bf3c","parentSpanId":"e11cdbca639eadf3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719676991167","endTimeUnixNano":"1779351719677003667","durationMs":0.0125,"attributes":{"channel":"desktop:discover-ssh-hosts"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.registerInvoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"ac50f708122e35eb","parentSpanId":"e11cdbca639eadf3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719677011542","endTimeUnixNano":"1779351719677025292","durationMs":0.01375,"attributes":{"channel":"desktop:ensure-ssh-environment"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.registerInvoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"89e5ce93de1570e6","parentSpanId":"e11cdbca639eadf3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719677033000","endTimeUnixNano":"1779351719677043209","durationMs":0.010209,"attributes":{"channel":"desktop:disconnect-ssh-environment"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.registerInvoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"02e4d12c08f77e1b","parentSpanId":"e11cdbca639eadf3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719677050459","endTimeUnixNano":"1779351719677058500","durationMs":0.008041,"attributes":{"channel":"desktop:fetch-ssh-environment-descriptor"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.registerInvoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"9eefaf63f4d91d30","parentSpanId":"e11cdbca639eadf3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719677065459","endTimeUnixNano":"1779351719677076084","durationMs":0.010625,"attributes":{"channel":"desktop:bootstrap-ssh-bearer-session"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.registerInvoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"6b6f646726751b3f","parentSpanId":"e11cdbca639eadf3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719677083459","endTimeUnixNano":"1779351719677091792","durationMs":0.008333,"attributes":{"channel":"desktop:fetch-ssh-session-state"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.registerInvoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"2937976d1ed01691","parentSpanId":"e11cdbca639eadf3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719677098875","endTimeUnixNano":"1779351719677107209","durationMs":0.008334,"attributes":{"channel":"desktop:issue-ssh-websocket-token"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.registerInvoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"79fd9588e0945784","parentSpanId":"e11cdbca639eadf3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719677114209","endTimeUnixNano":"1779351719677122334","durationMs":0.008125,"attributes":{"channel":"desktop:resolve-ssh-password-prompt"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.registerInvoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"ebdeaadb86a5ebde","parentSpanId":"e11cdbca639eadf3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719677129250","endTimeUnixNano":"1779351719677137459","durationMs":0.008209,"attributes":{"channel":"desktop:get-server-exposure-state"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.registerInvoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"186aff117787a782","parentSpanId":"e11cdbca639eadf3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719677144417","endTimeUnixNano":"1779351719677152417","durationMs":0.008,"attributes":{"channel":"desktop:set-server-exposure-mode"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.registerInvoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"53ce6d255ff698c4","parentSpanId":"e11cdbca639eadf3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719677159459","endTimeUnixNano":"1779351719677167709","durationMs":0.00825,"attributes":{"channel":"desktop:set-tailscale-serve-enabled"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.registerInvoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"666dfd21653ba55d","parentSpanId":"e11cdbca639eadf3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719677174417","endTimeUnixNano":"1779351719677182500","durationMs":0.008083,"attributes":{"channel":"desktop:get-advertised-endpoints"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.registerInvoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"cd2461fe638c4bfd","parentSpanId":"e11cdbca639eadf3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719677189792","endTimeUnixNano":"1779351719677200959","durationMs":0.011167,"attributes":{"channel":"desktop:pick-folder"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.registerInvoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"6cf89d195d2156a4","parentSpanId":"e11cdbca639eadf3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719677208750","endTimeUnixNano":"1779351719677216917","durationMs":0.008167,"attributes":{"channel":"desktop:confirm"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.registerInvoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"0a45edd9ca52de6c","parentSpanId":"e11cdbca639eadf3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719677224167","endTimeUnixNano":"1779351719677232000","durationMs":0.007833,"attributes":{"channel":"desktop:set-theme"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.registerInvoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"61982286695251bd","parentSpanId":"e11cdbca639eadf3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719677241584","endTimeUnixNano":"1779351719677250417","durationMs":0.008833,"attributes":{"channel":"desktop:context-menu"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.registerInvoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"b2882181f18834ad","parentSpanId":"e11cdbca639eadf3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719677257209","endTimeUnixNano":"1779351719677265292","durationMs":0.008083,"attributes":{"channel":"desktop:open-external"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.registerInvoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"821b2a1837e282c9","parentSpanId":"e11cdbca639eadf3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719677273042","endTimeUnixNano":"1779351719677280959","durationMs":0.007917,"attributes":{"channel":"desktop:update-get-state"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.registerInvoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"cf5d87acde06187f","parentSpanId":"e11cdbca639eadf3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719677289584","endTimeUnixNano":"1779351719677296667","durationMs":0.007083,"attributes":{"channel":"desktop:update-set-channel"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.registerInvoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"e9d09ef00692fe5e","parentSpanId":"e11cdbca639eadf3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719677304125","endTimeUnixNano":"1779351719677310959","durationMs":0.006834,"attributes":{"channel":"desktop:update-download"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.registerInvoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"c136ec0d6acecd79","parentSpanId":"e11cdbca639eadf3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719677443667","endTimeUnixNano":"1779351719677452875","durationMs":0.009208,"attributes":{"channel":"desktop:update-install"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.registerInvoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"72cda0e9eb54a975","parentSpanId":"e11cdbca639eadf3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719677461167","endTimeUnixNano":"1779351719677469042","durationMs":0.007875,"attributes":{"channel":"desktop:update-check"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.installHandlers","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"e11cdbca639eadf3","parentSpanId":"4c31135efaf00278","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719676613250","endTimeUnixNano":"1779351719677473625","durationMs":0.860375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.backendConfiguration.bootstrapToken","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"e2f41535f6659cde","parentSpanId":"b871db2b55715089","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719677690334","endTimeUnixNano":"1779351719677746000","durationMs":0.055666,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.backendConfiguration.resolveStartConfig","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"88420ed9571c3bd4","parentSpanId":"b871db2b55715089","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719677912959","endTimeUnixNano":"1779351719677976959","durationMs":0.064,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.backendConfiguration.resolve","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"b871db2b55715089","parentSpanId":"aec9c62bffcf1680","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719677661459","endTimeUnixNano":"1779351719677982667","durationMs":0.321208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.backendManager.start","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"aec9c62bffcf1680","parentSpanId":"4c31135efaf00278","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719677525292","endTimeUnixNano":"1779351719678166500","durationMs":0.641208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.bootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"4c31135efaf00278","parentSpanId":"c4a8f6f0503d9f3e","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719675792334","endTimeUnixNano":"1779351719678210625","durationMs":2.418291,"attributes":{},"events":[{"name":"bootstrap start","timeUnixNano":"1779351719676002084","attributes":{"scope":"desktop","runId":"5dd107f3af7b","component":"desktop-bootstrap","effect.fiberId":3,"effect.logLevel":"INFO"}},{"name":"using configured backend port","timeUnixNano":"1779351719676265917","attributes":{"scope":"desktop","runId":"5dd107f3af7b","component":"desktop-bootstrap","port":14124,"effect.fiberId":3,"effect.logLevel":"INFO"}},{"name":"bootstrap resolved backend endpoint","timeUnixNano":"1779351719676608792","attributes":{"scope":"desktop","runId":"5dd107f3af7b","component":"desktop-bootstrap","baseUrl":"http://127.0.0.1:14124/","effect.fiberId":3,"effect.logLevel":"INFO"}},{"name":"bootstrap ipc handlers registered","timeUnixNano":"1779351719677520000","attributes":{"scope":"desktop","runId":"5dd107f3af7b","component":"desktop-bootstrap","effect.fiberId":3,"effect.logLevel":"INFO"}},{"name":"bootstrap backend start requested","timeUnixNano":"1779351719678206209","attributes":{"scope":"desktop","runId":"5dd107f3af7b","component":"desktop-bootstrap","effect.fiberId":3,"effect.logLevel":"INFO"}}],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.startup","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"c4a8f6f0503d9f3e","parentSpanId":"d0b9e0cf7baa4a13","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719003516125","endTimeUnixNano":"1779351719678244125","durationMs":674.728,"attributes":{},"events":[{"name":"runtime logging configured","timeUnixNano":"1779351719275883042","attributes":{"scope":"desktop","runId":"5dd107f3af7b","component":"desktop-startup","logDir":"/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/.t3-home/dev/logs","effect.fiberId":3,"effect.logLevel":"INFO"}},{"name":"app ready","timeUnixNano":"1779351719468502292","attributes":{"scope":"desktop","runId":"5dd107f3af7b","component":"desktop-startup","effect.fiberId":3,"effect.logLevel":"INFO"}}],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.observability.writeBackendChildLogRecord","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"d15a36655ca8415e","parentSpanId":"3c3fa2ea984d9d61","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719679179500","endTimeUnixNano":"1779351719680203625","durationMs":1.024125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.observability.backendOutput.writeSessionBoundary","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"3c3fa2ea984d9d61","parentSpanId":"4e28ec33595fda7b","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719679128750","endTimeUnixNano":"1779351719680212000","durationMs":1.08325,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.backendManager.onStarted","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"4e28ec33595fda7b","parentSpanId":"33928349cb1f5169","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719679094750","endTimeUnixNano":"1779351719680216292","durationMs":1.121542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"http.client GET","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"22f0299374273deb","parentSpanId":"bf86a4316ccb76d5","sampled":true,"kind":"client","startTimeUnixNano":"1779351719680863417","endTimeUnixNano":"1779351719683470959","durationMs":2.607542,"attributes":{"http.request.method":"GET","server.address":"http://127.0.0.1:14124","server.port":14124,"url.full":"http://127.0.0.1:14124/.well-known/t3/environment","url.path":"/.well-known/t3/environment","url.scheme":"http"},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"HttpClientError: Transport error (GET http://127.0.0.1:14124/.well-known/t3/environment)\n at catch (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node@4.0.0-beta.59+5799f55463db83ec/node_modules/@effect/platform-node/dist/NodeHttpClient.js:95:21)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/effect.js:695:103\n at ~effect/Utils/internal (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Utils.js:69:12)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/effect.js:695:84\n at process.processTicksAndRejections (node:internal/process/task_queues:104:5)\n at http.client GET\n at desktop.backendManager.waitForHttpReady (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9723:9)\n at desktop.backendManager.waitForHttpReady (definition) (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9675:40)\n at runBackendProcess (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9814:19)\n at runBackendProcess (definition) (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9695:41)\n at desktop.backendManager.start (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9849:26)\n at desktop.bootstrap (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:11066:23)\n at desktop.startup (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:11092:23)\n at desktop.app (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:11109:50) {\n [cause]: Error: connect ECONNREFUSED 127.0.0.1:14124\n at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1705:16)\n}"}} -{"type":"effect-span","name":"http.client GET","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"36ca95eaaa409993","parentSpanId":"bf86a4316ccb76d5","sampled":true,"kind":"client","startTimeUnixNano":"1779351719784867667","endTimeUnixNano":"1779351719785546584","durationMs":0.678917,"attributes":{"http.request.method":"GET","server.address":"http://127.0.0.1:14124","server.port":14124,"url.full":"http://127.0.0.1:14124/.well-known/t3/environment","url.path":"/.well-known/t3/environment","url.scheme":"http"},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"HttpClientError: Transport error (GET http://127.0.0.1:14124/.well-known/t3/environment)\n at catch (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node@4.0.0-beta.59+5799f55463db83ec/node_modules/@effect/platform-node/dist/NodeHttpClient.js:95:21)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/effect.js:695:103\n at ~effect/Utils/internal (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Utils.js:69:12)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/effect.js:695:84\n at process.processTicksAndRejections (node:internal/process/task_queues:104:5)\n at http.client GET\n at desktop.backendManager.waitForHttpReady (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9723:9)\n at desktop.backendManager.waitForHttpReady (definition) (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9675:40)\n at runBackendProcess (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9814:19)\n at runBackendProcess (definition) (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9695:41)\n at desktop.backendManager.start (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9849:26)\n at desktop.bootstrap (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:11066:23)\n at desktop.startup (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:11092:23)\n at desktop.app (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:11109:50) {\n [cause]: Error: connect ECONNREFUSED 127.0.0.1:14124\n at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1705:16)\n}"}} -{"type":"effect-span","name":"http.client GET","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"711f51c74a480230","parentSpanId":"bf86a4316ccb76d5","sampled":true,"kind":"client","startTimeUnixNano":"1779351719887029209","endTimeUnixNano":"1779351719887507584","durationMs":0.478375,"attributes":{"http.request.method":"GET","server.address":"http://127.0.0.1:14124","server.port":14124,"url.full":"http://127.0.0.1:14124/.well-known/t3/environment","url.path":"/.well-known/t3/environment","url.scheme":"http"},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"HttpClientError: Transport error (GET http://127.0.0.1:14124/.well-known/t3/environment)\n at catch (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node@4.0.0-beta.59+5799f55463db83ec/node_modules/@effect/platform-node/dist/NodeHttpClient.js:95:21)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/effect.js:695:103\n at ~effect/Utils/internal (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Utils.js:69:12)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/effect.js:695:84\n at process.processTicksAndRejections (node:internal/process/task_queues:104:5)\n at http.client GET\n at desktop.backendManager.waitForHttpReady (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9723:9)\n at desktop.backendManager.waitForHttpReady (definition) (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9675:40)\n at runBackendProcess (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9814:19)\n at runBackendProcess (definition) (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9695:41)\n at desktop.backendManager.start (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9849:26)\n at desktop.bootstrap (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:11066:23)\n at desktop.startup (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:11092:23)\n at desktop.app (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:11109:50) {\n [cause]: Error: connect ECONNREFUSED 127.0.0.1:14124\n at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1705:16)\n}"}} -{"type":"effect-span","name":"http.client GET","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"1db236606068ad41","parentSpanId":"bf86a4316ccb76d5","sampled":true,"kind":"client","startTimeUnixNano":"1779351719988823792","endTimeUnixNano":"1779351719989421584","durationMs":0.597792,"attributes":{"http.request.method":"GET","server.address":"http://127.0.0.1:14124","server.port":14124,"url.full":"http://127.0.0.1:14124/.well-known/t3/environment","url.path":"/.well-known/t3/environment","url.scheme":"http"},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"HttpClientError: Transport error (GET http://127.0.0.1:14124/.well-known/t3/environment)\n at catch (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node@4.0.0-beta.59+5799f55463db83ec/node_modules/@effect/platform-node/dist/NodeHttpClient.js:95:21)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/effect.js:695:103\n at ~effect/Utils/internal (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Utils.js:69:12)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/effect.js:695:84\n at process.processTicksAndRejections (node:internal/process/task_queues:104:5)\n at http.client GET\n at desktop.backendManager.waitForHttpReady (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9723:9)\n at desktop.backendManager.waitForHttpReady (definition) (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9675:40)\n at runBackendProcess (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9814:19)\n at runBackendProcess (definition) (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9695:41)\n at desktop.backendManager.start (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9849:26)\n at desktop.bootstrap (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:11066:23)\n at desktop.startup (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:11092:23)\n at desktop.app (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:11109:50) {\n [cause]: Error: connect ECONNREFUSED 127.0.0.1:14124\n at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1705:16)\n}"}} -{"type":"effect-span","name":"http.client GET","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"f3abf30cdac396ca","parentSpanId":"bf86a4316ccb76d5","sampled":true,"kind":"client","startTimeUnixNano":"1779351720091170959","endTimeUnixNano":"1779351720091706959","durationMs":0.536,"attributes":{"http.request.method":"GET","server.address":"http://127.0.0.1:14124","server.port":14124,"url.full":"http://127.0.0.1:14124/.well-known/t3/environment","url.path":"/.well-known/t3/environment","url.scheme":"http"},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"HttpClientError: Transport error (GET http://127.0.0.1:14124/.well-known/t3/environment)\n at catch (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node@4.0.0-beta.59+5799f55463db83ec/node_modules/@effect/platform-node/dist/NodeHttpClient.js:95:21)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/effect.js:695:103\n at ~effect/Utils/internal (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Utils.js:69:12)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/effect.js:695:84\n at process.processTicksAndRejections (node:internal/process/task_queues:104:5)\n at http.client GET\n at desktop.backendManager.waitForHttpReady (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9723:9)\n at desktop.backendManager.waitForHttpReady (definition) (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9675:40)\n at runBackendProcess (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9814:19)\n at runBackendProcess (definition) (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9695:41)\n at desktop.backendManager.start (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9849:26)\n at desktop.bootstrap (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:11066:23)\n at desktop.startup (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:11092:23)\n at desktop.app (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:11109:50) {\n [cause]: Error: connect ECONNREFUSED 127.0.0.1:14124\n at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1705:16)\n}"}} -{"type":"effect-span","name":"desktop.observability.writeBackendChildLogRecord","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"e57f01ef924f4661","parentSpanId":"f6fbe6e6ba3de6c7","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720191246250","endTimeUnixNano":"1779351720194509917","durationMs":3.263667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.observability.backendOutput.writeOutputChunk","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"f6fbe6e6ba3de6c7","parentSpanId":"33928349cb1f5169","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720191140750","endTimeUnixNano":"1779351720194528750","durationMs":3.388,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.observability.writeBackendChildLogRecord","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"3b280457458071e0","parentSpanId":"9a32cc879c5ec88d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720202524709","endTimeUnixNano":"1779351720202965000","durationMs":0.440291,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.observability.backendOutput.writeOutputChunk","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"9a32cc879c5ec88d","parentSpanId":"33928349cb1f5169","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720202460084","endTimeUnixNano":"1779351720202978375","durationMs":0.518291,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.observability.writeBackendChildLogRecord","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"f912b003a3ad65e1","parentSpanId":"b68f5dd88d5f1d31","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720203158459","endTimeUnixNano":"1779351720203494917","durationMs":0.336458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.observability.backendOutput.writeOutputChunk","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"b68f5dd88d5f1d31","parentSpanId":"33928349cb1f5169","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720203130250","endTimeUnixNano":"1779351720203501209","durationMs":0.370959,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"http.client GET","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"c9619fcc4b30f45a","parentSpanId":"bf86a4316ccb76d5","sampled":true,"kind":"client","startTimeUnixNano":"1779351720191414625","endTimeUnixNano":"1779351721192888125","durationMs":1001.4735,"attributes":{"http.request.method":"GET","server.address":"http://127.0.0.1:14124","server.port":14124,"url.full":"http://127.0.0.1:14124/.well-known/t3/environment","url.path":"/.well-known/t3/environment","url.scheme":"http"},"events":[],"links":[],"exit":{"_tag":"Interrupted","cause":"InterruptError: All fibers interrupted without error\n at http.client GET\n at desktop.backendManager.waitForHttpReady (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9723:9)\n at desktop.backendManager.waitForHttpReady (definition) (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9675:40)\n at runBackendProcess (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9814:19)\n at runBackendProcess (definition) (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9695:41)\n at desktop.backendManager.start (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9849:26)\n at desktop.bootstrap (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:11066:23)\n at desktop.startup (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:11092:23)\n at desktop.app (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:11109:50) {\n [cause]: InterruptCause: The fiber was interrupted by:\n at fiber (#38)\n}"}} -{"type":"effect-span","name":"http.client GET","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"aee3762d3c1dd89d","parentSpanId":"bf86a4316ccb76d5","sampled":true,"kind":"client","startTimeUnixNano":"1779351721293009917","endTimeUnixNano":"1779351722294190375","durationMs":1001.180458,"attributes":{"http.request.method":"GET","server.address":"http://127.0.0.1:14124","server.port":14124,"url.full":"http://127.0.0.1:14124/.well-known/t3/environment","url.path":"/.well-known/t3/environment","url.scheme":"http"},"events":[],"links":[],"exit":{"_tag":"Interrupted","cause":"InterruptError: All fibers interrupted without error\n at http.client GET\n at desktop.backendManager.waitForHttpReady (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9723:9)\n at desktop.backendManager.waitForHttpReady (definition) (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9675:40)\n at runBackendProcess (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9814:19)\n at runBackendProcess (definition) (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9695:41)\n at desktop.backendManager.start (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9849:26)\n at desktop.bootstrap (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:11066:23)\n at desktop.startup (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:11092:23)\n at desktop.app (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:11109:50) {\n [cause]: InterruptCause: The fiber was interrupted by:\n at fiber (#38)\n}"}} -{"type":"effect-span","name":"http.client GET","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"11b6a7215f726e74","parentSpanId":"bf86a4316ccb76d5","sampled":true,"kind":"client","startTimeUnixNano":"1779351722395053292","endTimeUnixNano":"1779351723397166625","durationMs":1002.113333,"attributes":{"http.request.method":"GET","server.address":"http://127.0.0.1:14124","server.port":14124,"url.full":"http://127.0.0.1:14124/.well-known/t3/environment","url.path":"/.well-known/t3/environment","url.scheme":"http"},"events":[],"links":[],"exit":{"_tag":"Interrupted","cause":"InterruptError: All fibers interrupted without error\n at http.client GET\n at desktop.backendManager.waitForHttpReady (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9723:9)\n at desktop.backendManager.waitForHttpReady (definition) (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9675:40)\n at runBackendProcess (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9814:19)\n at runBackendProcess (definition) (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9695:41)\n at desktop.backendManager.start (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9849:26)\n at desktop.bootstrap (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:11066:23)\n at desktop.startup (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:11092:23)\n at desktop.app (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:11109:50) {\n [cause]: InterruptCause: The fiber was interrupted by:\n at fiber (#38)\n}"}} -{"type":"effect-span","name":"http.client GET","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"56ae62e6f9952279","parentSpanId":"bf86a4316ccb76d5","sampled":true,"kind":"client","startTimeUnixNano":"1779351723498849459","endTimeUnixNano":"1779351724501732084","durationMs":1002.882625,"attributes":{"http.request.method":"GET","server.address":"http://127.0.0.1:14124","server.port":14124,"url.full":"http://127.0.0.1:14124/.well-known/t3/environment","url.path":"/.well-known/t3/environment","url.scheme":"http"},"events":[],"links":[],"exit":{"_tag":"Interrupted","cause":"InterruptError: All fibers interrupted without error\n at http.client GET\n at desktop.backendManager.waitForHttpReady (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9723:9)\n at desktop.backendManager.waitForHttpReady (definition) (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9675:40)\n at runBackendProcess (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9814:19)\n at runBackendProcess (definition) (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9695:41)\n at desktop.backendManager.start (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:9849:26)\n at desktop.bootstrap (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:11066:23)\n at desktop.startup (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:11092:23)\n at desktop.app (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/desktop/dist-electron/main.cjs:11109:50) {\n [cause]: InterruptCause: The fiber was interrupted by:\n at fiber (#38)\n}"}} -{"type":"effect-span","name":"desktop.observability.writeBackendChildLogRecord","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"ff28a7bd01838b03","parentSpanId":"c4fd1cdf93742ee2","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724767213167","endTimeUnixNano":"1779351724767779042","durationMs":0.565875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.observability.backendOutput.writeOutputChunk","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"c4fd1cdf93742ee2","parentSpanId":"33928349cb1f5169","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724767117000","endTimeUnixNano":"1779351724767806959","durationMs":0.689959,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"http.client GET","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"b359e8dc109d7f0b","parentSpanId":"bf86a4316ccb76d5","sampled":true,"kind":"client","startTimeUnixNano":"1779351724603951042","endTimeUnixNano":"1779351724771841625","durationMs":167.890583,"attributes":{"http.request.method":"GET","server.address":"http://127.0.0.1:14124","server.port":14124,"url.full":"http://127.0.0.1:14124/.well-known/t3/environment","url.path":"/.well-known/t3/environment","url.scheme":"http","http.response.status_code":200,"http.response.header.access-control-allow-origin":"*","http.response.header.access-control-allow-methods":"GET, POST, OPTIONS","http.response.header.access-control-allow-headers":"authorization, b3, traceparent, content-type","http.response.header.content-type":"application/json","http.response.header.content-length":"198","http.response.header.date":"Thu, 21 May 2026 08:22:04 GMT","http.response.header.connection":"keep-alive","http.response.header.keep-alive":"timeout=5"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.backendManager.waitForHttpReady","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"bf86a4316ccb76d5","parentSpanId":"33928349cb1f5169","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719680336917","endTimeUnixNano":"1779351724771948292","durationMs":5091.611375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.window.createWindow","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"7532235d443c5fc3","parentSpanId":"b86299efc609dd4d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724772323125","endTimeUnixNano":"1779351724838310250","durationMs":65.987125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.window.createMain","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"b86299efc609dd4d","parentSpanId":"fbf21c4151947be6","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724772285334","endTimeUnixNano":"1779351724838481709","durationMs":66.196375,"attributes":{},"events":[{"name":"main window created","timeUnixNano":"1779351724838474834","attributes":{"scope":"desktop","runId":"5dd107f3af7b","component":"desktop-window","effect.fiberId":37,"effect.logLevel":"INFO"}}],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.window.createMainIfBackendReady","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"fbf21c4151947be6","parentSpanId":"b4b81f19b3f22333","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724772213500","endTimeUnixNano":"1779351724838498834","durationMs":66.285334,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.window.handleBackendReady","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"b4b81f19b3f22333","parentSpanId":"ba65396a7d114041","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724772068209","endTimeUnixNano":"1779351724838504792","durationMs":66.436583,"attributes":{},"events":[{"name":"backend ready","timeUnixNano":"1779351724772207292","attributes":{"scope":"desktop","runId":"5dd107f3af7b","component":"desktop-window","source":"http","effect.fiberId":37,"effect.logLevel":"INFO"}}],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.backendManager.onReady","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"ba65396a7d114041","parentSpanId":"33928349cb1f5169","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724771990792","endTimeUnixNano":"1779351724838518042","durationMs":66.52725,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.observability.writeBackendChildLogRecord","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"0a3b87fb13e52179","parentSpanId":"2e637c45b97c9e2d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724845204459","endTimeUnixNano":"1779351724846812750","durationMs":1.608291,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.observability.backendOutput.writeOutputChunk","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"2e637c45b97c9e2d","parentSpanId":"33928349cb1f5169","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724845131625","endTimeUnixNano":"1779351724846835084","durationMs":1.703459,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getAppBranding","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"da914e06acfff2e3","parentSpanId":"e46abffcf05e0d09","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731608063709","endTimeUnixNano":"1779351731608081209","durationMs":0.0175,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"e46abffcf05e0d09","parentSpanId":"6e99f7fc670eacf2","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731608047584","endTimeUnixNano":"1779351731608163792","durationMs":0.116208,"attributes":{"channel":"desktop:get-app-branding"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"6e99f7fc670eacf2","parentSpanId":"6f3457a6f04012cb","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731607981584","endTimeUnixNano":"1779351731608173042","durationMs":0.191458,"attributes":{"channel":"desktop:get-app-branding"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.setTheme","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"ba61ba4d6fb6b4f1","parentSpanId":"0e90ba78f773051c","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731643986750","endTimeUnixNano":"1779351731644452125","durationMs":0.465375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"0e90ba78f773051c","parentSpanId":"1d15231c43434d88","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731643966834","endTimeUnixNano":"1779351731644484542","durationMs":0.517708,"attributes":{"channel":"desktop:set-theme"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"1d15231c43434d88","parentSpanId":"0a45edd9ca52de6c","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731643863000","endTimeUnixNano":"1779351731644494125","durationMs":0.631125,"attributes":{"channel":"desktop:set-theme"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"0f993e3c5b1dbae6","parentSpanId":"c6666945b2f92c13","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731686285500","endTimeUnixNano":"1779351731686414709","durationMs":0.129209,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"c6666945b2f92c13","parentSpanId":"535992455e605732","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731686263250","endTimeUnixNano":"1779351731686502584","durationMs":0.239334,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"535992455e605732","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731686216542","endTimeUnixNano":"1779351731686512334","durationMs":0.295792,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"ebab79569d9da477","parentSpanId":"c10e578991610ce8","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731687840125","endTimeUnixNano":"1779351731687858959","durationMs":0.018834,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"c10e578991610ce8","parentSpanId":"f6a8dcccaba84233","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731687829667","endTimeUnixNano":"1779351731687879500","durationMs":0.049833,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"f6a8dcccaba84233","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731687802042","endTimeUnixNano":"1779351731687886417","durationMs":0.084375,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"615b7ae77ac85d5a","parentSpanId":"09b436bc19289145","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731688045334","endTimeUnixNano":"1779351731688056375","durationMs":0.011041,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"09b436bc19289145","parentSpanId":"2d46a373f9e2d4d2","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731688038125","endTimeUnixNano":"1779351731688072959","durationMs":0.034834,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"2d46a373f9e2d4d2","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731688021792","endTimeUnixNano":"1779351731688077750","durationMs":0.055958,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"f7a931e9e8fb19d6","parentSpanId":"840282b345899d3f","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731706197500","endTimeUnixNano":"1779351731706234209","durationMs":0.036709,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"840282b345899d3f","parentSpanId":"e7f06096dd6ce3fa","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731706043917","endTimeUnixNano":"1779351731706282959","durationMs":0.239042,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"e7f06096dd6ce3fa","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731705991500","endTimeUnixNano":"1779351731706291834","durationMs":0.300334,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"1702bc57d9283dce","parentSpanId":"85f62bbee96cbae1","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731712921917","endTimeUnixNano":"1779351731712955792","durationMs":0.033875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"85f62bbee96cbae1","parentSpanId":"89f31c317e26901c","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731712903709","endTimeUnixNano":"1779351731712995334","durationMs":0.091625,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"89f31c317e26901c","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731712843792","endTimeUnixNano":"1779351731713004292","durationMs":0.1605,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"aff6c305806dd0f1","parentSpanId":"4344779f26f15aaf","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731778455417","endTimeUnixNano":"1779351731778508584","durationMs":0.053167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"4344779f26f15aaf","parentSpanId":"087ed24b516ec6d7","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731778435042","endTimeUnixNano":"1779351731778549042","durationMs":0.114,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"087ed24b516ec6d7","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731778316584","endTimeUnixNano":"1779351731778557292","durationMs":0.240708,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"4e291be04447b9ac","parentSpanId":"e44fec1eb742fb16","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731778823000","endTimeUnixNano":"1779351731778848334","durationMs":0.025334,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"e44fec1eb742fb16","parentSpanId":"829ccb7f6d87fa49","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731778810625","endTimeUnixNano":"1779351731778866250","durationMs":0.055625,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"829ccb7f6d87fa49","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731778779209","endTimeUnixNano":"1779351731778872459","durationMs":0.09325,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"54fe5cf9dfd67f19","parentSpanId":"635117f1f870a592","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731782181667","endTimeUnixNano":"1779351731782198834","durationMs":0.017167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"635117f1f870a592","parentSpanId":"439dce4172cc7b13","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731782171125","endTimeUnixNano":"1779351731782218000","durationMs":0.046875,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"439dce4172cc7b13","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731782135042","endTimeUnixNano":"1779351731782229667","durationMs":0.094625,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"5b699b7e5b700032","parentSpanId":"2f2a22f718b558bc","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731782368375","endTimeUnixNano":"1779351731782380584","durationMs":0.012209,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"2f2a22f718b558bc","parentSpanId":"3d26788fd984a98f","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731782357417","endTimeUnixNano":"1779351731782390750","durationMs":0.033333,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"3d26788fd984a98f","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731782339209","endTimeUnixNano":"1779351731782801834","durationMs":0.462625,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"06a490579e7ea072","parentSpanId":"914be243659fa6c9","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731783058375","endTimeUnixNano":"1779351731783076000","durationMs":0.017625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"914be243659fa6c9","parentSpanId":"a9077c11eb2bcecb","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731783044500","endTimeUnixNano":"1779351731783103875","durationMs":0.059375,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"a9077c11eb2bcecb","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731783015125","endTimeUnixNano":"1779351731783111417","durationMs":0.096292,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"e9f24ec8d81dcd14","parentSpanId":"9253c9ed6549e478","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731783284417","endTimeUnixNano":"1779351731783297292","durationMs":0.012875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"9253c9ed6549e478","parentSpanId":"ef913d3f870af7c2","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731783266250","endTimeUnixNano":"1779351731783315834","durationMs":0.049584,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"ef913d3f870af7c2","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731783233292","endTimeUnixNano":"1779351731783321709","durationMs":0.088417,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.savedEnvironments.getRegistry","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"ac41e827bb110b15","parentSpanId":"01e456e541402152","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731783567292","endTimeUnixNano":"1779351731783748667","durationMs":0.181375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.savedEnvironments.getRegistry","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"01e456e541402152","parentSpanId":"73c3145f7eff5c26","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731783536500","endTimeUnixNano":"1779351731783756292","durationMs":0.219792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"73c3145f7eff5c26","parentSpanId":"02d54533ccdeef33","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731783519417","endTimeUnixNano":"1779351731783780625","durationMs":0.261208,"attributes":{"channel":"desktop:get-saved-environment-registry"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"02d54533ccdeef33","parentSpanId":"8c22ac865ab97f74","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731783495709","endTimeUnixNano":"1779351731783785542","durationMs":0.289833,"attributes":{"channel":"desktop:get-saved-environment-registry"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"a4dca996d9281ca9","parentSpanId":"28b36667e536cb7c","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731784145459","endTimeUnixNano":"1779351731784159042","durationMs":0.013583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"28b36667e536cb7c","parentSpanId":"b7e2864d0336e9bb","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731784134250","endTimeUnixNano":"1779351731784171875","durationMs":0.037625,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"b7e2864d0336e9bb","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731784111542","endTimeUnixNano":"1779351731784176917","durationMs":0.065375,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.clientSettings.get","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"00a4eeaf00ef9882","parentSpanId":"2ce610549b03dc57","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731785003209","endTimeUnixNano":"1779351731785211875","durationMs":0.208666,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.clientSettings.get","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"2ce610549b03dc57","parentSpanId":"133290a182ccf4cb","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731784971792","endTimeUnixNano":"1779351731785218584","durationMs":0.246792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"133290a182ccf4cb","parentSpanId":"d02a0b6ec067ba06","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731784950584","endTimeUnixNano":"1779351731785409667","durationMs":0.459083,"attributes":{"channel":"desktop:get-client-settings"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"d02a0b6ec067ba06","parentSpanId":"5fe2aab63144790d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731784918792","endTimeUnixNano":"1779351731785416209","durationMs":0.497417,"attributes":{"channel":"desktop:get-client-settings"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.updates.getState","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"e3ca3d10e1048cdd","parentSpanId":"6b124a813b02a9a8","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731785946334","endTimeUnixNano":"1779351731785967709","durationMs":0.021375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"6b124a813b02a9a8","parentSpanId":"3d245ea8ba0079ad","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731785931584","endTimeUnixNano":"1779351731786027584","durationMs":0.096,"attributes":{"channel":"desktop:update-get-state"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"3d245ea8ba0079ad","parentSpanId":"821b2a1837e282c9","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731785909875","endTimeUnixNano":"1779351731786032542","durationMs":0.122667,"attributes":{"channel":"desktop:update-get-state"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.updates.getState","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"1961a6ae15dc4740","parentSpanId":"5406824726747cc4","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731786579334","endTimeUnixNano":"1779351731786589417","durationMs":0.010083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"5406824726747cc4","parentSpanId":"f2943da7a4fad556","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731786566625","endTimeUnixNano":"1779351731786605167","durationMs":0.038542,"attributes":{"channel":"desktop:update-get-state"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"f2943da7a4fad556","parentSpanId":"821b2a1837e282c9","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731786548625","endTimeUnixNano":"1779351731786612792","durationMs":0.064167,"attributes":{"channel":"desktop:update-get-state"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"e2dc296fefebbe2e","parentSpanId":"a94d6e61f04b4ad1","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731788540500","endTimeUnixNano":"1779351731788560667","durationMs":0.020167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"a94d6e61f04b4ad1","parentSpanId":"9f25e1b82e89b599","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731788526459","endTimeUnixNano":"1779351731788574125","durationMs":0.047666,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"9f25e1b82e89b599","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731788504084","endTimeUnixNano":"1779351731788578209","durationMs":0.074125,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"971f0432d3d694de","parentSpanId":"227946a907b26738","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731788732500","endTimeUnixNano":"1779351731788746417","durationMs":0.013917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"227946a907b26738","parentSpanId":"05fc12446484d9da","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731788722542","endTimeUnixNano":"1779351731788759459","durationMs":0.036917,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"05fc12446484d9da","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731788702542","endTimeUnixNano":"1779351731788764292","durationMs":0.06175,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"9727c1941f3f1b7d","parentSpanId":"1ac655efc9fecfa0","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731789209375","endTimeUnixNano":"1779351731789218917","durationMs":0.009542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"1ac655efc9fecfa0","parentSpanId":"c1e768847dd9cf73","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731789201417","endTimeUnixNano":"1779351731789231709","durationMs":0.030292,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"c1e768847dd9cf73","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731789180167","endTimeUnixNano":"1779351731789236834","durationMs":0.056667,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"5f8cfe6f47eb8aad","parentSpanId":"c269e82a6c2c5b41","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731789342375","endTimeUnixNano":"1779351731789351125","durationMs":0.00875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"c269e82a6c2c5b41","parentSpanId":"6c6c5aa344d005e6","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731789335500","endTimeUnixNano":"1779351731789363042","durationMs":0.027542,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"6c6c5aa344d005e6","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731789319709","endTimeUnixNano":"1779351731789367459","durationMs":0.04775,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"05aec480c7f2da98","parentSpanId":"5a3dc5eeb9a67078","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731789570959","endTimeUnixNano":"1779351731789578375","durationMs":0.007416,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"5a3dc5eeb9a67078","parentSpanId":"31b621ddd038bfee","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731789564375","endTimeUnixNano":"1779351731789587500","durationMs":0.023125,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"31b621ddd038bfee","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731789551667","endTimeUnixNano":"1779351731789591334","durationMs":0.039667,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.updates.getState","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"45d45e4b7010408d","parentSpanId":"ca249799a01cf04f","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731790103375","endTimeUnixNano":"1779351731790110042","durationMs":0.006667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"ca249799a01cf04f","parentSpanId":"756f011817e2e875","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731790089125","endTimeUnixNano":"1779351731790127917","durationMs":0.038792,"attributes":{"channel":"desktop:update-get-state"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"756f011817e2e875","parentSpanId":"821b2a1837e282c9","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731790067375","endTimeUnixNano":"1779351731790132667","durationMs":0.065292,"attributes":{"channel":"desktop:update-get-state"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"acb6e7afe4ecf4d3","parentSpanId":"4426029445671425","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731799530250","endTimeUnixNano":"1779351731799550125","durationMs":0.019875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"4426029445671425","parentSpanId":"f8063f78eed4fd37","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731799522292","endTimeUnixNano":"1779351731799723334","durationMs":0.201042,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"f8063f78eed4fd37","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731799486667","endTimeUnixNano":"1779351731799731334","durationMs":0.244667,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"9663cfcb25832213","parentSpanId":"6d706ee543ceafb3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731804287250","endTimeUnixNano":"1779351731804305625","durationMs":0.018375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"6d706ee543ceafb3","parentSpanId":"fba19c4459dbd1a6","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731804277917","endTimeUnixNano":"1779351731804336125","durationMs":0.058208,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"fba19c4459dbd1a6","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731804251125","endTimeUnixNano":"1779351731804342917","durationMs":0.091792,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.updates.getState","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"a89db2095e5f264c","parentSpanId":"62970538f3fa8cd0","sampled":true,"kind":"internal","startTimeUnixNano":"1779351888707984000","endTimeUnixNano":"1779351888708008000","durationMs":0.024,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"62970538f3fa8cd0","parentSpanId":"ff60a5634b12f06d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351888707944000","endTimeUnixNano":"1779351888708221417","durationMs":0.277417,"attributes":{"channel":"desktop:update-get-state"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"ff60a5634b12f06d","parentSpanId":"821b2a1837e282c9","sampled":true,"kind":"internal","startTimeUnixNano":"1779351888707739417","endTimeUnixNano":"1779351888708241959","durationMs":0.502542,"attributes":{"channel":"desktop:update-get-state"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"9e2dccdc01796804","parentSpanId":"9661015187dfb28a","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896404662459","endTimeUnixNano":"1779351896404688000","durationMs":0.025541,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"9661015187dfb28a","parentSpanId":"f9ae2f3dd9373aeb","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896404652750","endTimeUnixNano":"1779351896404723750","durationMs":0.071,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"f9ae2f3dd9373aeb","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896404612584","endTimeUnixNano":"1779351896404730459","durationMs":0.117875,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"e82dffe5fa6b05c2","parentSpanId":"56875ca97aeb4d60","sampled":true,"kind":"internal","startTimeUnixNano":"1779351904706165709","endTimeUnixNano":"1779351904706189834","durationMs":0.024125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"56875ca97aeb4d60","parentSpanId":"6b9d56d034c65f85","sampled":true,"kind":"internal","startTimeUnixNano":"1779351904706154125","endTimeUnixNano":"1779351904706230542","durationMs":0.076417,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"6b9d56d034c65f85","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779351904706111709","endTimeUnixNano":"1779351904706240500","durationMs":0.128791,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.lifecycle.windowAllClosed","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"c105882b6bcf7b46","parentSpanId":"1df71f533ffab481","sampled":true,"kind":"internal","startTimeUnixNano":"1779351912219569834","endTimeUnixNano":"1779351912219813792","durationMs":0.243958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.window.createWindow","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"da7b1ee4b0f22c4f","parentSpanId":"5613082dc2c95d02","sampled":true,"kind":"internal","startTimeUnixNano":"1779352569948583000","endTimeUnixNano":"1779352569971823500","durationMs":23.2405,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.window.createMain","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"5613082dc2c95d02","parentSpanId":"069a85a179705203","sampled":true,"kind":"internal","startTimeUnixNano":"1779352569948513167","endTimeUnixNano":"1779352569972252417","durationMs":23.73925,"attributes":{},"events":[{"name":"main window created","timeUnixNano":"1779352569972231584","attributes":{"scope":"desktop","runId":"5dd107f3af7b","component":"desktop-window","effect.fiberId":92,"effect.logLevel":"INFO"}}],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.window.createMainIfBackendReady","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"069a85a179705203","parentSpanId":"3fabf9088b7da39b","sampled":true,"kind":"internal","startTimeUnixNano":"1779352569948471459","endTimeUnixNano":"1779352569972290000","durationMs":23.818541,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.window.activate","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"3fabf9088b7da39b","parentSpanId":"9fe774ec501e0fd7","sampled":true,"kind":"internal","startTimeUnixNano":"1779352569948251125","endTimeUnixNano":"1779352569972301750","durationMs":24.050625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.lifecycle.activate","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"9fe774ec501e0fd7","parentSpanId":"1df71f533ffab481","sampled":true,"kind":"internal","startTimeUnixNano":"1779352569948168292","endTimeUnixNano":"1779352569972308875","durationMs":24.140583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getAppBranding","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"27ffef31c6eb04ed","parentSpanId":"9df45816ac41c9d8","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570482045584","endTimeUnixNano":"1779352570482058292","durationMs":0.012708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"9df45816ac41c9d8","parentSpanId":"9db82bf6f6256f1c","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570482032750","endTimeUnixNano":"1779352570482101000","durationMs":0.06825,"attributes":{"channel":"desktop:get-app-branding"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"9db82bf6f6256f1c","parentSpanId":"6f3457a6f04012cb","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570481994875","endTimeUnixNano":"1779352570482110500","durationMs":0.115625,"attributes":{"channel":"desktop:get-app-branding"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.setTheme","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"3b1cc9a1a92ef7ae","parentSpanId":"132722fe69c05241","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570515895542","endTimeUnixNano":"1779352570516494167","durationMs":0.598625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"132722fe69c05241","parentSpanId":"1ba8af7b772ee754","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570515879667","endTimeUnixNano":"1779352570516514500","durationMs":0.634833,"attributes":{"channel":"desktop:set-theme"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"1ba8af7b772ee754","parentSpanId":"0a45edd9ca52de6c","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570515824334","endTimeUnixNano":"1779352570516522542","durationMs":0.698208,"attributes":{"channel":"desktop:set-theme"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"3a95863a74c29e93","parentSpanId":"7b2809495e27ffba","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570550363417","endTimeUnixNano":"1779352570550393792","durationMs":0.030375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"7b2809495e27ffba","parentSpanId":"4bfb4320eaad2e22","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570550334875","endTimeUnixNano":"1779352570550445292","durationMs":0.110417,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"4bfb4320eaad2e22","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570550281875","endTimeUnixNano":"1779352570550453750","durationMs":0.171875,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"3267157a5ff29510","parentSpanId":"ddc2b6e889ff01b0","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570551621167","endTimeUnixNano":"1779352570551640292","durationMs":0.019125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"ddc2b6e889ff01b0","parentSpanId":"b5e0f17984c05c98","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570551600542","endTimeUnixNano":"1779352570551668542","durationMs":0.068,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"b5e0f17984c05c98","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570551568875","endTimeUnixNano":"1779352570551675792","durationMs":0.106917,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"062493fa586bfadf","parentSpanId":"0c46f7ef4233f0cb","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570551869459","endTimeUnixNano":"1779352570551880542","durationMs":0.011083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"0c46f7ef4233f0cb","parentSpanId":"7cb578157ceb0f38","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570551860792","endTimeUnixNano":"1779352570551894000","durationMs":0.033208,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"7cb578157ceb0f38","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570551842417","endTimeUnixNano":"1779352570551898375","durationMs":0.055958,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"f91f877aa374d805","parentSpanId":"75e2fff4f8adb84a","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570625142250","endTimeUnixNano":"1779352570625164375","durationMs":0.022125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"75e2fff4f8adb84a","parentSpanId":"0e56ec4c5b7b9e94","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570625133625","endTimeUnixNano":"1779352570625198292","durationMs":0.064667,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"0e56ec4c5b7b9e94","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570625099875","endTimeUnixNano":"1779352570625204459","durationMs":0.104584,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"ff97a247f6df089d","parentSpanId":"aeee637b779f3aaa","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570625417709","endTimeUnixNano":"1779352570625427709","durationMs":0.01,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"aeee637b779f3aaa","parentSpanId":"ea3bf0688917cece","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570625410000","endTimeUnixNano":"1779352570625441834","durationMs":0.031834,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"ea3bf0688917cece","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570625388792","endTimeUnixNano":"1779352570625447000","durationMs":0.058208,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"6c603a8f8f0d2a49","parentSpanId":"17eda97c2ebf1971","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570628470334","endTimeUnixNano":"1779352570628481209","durationMs":0.010875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"17eda97c2ebf1971","parentSpanId":"d281e023b6182ad8","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570628457917","endTimeUnixNano":"1779352570628496667","durationMs":0.03875,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"d281e023b6182ad8","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570628435125","endTimeUnixNano":"1779352570628501750","durationMs":0.066625,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"3218a1e58d9edc95","parentSpanId":"03f165830d32ab82","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570628647125","endTimeUnixNano":"1779352570628656334","durationMs":0.009209,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"03f165830d32ab82","parentSpanId":"2e048a9f756446b9","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570628639292","endTimeUnixNano":"1779352570628670542","durationMs":0.03125,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"2e048a9f756446b9","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570628620167","endTimeUnixNano":"1779352570628676000","durationMs":0.055833,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"7abc8316839bed40","parentSpanId":"4f0f9e1a11e8865b","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570628827709","endTimeUnixNano":"1779352570628833625","durationMs":0.005916,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"4f0f9e1a11e8865b","parentSpanId":"994878d2f7e7a120","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570628822167","endTimeUnixNano":"1779352570628841542","durationMs":0.019375,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"994878d2f7e7a120","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570628810542","endTimeUnixNano":"1779352570628844917","durationMs":0.034375,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"d647acf4a526c82d","parentSpanId":"9c6d156e39086e67","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570628924959","endTimeUnixNano":"1779352570628930709","durationMs":0.00575,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"9c6d156e39086e67","parentSpanId":"425fac7a7ebc367e","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570628919750","endTimeUnixNano":"1779352570628937084","durationMs":0.017334,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"425fac7a7ebc367e","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570628910209","endTimeUnixNano":"1779352570628940000","durationMs":0.029791,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.savedEnvironments.getRegistry","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"c234518921df3538","parentSpanId":"5bf8e9848962a67a","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570629141459","endTimeUnixNano":"1779352570629382542","durationMs":0.241083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.savedEnvironments.getRegistry","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"5bf8e9848962a67a","parentSpanId":"0f99b348b2dae3c2","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570629134125","endTimeUnixNano":"1779352570629392917","durationMs":0.258792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"0f99b348b2dae3c2","parentSpanId":"efb75ea6f016d538","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570629118667","endTimeUnixNano":"1779352570629421417","durationMs":0.30275,"attributes":{"channel":"desktop:get-saved-environment-registry"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"efb75ea6f016d538","parentSpanId":"8c22ac865ab97f74","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570629085250","endTimeUnixNano":"1779352570629428459","durationMs":0.343209,"attributes":{"channel":"desktop:get-saved-environment-registry"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"667d75281865c103","parentSpanId":"72a5bf911da559f0","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570629658750","endTimeUnixNano":"1779352570629664292","durationMs":0.005542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"72a5bf911da559f0","parentSpanId":"46107dfba28329d7","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570629653042","endTimeUnixNano":"1779352570629671500","durationMs":0.018458,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"46107dfba28329d7","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570629641792","endTimeUnixNano":"1779352570629674584","durationMs":0.032792,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.clientSettings.get","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"cd4a3fdce8433bf2","parentSpanId":"52a36da5c8bdf720","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570629845875","endTimeUnixNano":"1779352570629911375","durationMs":0.0655,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.clientSettings.get","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"52a36da5c8bdf720","parentSpanId":"000b0ee00db4e7fa","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570629839750","endTimeUnixNano":"1779352570629915709","durationMs":0.075959,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"000b0ee00db4e7fa","parentSpanId":"8ba08b8d67628f90","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570629830834","endTimeUnixNano":"1779352570629922500","durationMs":0.091666,"attributes":{"channel":"desktop:get-client-settings"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"8ba08b8d67628f90","parentSpanId":"5fe2aab63144790d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570629810084","endTimeUnixNano":"1779352570629926250","durationMs":0.116166,"attributes":{"channel":"desktop:get-client-settings"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.updates.getState","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"23db8c83b4c41b99","parentSpanId":"4bfa9a5ea2bd0692","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570631185292","endTimeUnixNano":"1779352570631192792","durationMs":0.0075,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"4bfa9a5ea2bd0692","parentSpanId":"df970400883ae7e4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570631177125","endTimeUnixNano":"1779352570631211875","durationMs":0.03475,"attributes":{"channel":"desktop:update-get-state"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"df970400883ae7e4","parentSpanId":"821b2a1837e282c9","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570631156334","endTimeUnixNano":"1779352570631215667","durationMs":0.059333,"attributes":{"channel":"desktop:update-get-state"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.updates.getState","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"45b35e9523d20493","parentSpanId":"b7da5b4c75bd18c3","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570631760667","endTimeUnixNano":"1779352570631766667","durationMs":0.006,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"b7da5b4c75bd18c3","parentSpanId":"e57589a0fa9c9932","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570631751334","endTimeUnixNano":"1779352570631785917","durationMs":0.034583,"attributes":{"channel":"desktop:update-get-state"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"e57589a0fa9c9932","parentSpanId":"821b2a1837e282c9","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570631735584","endTimeUnixNano":"1779352570631791375","durationMs":0.055791,"attributes":{"channel":"desktop:update-get-state"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"646cda1efc9c488d","parentSpanId":"694f2574b3cf3e4c","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570633573875","endTimeUnixNano":"1779352570633581750","durationMs":0.007875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"694f2574b3cf3e4c","parentSpanId":"a5059260689358ac","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570633564042","endTimeUnixNano":"1779352570633591375","durationMs":0.027333,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"a5059260689358ac","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570633549792","endTimeUnixNano":"1779352570633594709","durationMs":0.044917,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"2cb1135e4eb78488","parentSpanId":"f5e352700f783dc4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570633773542","endTimeUnixNano":"1779352570633782209","durationMs":0.008667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"f5e352700f783dc4","parentSpanId":"169ccf108ae0ea21","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570633766625","endTimeUnixNano":"1779352570633792917","durationMs":0.026292,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"169ccf108ae0ea21","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570633748917","endTimeUnixNano":"1779352570633796709","durationMs":0.047792,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"0443b47c79074ba0","parentSpanId":"aff88733fab506c5","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570634177959","endTimeUnixNano":"1779352570634186084","durationMs":0.008125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"aff88733fab506c5","parentSpanId":"3d422850aee5c6f7","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570634172125","endTimeUnixNano":"1779352570634198084","durationMs":0.025959,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"3d422850aee5c6f7","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570634159125","endTimeUnixNano":"1779352570634202625","durationMs":0.0435,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"f8c285f6d38d4f15","parentSpanId":"61a3fc86d13d3f4e","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570634302334","endTimeUnixNano":"1779352570634309917","durationMs":0.007583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"61a3fc86d13d3f4e","parentSpanId":"8d17e91f10754fa3","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570634295459","endTimeUnixNano":"1779352570634319250","durationMs":0.023791,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"8d17e91f10754fa3","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570634279209","endTimeUnixNano":"1779352570634323000","durationMs":0.043791,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"608a1ed3c1080387","parentSpanId":"55de1bd88c360532","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570634486375","endTimeUnixNano":"1779352570634491375","durationMs":0.005,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"55de1bd88c360532","parentSpanId":"e860e34bc3c6acba","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570634481084","endTimeUnixNano":"1779352570634498875","durationMs":0.017791,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"e860e34bc3c6acba","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570634470667","endTimeUnixNano":"1779352570634507084","durationMs":0.036417,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.updates.getState","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"9c6903ae5b11a49f","parentSpanId":"941bfc0b87cee362","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570634945209","endTimeUnixNano":"1779352570634953709","durationMs":0.0085,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"941bfc0b87cee362","parentSpanId":"ba58b1394a8ce676","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570634931584","endTimeUnixNano":"1779352570634974792","durationMs":0.043208,"attributes":{"channel":"desktop:update-get-state"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"ba58b1394a8ce676","parentSpanId":"821b2a1837e282c9","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570634913000","endTimeUnixNano":"1779352570634979375","durationMs":0.066375,"attributes":{"channel":"desktop:update-get-state"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"571d89812e1c19c2","parentSpanId":"d932eacc30f8a080","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570643857709","endTimeUnixNano":"1779352570643881875","durationMs":0.024166,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"d932eacc30f8a080","parentSpanId":"e708d955fe337f4e","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570643846584","endTimeUnixNano":"1779352570643910917","durationMs":0.064333,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"e708d955fe337f4e","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570643815084","endTimeUnixNano":"1779352570643916292","durationMs":0.101208,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"5dd798b6c0946670","parentSpanId":"2c0f4b3f1f0ec5f8","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570647866750","endTimeUnixNano":"1779352570647878667","durationMs":0.011917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"2c0f4b3f1f0ec5f8","parentSpanId":"cc73eb30d5001521","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570647856875","endTimeUnixNano":"1779352570647899750","durationMs":0.042875,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"cc73eb30d5001521","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570647832834","endTimeUnixNano":"1779352570647904750","durationMs":0.071916,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"2e4d2fb87b119f90","parentSpanId":"461ae3e9f95798ff","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570817754834","endTimeUnixNano":"1779352570817777000","durationMs":0.022166,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"461ae3e9f95798ff","parentSpanId":"7ea989cddeeff57d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570817745209","endTimeUnixNano":"1779352570817806667","durationMs":0.061458,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"7ea989cddeeff57d","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570817703917","endTimeUnixNano":"1779352570817813584","durationMs":0.109667,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.showContextMenu","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"4116ce05bfb0fbe3","parentSpanId":"9a01d7c4397cedfb","sampled":true,"kind":"internal","startTimeUnixNano":"1779352574348871667","endTimeUnixNano":"1779352576754856667","durationMs":2405.985,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"9a01d7c4397cedfb","parentSpanId":"3acc7bbf291dcda1","sampled":true,"kind":"internal","startTimeUnixNano":"1779352574348807167","endTimeUnixNano":"1779352576755064917","durationMs":2406.25775,"attributes":{"channel":"desktop:context-menu"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invoke","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"3acc7bbf291dcda1","parentSpanId":"61982286695251bd","sampled":true,"kind":"internal","startTimeUnixNano":"1779352574347613959","endTimeUnixNano":"1779352576755116750","durationMs":2407.502791,"attributes":{"channel":"desktop:context-menu"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"0452fdb61512115d","parentSpanId":"9b5376196abe26e5","sampled":true,"kind":"internal","startTimeUnixNano":"1779352590561702750","endTimeUnixNano":"1779352590561750125","durationMs":0.047375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"9b5376196abe26e5","parentSpanId":"fda469e6147fc723","sampled":true,"kind":"internal","startTimeUnixNano":"1779352590561686792","endTimeUnixNano":"1779352590561826500","durationMs":0.139708,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"fda469e6147fc723","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352590561613042","endTimeUnixNano":"1779352590561841167","durationMs":0.228125,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"2826c32e3a3b349f","parentSpanId":"80531d953d2996fb","sampled":true,"kind":"internal","startTimeUnixNano":"1779352592716670959","endTimeUnixNano":"1779352592716715917","durationMs":0.044958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"80531d953d2996fb","parentSpanId":"6714840b037b5495","sampled":true,"kind":"internal","startTimeUnixNano":"1779352592716655125","endTimeUnixNano":"1779352592716788000","durationMs":0.132875,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"6714840b037b5495","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352592716588584","endTimeUnixNano":"1779352592716800959","durationMs":0.212375,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"5576d6b60b84b40a","parentSpanId":"2f82fcb87b0ee855","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600825970917","endTimeUnixNano":"1779352600825990084","durationMs":0.019167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"2f82fcb87b0ee855","parentSpanId":"f6cc4fd08134dc11","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600825962542","endTimeUnixNano":"1779352600826023917","durationMs":0.061375,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"f6cc4fd08134dc11","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600825930125","endTimeUnixNano":"1779352600826032042","durationMs":0.101917,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"e91535462643aa48","parentSpanId":"060b11301b32c3c8","sampled":true,"kind":"internal","startTimeUnixNano":"1779352607104079875","endTimeUnixNano":"1779352607104124792","durationMs":0.044917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"060b11301b32c3c8","parentSpanId":"aed37d3bb6cdbab1","sampled":true,"kind":"internal","startTimeUnixNano":"1779352607104062625","endTimeUnixNano":"1779352607104200709","durationMs":0.138084,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"aed37d3bb6cdbab1","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352607103988209","endTimeUnixNano":"1779352607104218625","durationMs":0.230416,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"41a9414bc42c20b3","parentSpanId":"10188df699ad7b73","sampled":true,"kind":"internal","startTimeUnixNano":"1779352610653026000","endTimeUnixNano":"1779352610653073667","durationMs":0.047667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"10188df699ad7b73","parentSpanId":"4185bc1ba07b0ecb","sampled":true,"kind":"internal","startTimeUnixNano":"1779352610653007459","endTimeUnixNano":"1779352610653149584","durationMs":0.142125,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"4185bc1ba07b0ecb","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352610652921709","endTimeUnixNano":"1779352610653164625","durationMs":0.242916,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"86e9bd3ff51dcc21","parentSpanId":"a50bcc601071b3cf","sampled":true,"kind":"internal","startTimeUnixNano":"1779352611581148000","endTimeUnixNano":"1779352611581179167","durationMs":0.031167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"a50bcc601071b3cf","parentSpanId":"4565ea87c6b4775b","sampled":true,"kind":"internal","startTimeUnixNano":"1779352611581129542","endTimeUnixNano":"1779352611581225834","durationMs":0.096292,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"4565ea87c6b4775b","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352611581078084","endTimeUnixNano":"1779352611581236500","durationMs":0.158416,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"452a783f6085f859","parentSpanId":"25daeb6129c999fd","sampled":true,"kind":"internal","startTimeUnixNano":"1779352612749693459","endTimeUnixNano":"1779352612749737459","durationMs":0.044,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"25daeb6129c999fd","parentSpanId":"b80955e2f91ec214","sampled":true,"kind":"internal","startTimeUnixNano":"1779352612749676209","endTimeUnixNano":"1779352612749819792","durationMs":0.143583,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"b80955e2f91ec214","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352612749603000","endTimeUnixNano":"1779352612749834000","durationMs":0.231,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"f1234a23cf0b6492","parentSpanId":"04855499a6f73028","sampled":true,"kind":"internal","startTimeUnixNano":"1779352615117858334","endTimeUnixNano":"1779352615117905584","durationMs":0.04725,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"04855499a6f73028","parentSpanId":"ad5b871be7fe40b3","sampled":true,"kind":"internal","startTimeUnixNano":"1779352615117840625","endTimeUnixNano":"1779352615117982709","durationMs":0.142084,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"ad5b871be7fe40b3","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352615117767042","endTimeUnixNano":"1779352615117998000","durationMs":0.230958,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"a03a6da8683cd060","parentSpanId":"5075bf940d6e1d7b","sampled":true,"kind":"internal","startTimeUnixNano":"1779352615968831709","endTimeUnixNano":"1779352615968864959","durationMs":0.03325,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"5075bf940d6e1d7b","parentSpanId":"9eaefa48714f1403","sampled":true,"kind":"internal","startTimeUnixNano":"1779352615968812792","endTimeUnixNano":"1779352615968918042","durationMs":0.10525,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"9eaefa48714f1403","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352615968751375","endTimeUnixNano":"1779352615968931125","durationMs":0.17975,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"4587ccd5e12417dc","parentSpanId":"60591b86a5c6bc49","sampled":true,"kind":"internal","startTimeUnixNano":"1779352819113519917","endTimeUnixNano":"1779352819113568584","durationMs":0.048667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"60591b86a5c6bc49","parentSpanId":"85d40196e09c759b","sampled":true,"kind":"internal","startTimeUnixNano":"1779352819113499334","endTimeUnixNano":"1779352819113650542","durationMs":0.151208,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"85d40196e09c759b","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352819113378417","endTimeUnixNano":"1779352819113666375","durationMs":0.287958,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.window.getLocalEnvironmentBootstrap","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"32a60a4dbc4951d2","parentSpanId":"42f25cb381e3aa35","sampled":true,"kind":"internal","startTimeUnixNano":"1779352819115239750","endTimeUnixNano":"1779352819115264750","durationMs":0.025,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.method","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"42f25cb381e3aa35","parentSpanId":"b047e20ad9ab0115","sampled":true,"kind":"internal","startTimeUnixNano":"1779352819115217500","endTimeUnixNano":"1779352819115300250","durationMs":0.08275,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.ipc.invokeSync","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"b047e20ad9ab0115","parentSpanId":"f65bdd3f87c006c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352819115174459","endTimeUnixNano":"1779352819115311750","durationMs":0.137291,"attributes":{"channel":"desktop:get-local-environment-bootstrap"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.lifecycle.windowAllClosed","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"09da0d773a1feaaa","parentSpanId":"1df71f533ffab481","sampled":true,"kind":"internal","startTimeUnixNano":"1779352829160526625","endTimeUnixNano":"1779352829160577792","durationMs":0.051167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runBackendProcess","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"33928349cb1f5169","parentSpanId":"aec9c62bffcf1680","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719678272334","endTimeUnixNano":"1779353647794209875","durationMs":1928115.937541,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.backendManager.finalizeRun","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"b26761bff19d80c0","parentSpanId":"aec9c62bffcf1680","sampled":true,"kind":"internal","startTimeUnixNano":"1779353647794335167","endTimeUnixNano":"1779353647794567917","durationMs":0.23275,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.backendManager.stop","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"5b99537e9ba311ac","parentSpanId":"d0b9e0cf7baa4a13","sampled":true,"kind":"internal","startTimeUnixNano":"1779353647084353625","endTimeUnixNano":"1779353647794650459","durationMs":710.296834,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.lifecycle.requestShutdownAndWait","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"561409f5d0864af9","parentSpanId":"2092e74c267f6167","sampled":true,"kind":"internal","startTimeUnixNano":"1779353647083313625","endTimeUnixNano":"1779353647794668667","durationMs":711.355042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.lifecycle.beforeQuit","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"2092e74c267f6167","parentSpanId":"1df71f533ffab481","sampled":true,"kind":"internal","startTimeUnixNano":"1779353647082721459","endTimeUnixNano":"1779353647794678042","durationMs":711.956583,"attributes":{},"events":[{"name":"before-quit received","timeUnixNano":"1779353647083273834","attributes":{"scope":"desktop","runId":"5dd107f3af7b","component":"desktop-lifecycle","effect.fiberId":133,"effect.logLevel":"INFO"}}],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.app","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"d0b9e0cf7baa4a13","sampled":true,"kind":"internal","startTimeUnixNano":"1779351719003286334","endTimeUnixNano":"1779353647794816250","durationMs":1928791.529916,"attributes":{"scope":"desktop","runId":"5dd107f3af7b"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"desktop.backendManager.stop","traceId":"89162937465dd7ed21fdd25ffc90ba19","spanId":"367e65d566749f1a","parentSpanId":"3f9f56521ebf8493","sampled":true,"kind":"internal","startTimeUnixNano":"1779353647795281459","endTimeUnixNano":"1779353647795332667","durationMs":0.051208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} diff --git a/.t3-home/dev/logs/server.trace.ndjson b/.t3-home/dev/logs/server.trace.ndjson deleted file mode 100644 index 23e703a2a7af..000000000000 --- a/.t3-home/dev/logs/server.trace.ndjson +++ /dev/null @@ -1,1976 +0,0 @@ -{"type":"effect-span","name":"makeTraceDiagnostics","traceId":"e0060b2bce6574267460b8f15dcf058a","spanId":"007ce67b61b7b15d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720185088834","endTimeUnixNano":"1779351720185149709","durationMs":0.060875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeProcessResourceMonitor","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720185234209","endTimeUnixNano":"1779351720185279125","durationMs":0.044916,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeProcessDiagnostics","traceId":"21259c0a7c8d2ab2d8e74ac5c8d50f65","spanId":"e0c492f1fc99481d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720185296459","endTimeUnixNano":"1779351720185323834","durationMs":0.027375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeWithDatabase","traceId":"b8c3650e5a8e86db7c81841a1404a0ca","spanId":"4761c89f24507d9e","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720188921917","endTimeUnixNano":"1779351720189639750","durationMs":0.717833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"768cdb8f940f9b8da0f520aacf20f493","spanId":"8a519b7d52bc1e8e","sampled":true,"kind":"client","startTimeUnixNano":"1779351720189724792","endTimeUnixNano":"1779351720190785584","durationMs":1.060792,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"PRAGMA journal_mode = WAL;"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"6f13a3efffb165f01e51a8c4c0cc62ef","spanId":"1698c90b4a30fa96","sampled":true,"kind":"client","startTimeUnixNano":"1779351720190848292","endTimeUnixNano":"1779351720190908417","durationMs":0.060125,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"PRAGMA foreign_keys = ON;"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"c05b40409e417d16","parentSpanId":"4cc7384a52ecdbe5","sampled":true,"kind":"client","startTimeUnixNano":"1779351720191757625","endTimeUnixNano":"1779351720192241375","durationMs":0.48375,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"CREATE TABLE IF NOT EXISTS \"effect_sql_migrations\" (\n migration_id integer PRIMARY KEY NOT NULL,\n created_at datetime NOT NULL DEFAULT current_timestamp,\n name VARCHAR(255) NOT NULL\n)"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"9fc4f66ada99f99f","parentSpanId":"673600a5f4185709","sampled":true,"kind":"client","startTimeUnixNano":"1779351720192554500","endTimeUnixNano":"1779351720192628084","durationMs":0.073584,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"executeWithoutTransform","db.query.text":"SELECT migration_id, name, created_at FROM \"effect_sql_migrations\" ORDER BY migration_id DESC"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"80d07d78ba0c05bf","parentSpanId":"673600a5f4185709","sampled":true,"kind":"client","startTimeUnixNano":"1779351720192821084","endTimeUnixNano":"1779351720192993125","durationMs":0.172041,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"executeWithoutTransform","db.query.text":"INSERT INTO \"effect_sql_migrations\" (\"migration_id\",\"name\") VALUES (?,?),(?,?),(?,?),(?,?),(?,?),(?,?),(?,?),(?,?),(?,?),(?,?),(?,?),(?,?),(?,?),(?,?),(?,?),(?,?),(?,?),(?,?),(?,?),(?,?),(?,?),(?,?),(?,?),(?,?),(?,?),(?,?),(?,?),(?,?),(?,?),(?,?)"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"57fef04a72195fad","parentSpanId":"ddaf7562061f30ed","sampled":true,"kind":"client","startTimeUnixNano":"1779351720193177209","endTimeUnixNano":"1779351720193275834","durationMs":0.098625,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE TABLE IF NOT EXISTS orchestration_events (\n sequence INTEGER PRIMARY KEY AUTOINCREMENT,\n event_id TEXT NOT NULL UNIQUE,\n aggregate_kind TEXT NOT NULL,\n stream_id TEXT NOT NULL,\n stream_version INTEGER NOT NULL,\n event_type TEXT NOT NULL,\n occurred_at TEXT NOT NULL,\n command_id TEXT,\n causation_event_id TEXT,\n correlation_id TEXT,\n actor_kind TEXT NOT NULL,\n payload_json TEXT NOT NULL,\n metadata_json TEXT NOT NULL\n )\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"618e74b874f7e415","parentSpanId":"ddaf7562061f30ed","sampled":true,"kind":"client","startTimeUnixNano":"1779351720193297834","endTimeUnixNano":"1779351720193344750","durationMs":0.046916,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE UNIQUE INDEX IF NOT EXISTS idx_orch_events_stream_version\n ON orchestration_events(aggregate_kind, stream_id, stream_version)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"8aef68e8f89f7e80","parentSpanId":"ddaf7562061f30ed","sampled":true,"kind":"client","startTimeUnixNano":"1779351720193357084","endTimeUnixNano":"1779351720193391667","durationMs":0.034583,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE INDEX IF NOT EXISTS idx_orch_events_stream_sequence\n ON orchestration_events(aggregate_kind, stream_id, sequence)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"9ef67ea0eb799eec","parentSpanId":"ddaf7562061f30ed","sampled":true,"kind":"client","startTimeUnixNano":"1779351720193400667","endTimeUnixNano":"1779351720193448084","durationMs":0.047417,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE INDEX IF NOT EXISTS idx_orch_events_command_id\n ON orchestration_events(command_id)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"17653dad296eb524","parentSpanId":"ddaf7562061f30ed","sampled":true,"kind":"client","startTimeUnixNano":"1779351720193456625","endTimeUnixNano":"1779351720193496834","durationMs":0.040209,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE INDEX IF NOT EXISTS idx_orch_events_correlation_id\n ON orchestration_events(correlation_id)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"Migrator 1_OrchestrationEvents","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"ddaf7562061f30ed","parentSpanId":"673600a5f4185709","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720193074750","endTimeUnixNano":"1779351720193503875","durationMs":0.429125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"03c64dda99e7b4c8","parentSpanId":"5109c6d7985be208","sampled":true,"kind":"client","startTimeUnixNano":"1779351720193550792","endTimeUnixNano":"1779351720193605209","durationMs":0.054417,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE TABLE IF NOT EXISTS orchestration_command_receipts (\n command_id TEXT PRIMARY KEY,\n aggregate_kind TEXT NOT NULL,\n aggregate_id TEXT NOT NULL,\n accepted_at TEXT NOT NULL,\n result_sequence INTEGER NOT NULL,\n status TEXT NOT NULL,\n error TEXT\n )\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"3ab5ee6a8d9e962c","parentSpanId":"5109c6d7985be208","sampled":true,"kind":"client","startTimeUnixNano":"1779351720193612959","endTimeUnixNano":"1779351720193652542","durationMs":0.039583,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE INDEX IF NOT EXISTS idx_orch_command_receipts_aggregate\n ON orchestration_command_receipts(aggregate_kind, aggregate_id)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"2f74b05ecdfc9375","parentSpanId":"5109c6d7985be208","sampled":true,"kind":"client","startTimeUnixNano":"1779351720193662125","endTimeUnixNano":"1779351720193719709","durationMs":0.057584,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE INDEX IF NOT EXISTS idx_orch_command_receipts_sequence\n ON orchestration_command_receipts(result_sequence)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"Migrator 2_OrchestrationCommandReceipts","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"5109c6d7985be208","parentSpanId":"673600a5f4185709","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720193517375","endTimeUnixNano":"1779351720193727125","durationMs":0.20975,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"cbd2f6febd076043","parentSpanId":"187c7b1fba51b5db","sampled":true,"kind":"client","startTimeUnixNano":"1779351720193769417","endTimeUnixNano":"1779351720193842042","durationMs":0.072625,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE TABLE IF NOT EXISTS checkpoint_diff_blobs (\n thread_id TEXT NOT NULL,\n from_turn_count INTEGER NOT NULL,\n to_turn_count INTEGER NOT NULL,\n diff TEXT NOT NULL,\n created_at TEXT NOT NULL,\n UNIQUE (thread_id, from_turn_count, to_turn_count)\n )\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"b294a0197ec43a5d","parentSpanId":"187c7b1fba51b5db","sampled":true,"kind":"client","startTimeUnixNano":"1779351720193848250","endTimeUnixNano":"1779351720193887084","durationMs":0.038834,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE INDEX IF NOT EXISTS idx_checkpoint_diff_blobs_thread_to_turn\n ON checkpoint_diff_blobs(thread_id, to_turn_count)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"Migrator 3_CheckpointDiffBlobs","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"187c7b1fba51b5db","parentSpanId":"673600a5f4185709","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720193738792","endTimeUnixNano":"1779351720193893250","durationMs":0.154458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"7ad53fe4667577ec","parentSpanId":"18e63bfa06d8e47d","sampled":true,"kind":"client","startTimeUnixNano":"1779351720193931584","endTimeUnixNano":"1779351720194002167","durationMs":0.070583,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE TABLE IF NOT EXISTS provider_session_runtime (\n thread_id TEXT PRIMARY KEY,\n provider_name TEXT NOT NULL,\n adapter_key TEXT NOT NULL,\n runtime_mode TEXT NOT NULL DEFAULT 'full-access',\n status TEXT NOT NULL,\n last_seen_at TEXT NOT NULL,\n resume_cursor_json TEXT,\n runtime_payload_json TEXT\n )\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"963e8cbb913e5b5a","parentSpanId":"18e63bfa06d8e47d","sampled":true,"kind":"client","startTimeUnixNano":"1779351720194010292","endTimeUnixNano":"1779351720194041459","durationMs":0.031167,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE INDEX IF NOT EXISTS idx_provider_session_runtime_status\n ON provider_session_runtime(status)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"43aba3fe02071998","parentSpanId":"18e63bfa06d8e47d","sampled":true,"kind":"client","startTimeUnixNano":"1779351720194046959","endTimeUnixNano":"1779351720194069750","durationMs":0.022791,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE INDEX IF NOT EXISTS idx_provider_session_runtime_provider\n ON provider_session_runtime(provider_name)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"Migrator 4_ProviderSessionRuntime","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"18e63bfa06d8e47d","parentSpanId":"673600a5f4185709","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720193901625","endTimeUnixNano":"1779351720194075917","durationMs":0.174292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"9cf4f0e8119bbf27","parentSpanId":"4be83a69636d7b57","sampled":true,"kind":"client","startTimeUnixNano":"1779351720194135584","endTimeUnixNano":"1779351720194182250","durationMs":0.046666,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE TABLE IF NOT EXISTS projection_projects (\n project_id TEXT PRIMARY KEY,\n title TEXT NOT NULL,\n workspace_root TEXT NOT NULL,\n default_model TEXT,\n scripts_json TEXT NOT NULL,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n deleted_at TEXT\n )\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"bcee87f07cfa1205","parentSpanId":"4be83a69636d7b57","sampled":true,"kind":"client","startTimeUnixNano":"1779351720194187750","endTimeUnixNano":"1779351720194218500","durationMs":0.03075,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE TABLE IF NOT EXISTS projection_threads (\n thread_id TEXT PRIMARY KEY,\n project_id TEXT NOT NULL,\n title TEXT NOT NULL,\n model TEXT NOT NULL,\n branch TEXT,\n worktree_path TEXT,\n latest_turn_id TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n deleted_at TEXT\n )\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"d6928d82872b2e20","parentSpanId":"4be83a69636d7b57","sampled":true,"kind":"client","startTimeUnixNano":"1779351720194223959","endTimeUnixNano":"1779351720194257542","durationMs":0.033583,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE TABLE IF NOT EXISTS projection_thread_messages (\n message_id TEXT PRIMARY KEY,\n thread_id TEXT NOT NULL,\n turn_id TEXT,\n role TEXT NOT NULL,\n text TEXT NOT NULL,\n is_streaming INTEGER NOT NULL,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL\n )\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"87b96af986701c13","parentSpanId":"4be83a69636d7b57","sampled":true,"kind":"client","startTimeUnixNano":"1779351720194262959","endTimeUnixNano":"1779351720194310209","durationMs":0.04725,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE TABLE IF NOT EXISTS projection_thread_activities (\n activity_id TEXT PRIMARY KEY,\n thread_id TEXT NOT NULL,\n turn_id TEXT,\n tone TEXT NOT NULL,\n kind TEXT NOT NULL,\n summary TEXT NOT NULL,\n payload_json TEXT NOT NULL,\n created_at TEXT NOT NULL\n )\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"6c00db5e71044777","parentSpanId":"4be83a69636d7b57","sampled":true,"kind":"client","startTimeUnixNano":"1779351720194315500","endTimeUnixNano":"1779351720194415625","durationMs":0.100125,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE TABLE IF NOT EXISTS projection_thread_sessions (\n thread_id TEXT PRIMARY KEY,\n status TEXT NOT NULL,\n provider_name TEXT,\n provider_session_id TEXT,\n provider_thread_id TEXT,\n active_turn_id TEXT,\n last_error TEXT,\n updated_at TEXT NOT NULL\n )\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"d17e0a5c79882abf","parentSpanId":"4be83a69636d7b57","sampled":true,"kind":"client","startTimeUnixNano":"1779351720194427667","endTimeUnixNano":"1779351720194497209","durationMs":0.069542,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE TABLE IF NOT EXISTS projection_turns (\n row_id INTEGER PRIMARY KEY AUTOINCREMENT,\n thread_id TEXT NOT NULL,\n turn_id TEXT,\n pending_message_id TEXT,\n assistant_message_id TEXT,\n state TEXT NOT NULL,\n requested_at TEXT NOT NULL,\n started_at TEXT,\n completed_at TEXT,\n checkpoint_turn_count INTEGER,\n checkpoint_ref TEXT,\n checkpoint_status TEXT,\n checkpoint_files_json TEXT NOT NULL,\n UNIQUE (thread_id, turn_id),\n UNIQUE (thread_id, checkpoint_turn_count)\n )\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"d52af0a19c2096ff","parentSpanId":"4be83a69636d7b57","sampled":true,"kind":"client","startTimeUnixNano":"1779351720194782542","endTimeUnixNano":"1779351720194828625","durationMs":0.046083,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE TABLE IF NOT EXISTS projection_pending_approvals (\n request_id TEXT PRIMARY KEY,\n thread_id TEXT NOT NULL,\n turn_id TEXT,\n status TEXT NOT NULL,\n decision TEXT,\n created_at TEXT NOT NULL,\n resolved_at TEXT\n )\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"85b01818489bfe00","parentSpanId":"4be83a69636d7b57","sampled":true,"kind":"client","startTimeUnixNano":"1779351720194836459","endTimeUnixNano":"1779351720194875417","durationMs":0.038958,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE TABLE IF NOT EXISTS projection_state (\n projector TEXT PRIMARY KEY,\n last_applied_sequence INTEGER NOT NULL,\n updated_at TEXT NOT NULL\n )\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"83c1ccc09ddf84ae","parentSpanId":"4be83a69636d7b57","sampled":true,"kind":"client","startTimeUnixNano":"1779351720194882167","endTimeUnixNano":"1779351720194914000","durationMs":0.031833,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE INDEX IF NOT EXISTS idx_projection_projects_updated_at\n ON projection_projects(updated_at)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"61e2d40cec61957d","parentSpanId":"4be83a69636d7b57","sampled":true,"kind":"client","startTimeUnixNano":"1779351720194920542","endTimeUnixNano":"1779351720194945209","durationMs":0.024667,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE INDEX IF NOT EXISTS idx_projection_threads_project_id\n ON projection_threads(project_id)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"53312b66bd6bb7c6","parentSpanId":"4be83a69636d7b57","sampled":true,"kind":"client","startTimeUnixNano":"1779351720194951209","endTimeUnixNano":"1779351720194976125","durationMs":0.024916,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE INDEX IF NOT EXISTS idx_projection_thread_messages_thread_created\n ON projection_thread_messages(thread_id, created_at)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"47cc782f8ab438ea","parentSpanId":"4be83a69636d7b57","sampled":true,"kind":"client","startTimeUnixNano":"1779351720194986417","endTimeUnixNano":"1779351720195015250","durationMs":0.028833,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE INDEX IF NOT EXISTS idx_projection_thread_activities_thread_created\n ON projection_thread_activities(thread_id, created_at)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"0368dff0bc6ede9f","parentSpanId":"4be83a69636d7b57","sampled":true,"kind":"client","startTimeUnixNano":"1779351720195020542","endTimeUnixNano":"1779351720195044959","durationMs":0.024417,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE INDEX IF NOT EXISTS idx_projection_thread_sessions_provider_session\n ON projection_thread_sessions(provider_session_id)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"28f0283359b45d7c","parentSpanId":"4be83a69636d7b57","sampled":true,"kind":"client","startTimeUnixNano":"1779351720195050292","endTimeUnixNano":"1779351720195079625","durationMs":0.029333,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE INDEX IF NOT EXISTS idx_projection_turns_thread_requested\n ON projection_turns(thread_id, requested_at)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"70df2d52775851bd","parentSpanId":"4be83a69636d7b57","sampled":true,"kind":"client","startTimeUnixNano":"1779351720195085042","endTimeUnixNano":"1779351720195112209","durationMs":0.027167,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE INDEX IF NOT EXISTS idx_projection_turns_thread_checkpoint_completed\n ON projection_turns(thread_id, checkpoint_turn_count, completed_at)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"3bea596bd34c361d","parentSpanId":"4be83a69636d7b57","sampled":true,"kind":"client","startTimeUnixNano":"1779351720195118167","endTimeUnixNano":"1779351720195141459","durationMs":0.023292,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE INDEX IF NOT EXISTS idx_projection_pending_approvals_thread_status\n ON projection_pending_approvals(thread_id, status)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"Migrator 5_Projections","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"4be83a69636d7b57","parentSpanId":"673600a5f4185709","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720194085167","endTimeUnixNano":"1779351720195149500","durationMs":1.064333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"e121f632801948dc","parentSpanId":"b51121c84579c13c","sampled":true,"kind":"client","startTimeUnixNano":"1779351720195205459","endTimeUnixNano":"1779351720195339292","durationMs":0.133833,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n ALTER TABLE projection_thread_sessions\n ADD COLUMN runtime_mode TEXT NOT NULL DEFAULT 'full-access'\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"b5ad37351746dc94","parentSpanId":"b51121c84579c13c","sampled":true,"kind":"client","startTimeUnixNano":"1779351720195352542","endTimeUnixNano":"1779351720195370709","durationMs":0.018167,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n UPDATE projection_thread_sessions\n SET runtime_mode = ?\n WHERE runtime_mode IS NULL\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"Migrator 6_ProjectionThreadSessionRuntimeModeColumns","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"b51121c84579c13c","parentSpanId":"673600a5f4185709","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720195167500","endTimeUnixNano":"1779351720195376667","durationMs":0.209167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"5321e3aeff63a8c8","parentSpanId":"8742a46d3d874541","sampled":true,"kind":"client","startTimeUnixNano":"1779351720195406375","endTimeUnixNano":"1779351720195500375","durationMs":0.094,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n ALTER TABLE projection_thread_messages\n ADD COLUMN attachments_json TEXT\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"Migrator 7_ProjectionThreadMessageAttachments","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"8742a46d3d874541","parentSpanId":"673600a5f4185709","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720195384917","endTimeUnixNano":"1779351720195506334","durationMs":0.121417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"3248dde56bdf04a1","parentSpanId":"23bf6688c10c76bc","sampled":true,"kind":"client","startTimeUnixNano":"1779351720195538042","endTimeUnixNano":"1779351720195624792","durationMs":0.08675,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n ALTER TABLE projection_thread_activities\n ADD COLUMN sequence INTEGER\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"0d73401990a70811","parentSpanId":"23bf6688c10c76bc","sampled":true,"kind":"client","startTimeUnixNano":"1779351720195630042","endTimeUnixNano":"1779351720195660375","durationMs":0.030333,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE INDEX IF NOT EXISTS idx_projection_thread_activities_thread_sequence\n ON projection_thread_activities(thread_id, sequence)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"Migrator 8_ProjectionThreadActivitySequence","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"23bf6688c10c76bc","parentSpanId":"673600a5f4185709","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720195515667","endTimeUnixNano":"1779351720195666209","durationMs":0.150542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"Migrator 9_ProviderSessionRuntimeMode","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"6bd9cb1018741856","parentSpanId":"673600a5f4185709","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720195676459","endTimeUnixNano":"1779351720195696375","durationMs":0.019916,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"57a82393c671b017","parentSpanId":"32b7157762b65a55","sampled":true,"kind":"client","startTimeUnixNano":"1779351720195731834","endTimeUnixNano":"1779351720195829209","durationMs":0.097375,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n ALTER TABLE projection_threads\n ADD COLUMN runtime_mode TEXT NOT NULL DEFAULT 'full-access'\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"115be85f8a3d1b86","parentSpanId":"32b7157762b65a55","sampled":true,"kind":"client","startTimeUnixNano":"1779351720195834959","endTimeUnixNano":"1779351720195850250","durationMs":0.015291,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n UPDATE projection_threads\n SET runtime_mode = 'full-access'\n WHERE runtime_mode IS NULL\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"Migrator 10_ProjectionThreadsRuntimeMode","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"32b7157762b65a55","parentSpanId":"673600a5f4185709","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720195705334","endTimeUnixNano":"1779351720195855834","durationMs":0.1505,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"9db4b0862667a8af","parentSpanId":"15aaf872bfc28886","sampled":true,"kind":"client","startTimeUnixNano":"1779351720195882167","endTimeUnixNano":"1779351720195899792","durationMs":0.017625,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n UPDATE orchestration_events\n SET payload_json = json_set(payload_json, '$.runtimeMode', 'full-access')\n WHERE event_type = 'thread.created'\n AND json_type(payload_json, '$.runtimeMode') IS NULL\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"Migrator 11_OrchestrationThreadCreatedRuntimeMode","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"15aaf872bfc28886","parentSpanId":"673600a5f4185709","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720195862917","endTimeUnixNano":"1779351720195905667","durationMs":0.04275,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"92facbabe7779574","parentSpanId":"cfc7142b18060bbf","sampled":true,"kind":"client","startTimeUnixNano":"1779351720195927667","endTimeUnixNano":"1779351720196016709","durationMs":0.089042,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n ALTER TABLE projection_threads\n ADD COLUMN interaction_mode TEXT NOT NULL DEFAULT 'default'\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"Migrator 12_ProjectionThreadsInteractionMode","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"cfc7142b18060bbf","parentSpanId":"673600a5f4185709","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720195911334","endTimeUnixNano":"1779351720196022417","durationMs":0.111083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"c48875a270500843","parentSpanId":"d975d144bebfbe47","sampled":true,"kind":"client","startTimeUnixNano":"1779351720196046792","endTimeUnixNano":"1779351720196082334","durationMs":0.035542,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE TABLE IF NOT EXISTS projection_thread_proposed_plans (\n plan_id TEXT PRIMARY KEY,\n thread_id TEXT NOT NULL,\n turn_id TEXT,\n plan_markdown TEXT NOT NULL,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL\n )\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"0261ee201b40cf6f","parentSpanId":"d975d144bebfbe47","sampled":true,"kind":"client","startTimeUnixNano":"1779351720196087500","endTimeUnixNano":"1779351720196113417","durationMs":0.025917,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE INDEX IF NOT EXISTS idx_projection_thread_proposed_plans_thread_created\n ON projection_thread_proposed_plans(thread_id, created_at)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"Migrator 13_ProjectionThreadProposedPlans","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"d975d144bebfbe47","parentSpanId":"673600a5f4185709","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720196028084","endTimeUnixNano":"1779351720196119042","durationMs":0.090958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"188770661f7bd185","parentSpanId":"4a9c38b05780d583","sampled":true,"kind":"client","startTimeUnixNano":"1779351720196141917","endTimeUnixNano":"1779351720196231750","durationMs":0.089833,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n ALTER TABLE projection_thread_proposed_plans\n ADD COLUMN implemented_at TEXT\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"cf3bfd9c3af18591","parentSpanId":"4a9c38b05780d583","sampled":true,"kind":"client","startTimeUnixNano":"1779351720196236709","endTimeUnixNano":"1779351720196324000","durationMs":0.087291,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n ALTER TABLE projection_thread_proposed_plans\n ADD COLUMN implementation_thread_id TEXT\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"Migrator 14_ProjectionThreadProposedPlanImplementation","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"4a9c38b05780d583","parentSpanId":"673600a5f4185709","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720196124417","endTimeUnixNano":"1779351720196412375","durationMs":0.287958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"0a4722b98e1d3cff","parentSpanId":"2c079749ca1d8d95","sampled":true,"kind":"client","startTimeUnixNano":"1779351720196437417","endTimeUnixNano":"1779351720196540084","durationMs":0.102667,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n ALTER TABLE projection_turns\n ADD COLUMN source_proposed_plan_thread_id TEXT\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"b3d59e53e7a1b4fe","parentSpanId":"2c079749ca1d8d95","sampled":true,"kind":"client","startTimeUnixNano":"1779351720196545042","endTimeUnixNano":"1779351720196738667","durationMs":0.193625,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n ALTER TABLE projection_turns\n ADD COLUMN source_proposed_plan_id TEXT\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"Migrator 15_ProjectionTurnsSourceProposedPlan","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"2c079749ca1d8d95","parentSpanId":"673600a5f4185709","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720196419000","endTimeUnixNano":"1779351720196745209","durationMs":0.326209,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"2baad41782a2d215","parentSpanId":"6abf340a526cd500","sampled":true,"kind":"client","startTimeUnixNano":"1779351720196809125","endTimeUnixNano":"1779351720196899667","durationMs":0.090542,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n ALTER TABLE projection_projects\n ADD COLUMN default_model_selection_json TEXT\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"472ac9d394c690b1","parentSpanId":"6abf340a526cd500","sampled":true,"kind":"client","startTimeUnixNano":"1779351720196904625","endTimeUnixNano":"1779351720196925375","durationMs":0.02075,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n UPDATE projection_projects\n SET default_model_selection_json = CASE\n WHEN default_model IS NULL THEN NULL\n ELSE json_object(\n 'provider',\n CASE\n WHEN lower(default_model) LIKE '%claude%' THEN 'claudeAgent'\n ELSE 'codex'\n END,\n 'model',\n default_model\n )\n END\n WHERE default_model_selection_json IS NULL\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"b5a244dc53ea9af9","parentSpanId":"6abf340a526cd500","sampled":true,"kind":"client","startTimeUnixNano":"1779351720196930500","endTimeUnixNano":"1779351720197019375","durationMs":0.088875,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n ALTER TABLE projection_threads\n ADD COLUMN model_selection_json TEXT\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"5e090ad50098a750","parentSpanId":"6abf340a526cd500","sampled":true,"kind":"client","startTimeUnixNano":"1779351720197024334","endTimeUnixNano":"1779351720197049875","durationMs":0.025541,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n UPDATE projection_threads\n SET model_selection_json = json_object(\n 'provider',\n COALESCE(\n (\n SELECT provider_name\n FROM projection_thread_sessions\n WHERE projection_thread_sessions.thread_id = projection_threads.thread_id\n ),\n CASE\n WHEN lower(model) LIKE '%claude%' THEN 'claudeAgent'\n ELSE 'codex'\n END,\n 'codex'\n ),\n 'model',\n model\n )\n WHERE model_selection_json IS NULL\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"799b797826c04e6b","parentSpanId":"6abf340a526cd500","sampled":true,"kind":"client","startTimeUnixNano":"1779351720197054959","endTimeUnixNano":"1779351720197457584","durationMs":0.402625,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n ALTER TABLE projection_projects\n DROP COLUMN default_model\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"733e33b15e5698a4","parentSpanId":"6abf340a526cd500","sampled":true,"kind":"client","startTimeUnixNano":"1779351720197463042","endTimeUnixNano":"1779351720197825542","durationMs":0.3625,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n ALTER TABLE projection_threads\n DROP COLUMN model\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"70ddbbd4aa313aef","parentSpanId":"6abf340a526cd500","sampled":true,"kind":"client","startTimeUnixNano":"1779351720197830834","endTimeUnixNano":"1779351720197884500","durationMs":0.053666,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n UPDATE orchestration_events\n SET payload_json = CASE\n WHEN json_type(payload_json, '$.defaultModel') = 'null' THEN json_remove(\n json_set(payload_json, '$.defaultModelSelection', json('null')),\n '$.defaultProvider',\n '$.defaultModel',\n '$.defaultModelOptions'\n )\n ELSE json_remove(\n json_set(\n payload_json,\n '$.defaultModelSelection',\n json_patch(\n json_object(\n 'provider',\n CASE\n WHEN json_extract(payload_json, '$.defaultProvider') IS NOT NULL\n THEN json_extract(payload_json, '$.defaultProvider')\n WHEN lower(json_extract(payload_json, '$.defaultModel')) LIKE '%claude%'\n THEN 'claudeAgent'\n ELSE 'codex'\n END,\n 'model',\n json_extract(payload_json, '$.defaultModel')\n ),\n CASE\n WHEN json_type(payload_json, '$.defaultModelOptions') IS NULL THEN '{}'\n WHEN json_type(payload_json, '$.defaultModelOptions.codex') IS NOT NULL\n OR json_type(payload_json, '$.defaultModelOptions.claudeAgent') IS NOT NULL\n THEN CASE\n WHEN (\n CASE\n WHEN json_extract(payload_json, '$.defaultProvider') IS NOT NULL\n THEN json_extract(payload_json, '$.defaultProvider')\n WHEN lower(json_extract(payload_json, '$.defaultModel')) LIKE '%claude%'\n THEN 'claudeAgent'\n ELSE 'codex'\n END\n ) = 'claudeAgent'\n THEN CASE\n WHEN json_type(payload_json, '$.defaultModelOptions.claudeAgent') IS NOT NULL\n THEN json_object(\n 'options',\n json(json_extract(payload_json, '$.defaultModelOptions.claudeAgent'))\n )\n WHEN json_type(payload_json, '$.defaultModelOptions.codex') IS NOT NULL\n THEN json_object(\n 'options',\n json(json_extract(payload_json, '$.defaultModelOptions.codex'))\n )\n ELSE '{}'\n END\n ELSE CASE\n WHEN json_type(payload_json, '$.defaultModelOptions.codex') IS NOT NULL\n THEN json_object(\n 'options',\n json(json_extract(payload_json, '$.defaultModelOptions.codex'))\n )\n WHEN json_type(payload_json, '$.defaultModelOptions.claudeAgent') IS NOT NULL\n THEN json_object(\n 'options',\n json(json_extract(payload_json, '$.defaultModelOptions.claudeAgent'))\n )\n ELSE '{}'\n END\n END\n ELSE json_object(\n 'options',\n json(json_extract(payload_json, '$.defaultModelOptions'))\n )\n END\n )\n ),\n '$.defaultProvider',\n '$.defaultModel',\n '$.defaultModelOptions'\n )\n END\n WHERE event_type IN ('project.created', 'project.meta-updated')\n AND json_type(payload_json, '$.defaultModelSelection') IS NULL\n AND json_type(payload_json, '$.defaultModel') IS NOT NULL\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"a4b57e1034f78a30","parentSpanId":"6abf340a526cd500","sampled":true,"kind":"client","startTimeUnixNano":"1779351720197892042","endTimeUnixNano":"1779351720197941625","durationMs":0.049583,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n UPDATE orchestration_events\n SET payload_json = json_remove(\n json_set(\n payload_json,\n '$.modelSelection',\n json_patch(\n json_object(\n 'provider',\n CASE\n WHEN json_extract(payload_json, '$.provider') IS NOT NULL\n THEN json_extract(payload_json, '$.provider')\n WHEN lower(json_extract(payload_json, '$.model')) LIKE '%claude%'\n THEN 'claudeAgent'\n ELSE 'codex'\n END,\n 'model',\n json_extract(payload_json, '$.model')\n ),\n CASE\n WHEN json_type(payload_json, '$.modelOptions') IS NULL THEN '{}'\n WHEN json_type(payload_json, '$.modelOptions.codex') IS NOT NULL\n OR json_type(payload_json, '$.modelOptions.claudeAgent') IS NOT NULL\n THEN CASE\n WHEN (\n CASE\n WHEN json_extract(payload_json, '$.provider') IS NOT NULL\n THEN json_extract(payload_json, '$.provider')\n WHEN lower(json_extract(payload_json, '$.model')) LIKE '%claude%'\n THEN 'claudeAgent'\n ELSE 'codex'\n END\n ) = 'claudeAgent'\n THEN CASE\n WHEN json_type(payload_json, '$.modelOptions.claudeAgent') IS NOT NULL\n THEN json_object(\n 'options',\n json(json_extract(payload_json, '$.modelOptions.claudeAgent'))\n )\n WHEN json_type(payload_json, '$.modelOptions.codex') IS NOT NULL\n THEN json_object(\n 'options',\n json(json_extract(payload_json, '$.modelOptions.codex'))\n )\n ELSE '{}'\n END\n ELSE CASE\n WHEN json_type(payload_json, '$.modelOptions.codex') IS NOT NULL\n THEN json_object(\n 'options',\n json(json_extract(payload_json, '$.modelOptions.codex'))\n )\n WHEN json_type(payload_json, '$.modelOptions.claudeAgent') IS NOT NULL\n THEN json_object(\n 'options',\n json(json_extract(payload_json, '$.modelOptions.claudeAgent'))\n )\n ELSE '{}'\n END\n END\n ELSE json_object('options', json(json_extract(payload_json, '$.modelOptions')))\n END\n )\n ),\n '$.provider',\n '$.model',\n '$.modelOptions'\n )\n WHERE event_type IN ('thread.created', 'thread.meta-updated', 'thread.turn-start-requested')\n AND json_type(payload_json, '$.modelSelection') IS NULL\n AND json_type(payload_json, '$.model') IS NOT NULL\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"64c74cae18820d47","parentSpanId":"6abf340a526cd500","sampled":true,"kind":"client","startTimeUnixNano":"1779351720197949125","endTimeUnixNano":"1779351720197968250","durationMs":0.019125,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n UPDATE orchestration_events\n SET payload_json = json_set(\n payload_json,\n '$.modelSelection',\n json(json_object('provider', 'codex', 'model', 'gpt-5.4'))\n )\n WHERE event_type = 'thread.created'\n AND json_type(payload_json, '$.modelSelection') IS NULL\n AND json_type(payload_json, '$.model') IS NULL\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"Migrator 16_CanonicalizeModelSelections","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"6abf340a526cd500","parentSpanId":"673600a5f4185709","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720196751417","endTimeUnixNano":"1779351720197974459","durationMs":1.223042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"3cdf3036d585a663","parentSpanId":"5e113ee5451a2f68","sampled":true,"kind":"client","startTimeUnixNano":"1779351720198004375","endTimeUnixNano":"1779351720198030584","durationMs":0.026209,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n PRAGMA table_info(projection_threads)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"85005da783d82fa0","parentSpanId":"5e113ee5451a2f68","sampled":true,"kind":"client","startTimeUnixNano":"1779351720198041834","endTimeUnixNano":"1779351720198143959","durationMs":0.102125,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n ALTER TABLE projection_threads\n ADD COLUMN archived_at TEXT\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"Migrator 17_ProjectionThreadsArchivedAt","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"5e113ee5451a2f68","parentSpanId":"673600a5f4185709","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720197980917","endTimeUnixNano":"1779351720198149834","durationMs":0.168917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"1eaa0acbbc82b441","parentSpanId":"ac9f0af17affe21a","sampled":true,"kind":"client","startTimeUnixNano":"1779351720198173334","endTimeUnixNano":"1779351720198207584","durationMs":0.03425,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE INDEX IF NOT EXISTS idx_projection_threads_project_archived_at\n ON projection_threads(project_id, archived_at)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"Migrator 18_ProjectionThreadsArchivedAtIndex","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"ac9f0af17affe21a","parentSpanId":"673600a5f4185709","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720198155500","endTimeUnixNano":"1779351720198213459","durationMs":0.057959,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"0593eaac2e48d32c","parentSpanId":"d6176e7af17ebf23","sampled":true,"kind":"client","startTimeUnixNano":"1779351720198237167","endTimeUnixNano":"1779351720198265042","durationMs":0.027875,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE INDEX IF NOT EXISTS idx_projection_projects_workspace_root_deleted_at\n ON projection_projects(workspace_root, deleted_at)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"b44cd1ca2a9c483d","parentSpanId":"d6176e7af17ebf23","sampled":true,"kind":"client","startTimeUnixNano":"1779351720198269417","endTimeUnixNano":"1779351720198294667","durationMs":0.02525,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE INDEX IF NOT EXISTS idx_projection_threads_project_deleted_created\n ON projection_threads(project_id, deleted_at, created_at)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"Migrator 19_ProjectionSnapshotLookupIndexes","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"d6176e7af17ebf23","parentSpanId":"673600a5f4185709","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720198218875","endTimeUnixNano":"1779351720198302375","durationMs":0.0835,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"2ac6b3fd69f29f65","parentSpanId":"2ec9e2fd18391d3d","sampled":true,"kind":"client","startTimeUnixNano":"1779351720198348792","endTimeUnixNano":"1779351720198402959","durationMs":0.054167,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE TABLE IF NOT EXISTS auth_pairing_links (\n id TEXT PRIMARY KEY,\n credential TEXT NOT NULL UNIQUE,\n method TEXT NOT NULL,\n role TEXT NOT NULL,\n subject TEXT NOT NULL,\n created_at TEXT NOT NULL,\n expires_at TEXT NOT NULL,\n consumed_at TEXT,\n revoked_at TEXT\n )\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"babb6733fb098762","parentSpanId":"2ec9e2fd18391d3d","sampled":true,"kind":"client","startTimeUnixNano":"1779351720198408417","endTimeUnixNano":"1779351720198447459","durationMs":0.039042,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE INDEX IF NOT EXISTS idx_auth_pairing_links_active\n ON auth_pairing_links(revoked_at, consumed_at, expires_at)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"882679aa124d7ff8","parentSpanId":"2ec9e2fd18391d3d","sampled":true,"kind":"client","startTimeUnixNano":"1779351720198452417","endTimeUnixNano":"1779351720198505625","durationMs":0.053208,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE TABLE IF NOT EXISTS auth_sessions (\n session_id TEXT PRIMARY KEY,\n subject TEXT NOT NULL,\n role TEXT NOT NULL,\n method TEXT NOT NULL,\n issued_at TEXT NOT NULL,\n expires_at TEXT NOT NULL,\n revoked_at TEXT\n )\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"13a4e9aeb12bf13a","parentSpanId":"2ec9e2fd18391d3d","sampled":true,"kind":"client","startTimeUnixNano":"1779351720198510667","endTimeUnixNano":"1779351720198547125","durationMs":0.036458,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE INDEX IF NOT EXISTS idx_auth_sessions_active\n ON auth_sessions(revoked_at, expires_at, issued_at)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"Migrator 20_AuthAccessManagement","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"2ec9e2fd18391d3d","parentSpanId":"673600a5f4185709","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720198309292","endTimeUnixNano":"1779351720198552875","durationMs":0.243583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"b628fd4b5199dc7f","parentSpanId":"1bc3dfe27e66b9d2","sampled":true,"kind":"client","startTimeUnixNano":"1779351720198596209","endTimeUnixNano":"1779351720198616959","durationMs":0.02075,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n PRAGMA table_info(auth_pairing_links)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"2bb293c4f5d896dd","parentSpanId":"1bc3dfe27e66b9d2","sampled":true,"kind":"client","startTimeUnixNano":"1779351720198626000","endTimeUnixNano":"1779351720198761875","durationMs":0.135875,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n ALTER TABLE auth_pairing_links\n ADD COLUMN label TEXT\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"614d2decc7fc4e78","parentSpanId":"1bc3dfe27e66b9d2","sampled":true,"kind":"client","startTimeUnixNano":"1779351720198766917","endTimeUnixNano":"1779351720198783917","durationMs":0.017,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n PRAGMA table_info(auth_sessions)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"755db0fadab0dfde","parentSpanId":"1bc3dfe27e66b9d2","sampled":true,"kind":"client","startTimeUnixNano":"1779351720198791667","endTimeUnixNano":"1779351720198901125","durationMs":0.109458,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n ALTER TABLE auth_sessions\n ADD COLUMN client_label TEXT\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"f0deaebbf647f99e","parentSpanId":"1bc3dfe27e66b9d2","sampled":true,"kind":"client","startTimeUnixNano":"1779351720198908834","endTimeUnixNano":"1779351720199021875","durationMs":0.113041,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n ALTER TABLE auth_sessions\n ADD COLUMN client_ip_address TEXT\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"7a3cad0c78f9d4c0","parentSpanId":"1bc3dfe27e66b9d2","sampled":true,"kind":"client","startTimeUnixNano":"1779351720199116292","endTimeUnixNano":"1779351720199220334","durationMs":0.104042,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n ALTER TABLE auth_sessions\n ADD COLUMN client_user_agent TEXT\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"ea9ecb63234a50a5","parentSpanId":"1bc3dfe27e66b9d2","sampled":true,"kind":"client","startTimeUnixNano":"1779351720199228417","endTimeUnixNano":"1779351720199332875","durationMs":0.104458,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n ALTER TABLE auth_sessions\n ADD COLUMN client_device_type TEXT NOT NULL DEFAULT 'unknown'\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"5b7cf23ae160f4f2","parentSpanId":"1bc3dfe27e66b9d2","sampled":true,"kind":"client","startTimeUnixNano":"1779351720199340334","endTimeUnixNano":"1779351720199485375","durationMs":0.145041,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n ALTER TABLE auth_sessions\n ADD COLUMN client_os TEXT\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"b135a34d72c1baaf","parentSpanId":"1bc3dfe27e66b9d2","sampled":true,"kind":"client","startTimeUnixNano":"1779351720199493417","endTimeUnixNano":"1779351720199597084","durationMs":0.103667,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n ALTER TABLE auth_sessions\n ADD COLUMN client_browser TEXT\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"Migrator 21_AuthSessionClientMetadata","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"1bc3dfe27e66b9d2","parentSpanId":"673600a5f4185709","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720198558625","endTimeUnixNano":"1779351720199603167","durationMs":1.044542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"ec206da9114ded24","parentSpanId":"7e62f8f4c71f05df","sampled":true,"kind":"client","startTimeUnixNano":"1779351720199634084","endTimeUnixNano":"1779351720199683875","durationMs":0.049791,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n PRAGMA table_info(auth_sessions)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"2bd2e2b5d6682d9a","parentSpanId":"7e62f8f4c71f05df","sampled":true,"kind":"client","startTimeUnixNano":"1779351720199698709","endTimeUnixNano":"1779351720199802750","durationMs":0.104041,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n ALTER TABLE auth_sessions\n ADD COLUMN last_connected_at TEXT\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"Migrator 22_AuthSessionLastConnectedAt","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"7e62f8f4c71f05df","parentSpanId":"673600a5f4185709","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720199610292","endTimeUnixNano":"1779351720199808375","durationMs":0.198083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"52e851be91ef1fa7","parentSpanId":"d0b42e25f0f8bf51","sampled":true,"kind":"client","startTimeUnixNano":"1779351720199847959","endTimeUnixNano":"1779351720199970709","durationMs":0.12275,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n ALTER TABLE projection_threads\n ADD COLUMN latest_user_message_at TEXT\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"79033fd3259be4b4","parentSpanId":"d0b42e25f0f8bf51","sampled":true,"kind":"client","startTimeUnixNano":"1779351720199976667","endTimeUnixNano":"1779351720200106709","durationMs":0.130042,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n ALTER TABLE projection_threads\n ADD COLUMN pending_approval_count INTEGER NOT NULL DEFAULT 0\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"fe62e491f025c7a5","parentSpanId":"d0b42e25f0f8bf51","sampled":true,"kind":"client","startTimeUnixNano":"1779351720200112417","endTimeUnixNano":"1779351720200218542","durationMs":0.106125,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n ALTER TABLE projection_threads\n ADD COLUMN pending_user_input_count INTEGER NOT NULL DEFAULT 0\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"741df8b6b5df3507","parentSpanId":"d0b42e25f0f8bf51","sampled":true,"kind":"client","startTimeUnixNano":"1779351720200223959","endTimeUnixNano":"1779351720200329834","durationMs":0.105875,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n ALTER TABLE projection_threads\n ADD COLUMN has_actionable_proposed_plan INTEGER NOT NULL DEFAULT 0\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"Migrator 23_ProjectionThreadShellSummary","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"d0b42e25f0f8bf51","parentSpanId":"673600a5f4185709","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720199813750","endTimeUnixNano":"1779351720200334875","durationMs":0.521125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"771cc0eab847110f","parentSpanId":"1c37edc71d55bc72","sampled":true,"kind":"client","startTimeUnixNano":"1779351720200387167","endTimeUnixNano":"1779351720200449500","durationMs":0.062333,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n INSERT OR IGNORE INTO projection_pending_approvals (\n request_id,\n thread_id,\n turn_id,\n status,\n decision,\n created_at,\n resolved_at\n )\n SELECT\n requested.request_id,\n requested.thread_id,\n requested.turn_id,\n 'pending',\n NULL,\n requested.created_at,\n NULL\n FROM (\n SELECT\n json_extract(payload_json, '$.requestId') AS request_id,\n thread_id,\n turn_id,\n created_at,\n ROW_NUMBER() OVER (\n PARTITION BY json_extract(payload_json, '$.requestId')\n ORDER BY created_at ASC, activity_id ASC\n ) AS row_number\n FROM projection_thread_activities\n WHERE kind = 'approval.requested'\n AND json_extract(payload_json, '$.requestId') IS NOT NULL\n ) AS requested\n WHERE requested.row_number = 1\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"01a411e6f5c91cda","parentSpanId":"1c37edc71d55bc72","sampled":true,"kind":"client","startTimeUnixNano":"1779351720200455250","endTimeUnixNano":"1779351720200553750","durationMs":0.0985,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n WITH latest_resolutions AS (\n SELECT\n resolved.request_id,\n resolved.resolved_at,\n resolved.decision\n FROM (\n SELECT\n json_extract(payload_json, '$.requestId') AS request_id,\n created_at AS resolved_at,\n CASE\n WHEN json_extract(payload_json, '$.decision') IN (\n 'accept',\n 'acceptForSession',\n 'decline',\n 'cancel'\n )\n THEN json_extract(payload_json, '$.decision')\n ELSE NULL\n END AS decision,\n ROW_NUMBER() OVER (\n PARTITION BY json_extract(payload_json, '$.requestId')\n ORDER BY created_at DESC, activity_id DESC\n ) AS row_number\n FROM projection_thread_activities\n WHERE kind = 'approval.resolved'\n AND json_extract(payload_json, '$.requestId') IS NOT NULL\n ) AS resolved\n WHERE resolved.row_number = 1\n )\n UPDATE projection_pending_approvals\n SET\n status = 'resolved',\n decision = (\n SELECT latest_resolutions.decision\n FROM latest_resolutions\n WHERE latest_resolutions.request_id = projection_pending_approvals.request_id\n ),\n resolved_at = (\n SELECT latest_resolutions.resolved_at\n FROM latest_resolutions\n WHERE latest_resolutions.request_id = projection_pending_approvals.request_id\n )\n WHERE EXISTS (\n SELECT 1\n FROM latest_resolutions\n WHERE latest_resolutions.request_id = projection_pending_approvals.request_id\n )\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"e4cb3f30df0c0a24","parentSpanId":"1c37edc71d55bc72","sampled":true,"kind":"client","startTimeUnixNano":"1779351720200559459","endTimeUnixNano":"1779351720200630417","durationMs":0.070958,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n WITH latest_response_events AS (\n SELECT\n response.request_id,\n response.resolved_at,\n response.decision\n FROM (\n SELECT\n json_extract(payload_json, '$.requestId') AS request_id,\n occurred_at AS resolved_at,\n CASE\n WHEN json_extract(payload_json, '$.decision') IN (\n 'accept',\n 'acceptForSession',\n 'decline',\n 'cancel'\n )\n THEN json_extract(payload_json, '$.decision')\n ELSE NULL\n END AS decision,\n ROW_NUMBER() OVER (\n PARTITION BY json_extract(payload_json, '$.requestId')\n ORDER BY occurred_at DESC, sequence DESC\n ) AS row_number\n FROM orchestration_events\n WHERE event_type = 'thread.approval-response-requested'\n AND json_extract(payload_json, '$.requestId') IS NOT NULL\n ) AS response\n WHERE response.row_number = 1\n )\n UPDATE projection_pending_approvals\n SET\n status = 'resolved',\n decision = (\n SELECT latest_response_events.decision\n FROM latest_response_events\n WHERE latest_response_events.request_id = projection_pending_approvals.request_id\n ),\n resolved_at = (\n SELECT latest_response_events.resolved_at\n FROM latest_response_events\n WHERE latest_response_events.request_id = projection_pending_approvals.request_id\n )\n WHERE EXISTS (\n SELECT 1\n FROM latest_response_events\n WHERE latest_response_events.request_id = projection_pending_approvals.request_id\n )\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"5b7ecf864a7bf15d","parentSpanId":"1c37edc71d55bc72","sampled":true,"kind":"client","startTimeUnixNano":"1779351720200635917","endTimeUnixNano":"1779351720200727625","durationMs":0.091708,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n WITH latest_stale_failures AS (\n SELECT\n failure.request_id,\n failure.resolved_at\n FROM (\n SELECT\n json_extract(payload_json, '$.requestId') AS request_id,\n created_at AS resolved_at,\n ROW_NUMBER() OVER (\n PARTITION BY json_extract(payload_json, '$.requestId')\n ORDER BY created_at DESC, activity_id DESC\n ) AS row_number\n FROM projection_thread_activities\n WHERE kind = 'provider.approval.respond.failed'\n AND json_extract(payload_json, '$.requestId') IS NOT NULL\n AND (\n lower(COALESCE(json_extract(payload_json, '$.detail'), ''))\n LIKE '%stale pending approval request%'\n OR lower(COALESCE(json_extract(payload_json, '$.detail'), ''))\n LIKE '%unknown pending approval request%'\n OR lower(COALESCE(json_extract(payload_json, '$.detail'), ''))\n LIKE '%unknown pending permission request%'\n )\n ) AS failure\n WHERE failure.row_number = 1\n )\n UPDATE projection_pending_approvals\n SET\n status = 'resolved',\n decision = NULL,\n resolved_at = (\n SELECT latest_stale_failures.resolved_at\n FROM latest_stale_failures\n WHERE latest_stale_failures.request_id = projection_pending_approvals.request_id\n )\n WHERE status = 'pending'\n AND EXISTS (\n SELECT 1\n FROM latest_stale_failures\n WHERE latest_stale_failures.request_id = projection_pending_approvals.request_id\n )\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"95882c5a017c9ed2","parentSpanId":"1c37edc71d55bc72","sampled":true,"kind":"client","startTimeUnixNano":"1779351720200733709","endTimeUnixNano":"1779351720200826917","durationMs":0.093208,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n UPDATE projection_threads\n SET\n latest_user_message_at = (\n SELECT MAX(message.created_at)\n FROM projection_thread_messages AS message\n WHERE message.thread_id = projection_threads.thread_id\n AND message.role = 'user'\n ),\n pending_approval_count = COALESCE((\n SELECT COUNT(*)\n FROM projection_pending_approvals\n WHERE projection_pending_approvals.thread_id = projection_threads.thread_id\n AND projection_pending_approvals.status = 'pending'\n ), 0),\n pending_user_input_count = COALESCE((\n WITH latest_user_input_states AS (\n SELECT\n latest.request_id,\n latest.kind,\n latest.detail\n FROM (\n SELECT\n json_extract(activity.payload_json, '$.requestId') AS request_id,\n activity.kind,\n lower(COALESCE(json_extract(activity.payload_json, '$.detail'), '')) AS detail,\n ROW_NUMBER() OVER (\n PARTITION BY json_extract(activity.payload_json, '$.requestId')\n ORDER BY activity.created_at DESC, activity.activity_id DESC\n ) AS row_number\n FROM projection_thread_activities AS activity\n WHERE activity.thread_id = projection_threads.thread_id\n AND json_extract(activity.payload_json, '$.requestId') IS NOT NULL\n AND activity.kind IN (\n 'user-input.requested',\n 'user-input.resolved',\n 'provider.user-input.respond.failed'\n )\n ) AS latest\n WHERE latest.row_number = 1\n )\n SELECT COUNT(*)\n FROM latest_user_input_states\n WHERE latest_user_input_states.kind = 'user-input.requested'\n OR (\n latest_user_input_states.kind = 'provider.user-input.respond.failed'\n AND latest_user_input_states.detail NOT LIKE '%stale pending user-input request%'\n AND latest_user_input_states.detail NOT LIKE '%unknown pending user-input request%'\n )\n ), 0),\n has_actionable_proposed_plan = COALESCE((\n SELECT CASE\n WHEN projection_threads.latest_turn_id IS NOT NULL\n AND EXISTS (\n SELECT 1\n FROM projection_thread_proposed_plans AS latest_turn_plan_exists\n WHERE latest_turn_plan_exists.thread_id = projection_threads.thread_id\n AND latest_turn_plan_exists.turn_id = projection_threads.latest_turn_id\n )\n THEN CASE\n WHEN (\n SELECT latest_turn_plan.implemented_at\n FROM projection_thread_proposed_plans AS latest_turn_plan\n WHERE latest_turn_plan.thread_id = projection_threads.thread_id\n AND latest_turn_plan.turn_id = projection_threads.latest_turn_id\n ORDER BY latest_turn_plan.updated_at DESC, latest_turn_plan.plan_id DESC\n LIMIT 1\n ) IS NULL\n THEN 1\n ELSE 0\n END\n WHEN EXISTS (\n SELECT 1\n FROM projection_thread_proposed_plans AS any_plan\n WHERE any_plan.thread_id = projection_threads.thread_id\n )\n THEN CASE\n WHEN (\n SELECT latest_plan.implemented_at\n FROM projection_thread_proposed_plans AS latest_plan\n WHERE latest_plan.thread_id = projection_threads.thread_id\n ORDER BY latest_plan.updated_at DESC, latest_plan.plan_id DESC\n LIMIT 1\n ) IS NULL\n THEN 1\n ELSE 0\n END\n ELSE 0\n END\n ), 0)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"Migrator 24_BackfillProjectionThreadShellSummary","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"1c37edc71d55bc72","parentSpanId":"673600a5f4185709","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720200340584","endTimeUnixNano":"1779351720200835417","durationMs":0.494833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"521ea3669309bd50","parentSpanId":"f9ff1afb6a13cf8c","sampled":true,"kind":"client","startTimeUnixNano":"1779351720200861542","endTimeUnixNano":"1779351720200884542","durationMs":0.023,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n DELETE FROM projection_pending_approvals\n WHERE NOT EXISTS (\n SELECT 1\n FROM projection_thread_activities AS activity\n WHERE activity.kind = 'approval.requested'\n AND json_extract(activity.payload_json, '$.requestId')\n = projection_pending_approvals.request_id\n )\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"d76b4c1b5b8ca932","parentSpanId":"f9ff1afb6a13cf8c","sampled":true,"kind":"client","startTimeUnixNano":"1779351720200889542","endTimeUnixNano":"1779351720200911584","durationMs":0.022042,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n UPDATE projection_threads\n SET pending_approval_count = COALESCE((\n SELECT COUNT(*)\n FROM projection_pending_approvals\n WHERE projection_pending_approvals.thread_id = projection_threads.thread_id\n AND projection_pending_approvals.status = 'pending'\n ), 0)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"Migrator 25_CleanupInvalidProjectionPendingApprovals","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"f9ff1afb6a13cf8c","parentSpanId":"673600a5f4185709","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720200841542","endTimeUnixNano":"1779351720200916625","durationMs":0.075083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"6e825bc079e9d4e0","parentSpanId":"e6fb4649fe189f29","sampled":true,"kind":"client","startTimeUnixNano":"1779351720200948417","endTimeUnixNano":"1779351720200988334","durationMs":0.039917,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n UPDATE projection_threads\n SET model_selection_json = json_set(\n model_selection_json,\n '$.options',\n (\n SELECT json_group_array(\n json_object(\n 'id', key,\n 'value',\n CASE type\n WHEN 'true' THEN json('true')\n WHEN 'false' THEN json('false')\n ELSE atom\n END\n )\n )\n FROM json_each(json_extract(model_selection_json, '$.options'))\n WHERE (type = 'text' AND trim(coalesce(atom, '')) != '')\n OR type IN ('true', 'false')\n )\n )\n WHERE model_selection_json IS NOT NULL\n AND json_type(model_selection_json, '$.options') = 'object'\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"aa093d4057ab435c","parentSpanId":"e6fb4649fe189f29","sampled":true,"kind":"client","startTimeUnixNano":"1779351720200993625","endTimeUnixNano":"1779351720201020542","durationMs":0.026917,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n UPDATE projection_projects\n SET default_model_selection_json = json_set(\n default_model_selection_json,\n '$.options',\n (\n SELECT json_group_array(\n json_object(\n 'id', key,\n 'value',\n CASE type\n WHEN 'true' THEN json('true')\n WHEN 'false' THEN json('false')\n ELSE atom\n END\n )\n )\n FROM json_each(json_extract(default_model_selection_json, '$.options'))\n WHERE (type = 'text' AND trim(coalesce(atom, '')) != '')\n OR type IN ('true', 'false')\n )\n )\n WHERE default_model_selection_json IS NOT NULL\n AND json_type(default_model_selection_json, '$.options') = 'object'\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"b9bf8c9678163bc6","parentSpanId":"e6fb4649fe189f29","sampled":true,"kind":"client","startTimeUnixNano":"1779351720201025625","endTimeUnixNano":"1779351720201052917","durationMs":0.027292,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n UPDATE orchestration_events\n SET payload_json = json_set(\n payload_json,\n '$.modelSelection.options',\n (\n SELECT json_group_array(\n json_object(\n 'id', key,\n 'value',\n CASE type\n WHEN 'true' THEN json('true')\n WHEN 'false' THEN json('false')\n ELSE atom\n END\n )\n )\n FROM json_each(json_extract(payload_json, '$.modelSelection.options'))\n WHERE (type = 'text' AND trim(coalesce(atom, '')) != '')\n OR type IN ('true', 'false')\n )\n )\n WHERE event_type IN (\n 'thread.created',\n 'thread.meta-updated',\n 'thread.turn-start-requested'\n )\n AND json_type(payload_json, '$.modelSelection.options') = 'object'\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"88c178668515e2d1","parentSpanId":"e6fb4649fe189f29","sampled":true,"kind":"client","startTimeUnixNano":"1779351720201058125","endTimeUnixNano":"1779351720201084417","durationMs":0.026292,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n UPDATE orchestration_events\n SET payload_json = json_set(\n payload_json,\n '$.defaultModelSelection.options',\n (\n SELECT json_group_array(\n json_object(\n 'id', key,\n 'value',\n CASE type\n WHEN 'true' THEN json('true')\n WHEN 'false' THEN json('false')\n ELSE atom\n END\n )\n )\n FROM json_each(json_extract(payload_json, '$.defaultModelSelection.options'))\n WHERE (type = 'text' AND trim(coalesce(atom, '')) != '')\n OR type IN ('true', 'false')\n )\n )\n WHERE event_type IN ('project.created', 'project.meta-updated')\n AND json_type(payload_json, '$.defaultModelSelection.options') = 'object'\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"Migrator 26_CanonicalizeModelSelectionOptions","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"e6fb4649fe189f29","parentSpanId":"673600a5f4185709","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720200922125","endTimeUnixNano":"1779351720201089584","durationMs":0.167459,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"012fd5c20ca6d614","parentSpanId":"722bd484d2ceeaa5","sampled":true,"kind":"client","startTimeUnixNano":"1779351720201116584","endTimeUnixNano":"1779351720201133000","durationMs":0.016416,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n PRAGMA table_info(provider_session_runtime)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"8fb33f96d14f95f2","parentSpanId":"722bd484d2ceeaa5","sampled":true,"kind":"client","startTimeUnixNano":"1779351720201140584","endTimeUnixNano":"1779351720201258292","durationMs":0.117708,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n ALTER TABLE provider_session_runtime\n ADD COLUMN provider_instance_id TEXT\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"c9b690ac18d98dc4","parentSpanId":"722bd484d2ceeaa5","sampled":true,"kind":"client","startTimeUnixNano":"1779351720201263459","endTimeUnixNano":"1779351720201297250","durationMs":0.033791,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE INDEX IF NOT EXISTS idx_provider_session_runtime_instance\n ON provider_session_runtime(provider_instance_id)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"Migrator 27_ProviderSessionRuntimeInstanceId","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"722bd484d2ceeaa5","parentSpanId":"673600a5f4185709","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720201094709","endTimeUnixNano":"1779351720201302209","durationMs":0.2075,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"b25155ed8d8c5fb2","parentSpanId":"cba6187852f6bf8f","sampled":true,"kind":"client","startTimeUnixNano":"1779351720201328834","endTimeUnixNano":"1779351720201345375","durationMs":0.016541,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n PRAGMA table_info(projection_thread_sessions)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"a2e2673dfb1cb7f8","parentSpanId":"cba6187852f6bf8f","sampled":true,"kind":"client","startTimeUnixNano":"1779351720201427750","endTimeUnixNano":"1779351720201549584","durationMs":0.121834,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n ALTER TABLE projection_thread_sessions\n ADD COLUMN provider_instance_id TEXT\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"60a061b538f18fdd","parentSpanId":"cba6187852f6bf8f","sampled":true,"kind":"client","startTimeUnixNano":"1779351720201554709","endTimeUnixNano":"1779351720201582542","durationMs":0.027833,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE INDEX IF NOT EXISTS idx_projection_thread_sessions_instance\n ON projection_thread_sessions(provider_instance_id)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"Migrator 28_ProjectionThreadSessionInstanceId","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"cba6187852f6bf8f","parentSpanId":"673600a5f4185709","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720201307875","endTimeUnixNano":"1779351720201587625","durationMs":0.27975,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"1b93e4379ec7ab7e","parentSpanId":"961ae0b38cc78f0e","sampled":true,"kind":"client","startTimeUnixNano":"1779351720201611000","endTimeUnixNano":"1779351720201643334","durationMs":0.032334,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE INDEX IF NOT EXISTS idx_projection_thread_activities_thread_sequence_created_id\n ON projection_thread_activities(thread_id, sequence, created_at, activity_id)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"b9894dc4639e4fbc","parentSpanId":"961ae0b38cc78f0e","sampled":true,"kind":"client","startTimeUnixNano":"1779351720201648209","endTimeUnixNano":"1779351720201678375","durationMs":0.030166,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE INDEX IF NOT EXISTS idx_projection_thread_messages_thread_created_id\n ON projection_thread_messages(thread_id, created_at, message_id)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"Migrator 29_ProjectionThreadDetailOrderingIndexes","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"961ae0b38cc78f0e","parentSpanId":"673600a5f4185709","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720201593125","endTimeUnixNano":"1779351720201683209","durationMs":0.090084,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"8b858459f2ffe9d0","parentSpanId":"25f1a7580f10f691","sampled":true,"kind":"client","startTimeUnixNano":"1779351720201705250","endTimeUnixNano":"1779351720201747834","durationMs":0.042584,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE INDEX IF NOT EXISTS idx_projection_threads_shell_active\n ON projection_threads(deleted_at, archived_at, project_id, created_at, thread_id)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"2297f90ceda10a5d","parentSpanId":"25f1a7580f10f691","sampled":true,"kind":"client","startTimeUnixNano":"1779351720201753250","endTimeUnixNano":"1779351720201854959","durationMs":0.101709,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n CREATE INDEX IF NOT EXISTS idx_projection_threads_shell_archived\n ON projection_threads(deleted_at, archived_at, project_id, thread_id)\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"Migrator 30_ProjectionThreadShellArchiveIndexes","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"25f1a7580f10f691","parentSpanId":"673600a5f4185709","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720201688417","endTimeUnixNano":"1779351720201870875","durationMs":0.182458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"45fc97fbc7441151","parentSpanId":"673600a5f4185709","sampled":true,"kind":"client","startTimeUnixNano":"1779351720201883250","endTimeUnixNano":"1779351720201931250","durationMs":0.048,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"executeWithoutTransform","db.query.text":"SELECT migration_id, name, created_at FROM \"effect_sql_migrations\" ORDER BY migration_id DESC"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.transaction","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"673600a5f4185709","parentSpanId":"4cc7384a52ecdbe5","sampled":true,"kind":"client","startTimeUnixNano":"1779351720192321292","endTimeUnixNano":"1779351720202560417","durationMs":10.239125,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite"},"events":[{"name":"db.transaction.commit","timeUnixNano":"1779351720202042875","attributes":{}}],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runMigrations","traceId":"5d25bbc950152aa90dfab763fd29da6c","spanId":"4cc7384a52ecdbe5","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720190932459","endTimeUnixNano":"1779351720203472209","durationMs":12.53975,"attributes":{},"events":[{"name":"Running all migrations...","timeUnixNano":"1779351720191407292","attributes":{"effect.fiberId":3,"effect.logLevel":"INFO"}},{"name":"Migrations ran successfully","timeUnixNano":"1779351720203450417","attributes":{"migrations":["1_OrchestrationEvents","2_OrchestrationCommandReceipts","3_CheckpointDiffBlobs","4_ProviderSessionRuntime","5_Projections","6_ProjectionThreadSessionRuntimeModeColumns","7_ProjectionThreadMessageAttachments","8_ProjectionThreadActivitySequence","9_ProviderSessionRuntimeMode","10_ProjectionThreadsRuntimeMode","11_OrchestrationThreadCreatedRuntimeMode","12_ProjectionThreadsInteractionMode","13_ProjectionThreadProposedPlans","14_ProjectionThreadProposedPlanImplementation","15_ProjectionTurnsSourceProposedPlan","16_CanonicalizeModelSelections","17_ProjectionThreadsArchivedAt","18_ProjectionThreadsArchivedAtIndex","19_ProjectionSnapshotLookupIndexes","20_AuthAccessManagement","21_AuthSessionClientMetadata","22_AuthSessionLastConnectedAt","23_ProjectionThreadShellSummary","24_BackfillProjectionThreadShellSummary","25_CleanupInvalidProjectionPendingApprovals","26_CanonicalizeModelSelectionOptions","27_ProviderSessionRuntimeInstanceId","28_ProjectionThreadSessionInstanceId","29_ProjectionThreadDetailOrderingIndexes","30_ProjectionThreadShellArchiveIndexes"],"effect.fiberId":3,"effect.logLevel":"INFO"}}],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"3efd374a461b5808","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720185511625","endTimeUnixNano":"1779351720213758042","durationMs":28.246417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"c9fbcdd56f368b7f58c58c05e6aa0021","spanId":"f402141231d48522","parentSpanId":"51f98a550bcb6247","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720217722417","endTimeUnixNano":"1779351720221064375","durationMs":3.341958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"c9fbcdd56f368b7f58c58c05e6aa0021","spanId":"575f60fb921fbf65","parentSpanId":"51f98a550bcb6247","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720217565584","endTimeUnixNano":"1779351720221142500","durationMs":3.576916,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"c9fbcdd56f368b7f58c58c05e6aa0021","spanId":"51f98a550bcb6247","parentSpanId":"5249a18c5e2df579","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720215712209","endTimeUnixNano":"1779351720221180667","durationMs":5.468458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runFriendlyLabelCommand","traceId":"c9fbcdd56f368b7f58c58c05e6aa0021","spanId":"5249a18c5e2df579","parentSpanId":"01dca14269c69e48","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720215611334","endTimeUnixNano":"1779351720221240542","durationMs":5.629208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveFriendlyHostLabel","traceId":"c9fbcdd56f368b7f58c58c05e6aa0021","spanId":"01dca14269c69e48","parentSpanId":"688073c3adbe1901","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720215590167","endTimeUnixNano":"1779351720221245459","durationMs":5.655292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveServerEnvironmentLabel","traceId":"c9fbcdd56f368b7f58c58c05e6aa0021","spanId":"688073c3adbe1901","parentSpanId":"82a2c6a412d892fd","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720215568584","endTimeUnixNano":"1779351720221249042","durationMs":5.680458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeServerEnvironment","traceId":"c9fbcdd56f368b7f58c58c05e6aa0021","spanId":"82a2c6a412d892fd","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720215092584","endTimeUnixNano":"1779351720221273167","durationMs":6.180583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeRepositoryIdentityResolver","traceId":"d35a0208ef04d308e73df6b7f1b2a639","spanId":"1acb4a6216813fbe","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720221301167","endTimeUnixNano":"1779351720221354750","durationMs":0.053583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeVcsProjectConfig","traceId":"166a81bae68419400dff4ccb522e94ec","spanId":"c2d1dd4df8299247","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720221445542","endTimeUnixNano":"1779351720221469292","durationMs":0.02375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeGitVcsDriverShape","traceId":"8f816ed8e8ec86415480068f2cdacf20","spanId":"4e394790b6e7b67c","parentSpanId":"09d1dfeac2330ec0","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720221529250","endTimeUnixNano":"1779351720221605375","durationMs":0.076125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeVcsDriverRegistry","traceId":"8f816ed8e8ec86415480068f2cdacf20","spanId":"09d1dfeac2330ec0","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720221487959","endTimeUnixNano":"1779351720221618875","durationMs":0.130916,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeEventNdjsonLogger","traceId":"06576c0100971eed1e2a6bb6bcc37b65","spanId":"eef062830ff83c04","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720221955959","endTimeUnixNano":"1779351720222072709","durationMs":0.11675,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeEventNdjsonLogger","traceId":"7aacfc9af402ba1fb0bd3e7e6e786339","spanId":"fe48222855d30732","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720222080875","endTimeUnixNano":"1779351720222103459","durationMs":0.022584,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveCodexHomeLayout","traceId":"4d80eb0dfae5cf12f029ae285b86a492","spanId":"9621d10fa37555e0","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720222893292","endTimeUnixNano":"1779351720222930250","durationMs":0.036958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"materializeCodexShadowHome","traceId":"5e99216102039c742098fc1451808634","spanId":"9bda98d9c089d25b","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720222955959","endTimeUnixNano":"1779351720222998750","durationMs":0.042791,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderMaintenanceCapabilitiesEffect","traceId":"3c0b85069aa6f460cb78b42b700618f2","spanId":"c03e035631755171","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720223008500","endTimeUnixNano":"1779351720223819667","durationMs":0.811167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeCodexAdapter","traceId":"2c79fc17f69748b116fe049e2f8a2696","spanId":"61103ac9093764b3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720223836959","endTimeUnixNano":"1779351720223980000","durationMs":0.143041,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeCodexTextGeneration","traceId":"a3b03b5256da2372285c03bbde1f0ad0","spanId":"acd0524238914c3b","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720223988959","endTimeUnixNano":"1779351720224041792","durationMs":0.052833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeManagedServerProvider","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"5bc4cdb3beb605ab","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720224060167","endTimeUnixNano":"1779351720224395625","durationMs":0.335458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderMaintenanceCapabilitiesEffect","traceId":"b8b47dc99e98076c13c65f4c3d166e74","spanId":"84103fd74364def6","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720224710875","endTimeUnixNano":"1779351720225038625","durationMs":0.32775,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveClaudeHomePath","traceId":"256fe2cfaa4b4e5ab708d3941d6f6216","spanId":"c6c61fbb59db2bd6","parentSpanId":"e7a12e1fecd4ca84","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720225064625","endTimeUnixNano":"1779351720225080125","durationMs":0.0155,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeClaudeContinuationGroupKey","traceId":"256fe2cfaa4b4e5ab708d3941d6f6216","spanId":"e7a12e1fecd4ca84","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720225046584","endTimeUnixNano":"1779351720225083959","durationMs":0.037375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeClaudeEnvironment","traceId":"cfb56d014e99dcacfd9ed50232689d50","spanId":"e77709787fb55d7e","parentSpanId":"ae38bdba0b734bdd","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720225192959","endTimeUnixNano":"1779351720225206750","durationMs":0.013791,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeClaudeAdapter","traceId":"cfb56d014e99dcacfd9ed50232689d50","spanId":"ae38bdba0b734bdd","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720225097667","endTimeUnixNano":"1779351720225240459","durationMs":0.142792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeClaudeEnvironment","traceId":"774465a17fff2e62d8d2d951a1efaa13","spanId":"e24396f3d7f65573","parentSpanId":"4de369e8c1b5287d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720225273750","endTimeUnixNano":"1779351720225277334","durationMs":0.003584,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeClaudeTextGeneration","traceId":"774465a17fff2e62d8d2d951a1efaa13","spanId":"4de369e8c1b5287d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720225245500","endTimeUnixNano":"1779351720225284250","durationMs":0.03875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveClaudeHomePath","traceId":"1b03716067ee5dbfcca158999660187d","spanId":"9a176707fe89ebb6","parentSpanId":"947d1f1f10956ba8","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720225304959","endTimeUnixNano":"1779351720225309750","durationMs":0.004791,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeClaudeCapabilitiesCacheKey","traceId":"1b03716067ee5dbfcca158999660187d","spanId":"947d1f1f10956ba8","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720225293542","endTimeUnixNano":"1779351720225312417","durationMs":0.018875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeManagedServerProvider","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"d8882d30663dbbb0","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720225322125","endTimeUnixNano":"1779351720225438000","durationMs":0.115875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderMaintenanceCapabilitiesEffect","traceId":"40e5f2679d98eb5c3346b04d9a398494","spanId":"9896766bca105a01","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720225579042","endTimeUnixNano":"1779351720225736542","durationMs":0.1575,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeCursorTextGeneration","traceId":"db45a28dd8356de5de5dd0cea8912e89","spanId":"fffbf4467c5a9258","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720225859792","endTimeUnixNano":"1779351720225889042","durationMs":0.02925,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeManagedServerProvider","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"f4270506fde844da","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720225900959","endTimeUnixNano":"1779351720225983042","durationMs":0.082083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeClaudeEnvironment","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"0d69dd493f248435","parentSpanId":"9db15f7db28dab1b","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720226643334","endTimeUnixNano":"1779351720226647625","durationMs":0.004291,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"checkCursorProviderStatus","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"aeb6c3ce2fea8e6f","parentSpanId":"acbffcae7439b9f1","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720227666709","endTimeUnixNano":"1779351720227736042","durationMs":0.069333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"248cf8291af8d915","parentSpanId":"acbffcae7439b9f1","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720227811459","endTimeUnixNano":"1779351720227929334","durationMs":0.117875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"acbffcae7439b9f1","parentSpanId":"f4270506fde844da","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720227659084","endTimeUnixNano":"1779351720227932667","durationMs":0.273583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runClaudeCommand","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"9db15f7db28dab1b","parentSpanId":"8c50f28fdc559ca4","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720226624750","endTimeUnixNano":"1779351720228095584","durationMs":1.470834,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"PlatformError: NotFound: ChildProcess.spawn (claude --version)\n at Module.systemError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/PlatformError.js:59:39)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/internal/utils.js:28:24\n at toPlatformError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:25:54)\n at ChildProcess. (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:230:26)\n at ChildProcess.emit (node:events:509:28)\n at ChildProcess._handle.onexit (node:internal/child_process:293:12)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n at runClaudeCommand (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:27894:30)\n at runClaudeCommand (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:27870:33)\n at checkClaudeProviderStatus (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30400:25)\n at checkClaudeProviderStatus (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:27878:42)\n at applySnapshot (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30277:83)\n at applySnapshot (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30257:35)\n at makeManagedServerProvider (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30401:27)\n at makeManagedServerProvider (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30222:42) {\n [cause]: Error: spawn claude ENOENT\n at ChildProcess._handle.onexit (node:internal/child_process:287:19)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n}"}} -{"type":"effect-span","name":"checkClaudeProviderStatus","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"8c50f28fdc559ca4","parentSpanId":"f25b1941617620f0","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720226547250","endTimeUnixNano":"1779351720230889917","durationMs":4.342667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"f0f581854e5c000c","parentSpanId":"f25b1941617620f0","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720230910417","endTimeUnixNano":"1779351720230942209","durationMs":0.031792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"f25b1941617620f0","parentSpanId":"d8882d30663dbbb0","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720226537417","endTimeUnixNano":"1779351720230945667","durationMs":4.40825,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeCodexAppServerPatchedProtocol","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"cc14532d2d22678d","parentSpanId":"93140c6312c217f3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720231505375","endTimeUnixNano":"1779351720231676292","durationMs":0.170917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"effect-codex-app-server/CodexAppServerClient.make","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"93140c6312c217f3","parentSpanId":"0f6840ec7c3fe5b0","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720231437250","endTimeUnixNano":"1779351720231685625","durationMs":0.248375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"7162dc8c743783e9","parentSpanId":"248cf8291af8d915","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720232122750","endTimeUnixNano":"1779351720232182125","durationMs":0.059375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"b810443e692ab9d1","parentSpanId":"248cf8291af8d915","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720232199542","endTimeUnixNano":"1779351720232388375","durationMs":0.188833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"975986537ae20284","parentSpanId":"f0f581854e5c000c","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720232423625","endTimeUnixNano":"1779351720232432167","durationMs":0.008542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"e574d13686f233d8","parentSpanId":"f0f581854e5c000c","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720232441250","endTimeUnixNano":"1779351720232582500","durationMs":0.14125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderMaintenanceCapabilitiesEffect","traceId":"8fdfd656e584a499a11e2dbee2d9a5cc","spanId":"04fa519b01dd0819","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720226103709","endTimeUnixNano":"1779351720233000375","durationMs":6.896666,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeOpenCodeTextGeneration","traceId":"2596d247ab8f9051392b6558766c78f2","spanId":"38f7ccc336ea8ba2","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720233089334","endTimeUnixNano":"1779351720233143292","durationMs":0.053958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeManagedServerProvider","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"2f989ef1cbf60c79","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720233156625","endTimeUnixNano":"1779351720233256084","durationMs":0.099459,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"777b0a51d7e25ac60548f58b88e84e03","spanId":"5356bc5c9e26cb0c","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720233527417","endTimeUnixNano":"1779351720233539125","durationMs":0.011708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"f40e846f635226cdfa5a4e13bfb66b49","spanId":"bc0aa73576dff036","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720233564834","endTimeUnixNano":"1779351720233575375","durationMs":0.010541,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"5e62af99ec20e156e1e3b2a17c0872f3","spanId":"2335e3b07686bcf2","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720233698292","endTimeUnixNano":"1779351720233707584","durationMs":0.009292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"requestAllCodexModels","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"e3ce8c5cfc9d213c","parentSpanId":"0f6840ec7c3fe5b0","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720258881625","endTimeUnixNano":"1779351720260266625","durationMs":1.385,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"probeCodexAppServerProvider","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"0f6840ec7c3fe5b0","parentSpanId":"fd904c2051487f25","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720226320209","endTimeUnixNano":"1779351720290688500","durationMs":64.368291,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"checkCodexProviderStatus","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"fd904c2051487f25","parentSpanId":"f874dc5e90d661d0","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720226252959","endTimeUnixNano":"1779351720292657084","durationMs":66.404125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"84a18b8167e75b2b","parentSpanId":"f874dc5e90d661d0","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720292697500","endTimeUnixNano":"1779351720292741000","durationMs":0.0435,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"f874dc5e90d661d0","parentSpanId":"5bc4cdb3beb605ab","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720226216667","endTimeUnixNano":"1779351720292750834","durationMs":66.534167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"9a091409985a7dc50738827952119ab5","spanId":"bc240738cb5c9feb","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720298261625","endTimeUnixNano":"1779351720298278459","durationMs":0.016834,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"a349049150243381e504db76c4f8a898","spanId":"6a0ea5dd71342b7b","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720298347167","endTimeUnixNano":"1779351720298364834","durationMs":0.017667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"b537c91cc25acddcda25ca7b02801050","spanId":"9759f4ada206eb90","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720298424584","endTimeUnixNano":"1779351720298431042","durationMs":0.006458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"e7ca09a3bb1dfab4082354616aefec5d","spanId":"103a2a208a47b1ea","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720298449250","endTimeUnixNano":"1779351720298454292","durationMs":0.005042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"cbf3944c16f32de68cb50aaa36de85cc","spanId":"4ffc345b9495c921","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720298469084","endTimeUnixNano":"1779351720298473834","durationMs":0.00475,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"928f15f8b83944620919ffc4f9ac2fa3","spanId":"b7d3cfb5e8a272bc","parentSpanId":"954fd8a28652fe2f","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720298673334","endTimeUnixNano":"1779351720298693042","durationMs":0.019708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"928f15f8b83944620919ffc4f9ac2fa3","spanId":"a1eaa1c144458ac4","parentSpanId":"954fd8a28652fe2f","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720298701125","endTimeUnixNano":"1779351720298708792","durationMs":0.007667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"928f15f8b83944620919ffc4f9ac2fa3","spanId":"605ace835a4700d7","parentSpanId":"954fd8a28652fe2f","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720298714959","endTimeUnixNano":"1779351720298723000","durationMs":0.008041,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"928f15f8b83944620919ffc4f9ac2fa3","spanId":"c39ce14157220b48","parentSpanId":"954fd8a28652fe2f","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720298728584","endTimeUnixNano":"1779351720298733125","durationMs":0.004541,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"928f15f8b83944620919ffc4f9ac2fa3","spanId":"618c0b65519c90ac","parentSpanId":"954fd8a28652fe2f","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720303559584","endTimeUnixNano":"1779351720303565875","durationMs":0.006291,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"928f15f8b83944620919ffc4f9ac2fa3","spanId":"df10462bee81ac20","parentSpanId":"954fd8a28652fe2f","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720303668084","endTimeUnixNano":"1779351720303673625","durationMs":0.005541,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"928f15f8b83944620919ffc4f9ac2fa3","spanId":"b8c44ccb88bae57e","parentSpanId":"954fd8a28652fe2f","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720303732375","endTimeUnixNano":"1779351720303738917","durationMs":0.006542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"928f15f8b83944620919ffc4f9ac2fa3","spanId":"b2b0a8da1c716e3b","parentSpanId":"954fd8a28652fe2f","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720303771292","endTimeUnixNano":"1779351720303776584","durationMs":0.005292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"928f15f8b83944620919ffc4f9ac2fa3","spanId":"954fd8a28652fe2f","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720298616834","endTimeUnixNano":"1779351720305011959","durationMs":6.395125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeClaudeEnvironment","traceId":"55d3a48f3bfeae4512d899e4cfe00f74","spanId":"3b3335cc3dc00332","parentSpanId":"ab964cc39f886c60","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720305489334","endTimeUnixNano":"1779351720305494417","durationMs":0.005083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"checkCursorProviderStatus","traceId":"f783fd535a7f4b35f9887f1484131d4d","spanId":"f78fe7434434d296","parentSpanId":"f9d5ca81b14be436","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720306573167","endTimeUnixNano":"1779351720306589167","durationMs":0.016,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"f783fd535a7f4b35f9887f1484131d4d","spanId":"1bdfc28167a4e664","parentSpanId":"f9d5ca81b14be436","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720306605000","endTimeUnixNano":"1779351720306633042","durationMs":0.028042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"f783fd535a7f4b35f9887f1484131d4d","spanId":"f9d5ca81b14be436","parentSpanId":"032189de45dd1c23","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720306566250","endTimeUnixNano":"1779351720306639125","durationMs":0.072875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"f783fd535a7f4b35f9887f1484131d4d","spanId":"032189de45dd1c23","parentSpanId":"cf7aafa0e28fc2d5","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720306556167","endTimeUnixNano":"1779351720306642625","durationMs":0.086458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"f783fd535a7f4b35f9887f1484131d4d","spanId":"50137ef1d19c7492","parentSpanId":"e17bde7452f6f5e8","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720306684334","endTimeUnixNano":"1779351720306689709","durationMs":0.005375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"f783fd535a7f4b35f9887f1484131d4d","spanId":"2383d1bab11a6bcd","parentSpanId":"e17bde7452f6f5e8","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720306747834","endTimeUnixNano":"1779351720306756250","durationMs":0.008416,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runClaudeCommand","traceId":"55d3a48f3bfeae4512d899e4cfe00f74","spanId":"ab964cc39f886c60","parentSpanId":"2d139ffd91150c93","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720305482584","endTimeUnixNano":"1779351720306852709","durationMs":1.370125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"PlatformError: NotFound: ChildProcess.spawn (claude --version)\n at Module.systemError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/PlatformError.js:59:39)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/internal/utils.js:28:24\n at toPlatformError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:25:54)\n at ChildProcess. (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:230:26)\n at ChildProcess.emit (node:events:509:28)\n at ChildProcess._handle.onexit (node:internal/child_process:293:12)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n at runClaudeCommand (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:27894:30)\n at runClaudeCommand (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:27870:33)\n at checkClaudeProviderStatus (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30400:25)\n at checkClaudeProviderStatus (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:27878:42)\n at applySnapshot (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30277:83)\n at applySnapshot (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30257:35)\n at refreshSnapshot (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30287:12)\n at refreshSnapshot (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30278:33)\n at refreshOneSource (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:60542:55)\n at refreshOneSource (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:60475:34) {\n [cause]: Error: spawn claude ENOENT\n at ChildProcess._handle.onexit (node:internal/child_process:287:19)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n}"}} -{"type":"effect-span","name":"checkClaudeProviderStatus","traceId":"55d3a48f3bfeae4512d899e4cfe00f74","spanId":"2d139ffd91150c93","parentSpanId":"89f2c02db2fd3b90","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720305464042","endTimeUnixNano":"1779351720306975167","durationMs":1.511125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"55d3a48f3bfeae4512d899e4cfe00f74","spanId":"643b45d396c0a868","parentSpanId":"89f2c02db2fd3b90","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720306991709","endTimeUnixNano":"1779351720307010584","durationMs":0.018875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"55d3a48f3bfeae4512d899e4cfe00f74","spanId":"89f2c02db2fd3b90","parentSpanId":"69818a39868e9c68","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720305457875","endTimeUnixNano":"1779351720307013625","durationMs":1.55575,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"55d3a48f3bfeae4512d899e4cfe00f74","spanId":"69818a39868e9c68","parentSpanId":"7fcc8e4e185e0458","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720305448542","endTimeUnixNano":"1779351720307016917","durationMs":1.568375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"55d3a48f3bfeae4512d899e4cfe00f74","spanId":"448d3026cdbc1ee2","parentSpanId":"a5b7776a38c6ed73","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720307126500","endTimeUnixNano":"1779351720307131334","durationMs":0.004834,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"55d3a48f3bfeae4512d899e4cfe00f74","spanId":"2402981ed3818e2a","parentSpanId":"a5b7776a38c6ed73","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720307181167","endTimeUnixNano":"1779351720307186084","durationMs":0.004917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"f783fd535a7f4b35f9887f1484131d4d","spanId":"a0d401a8ad517953","parentSpanId":"1bdfc28167a4e664","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720307318000","endTimeUnixNano":"1779351720307328417","durationMs":0.010417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"701f26ca14445403a9f7a509d4500be0","spanId":"75ee968f0dfcf0ba","parentSpanId":"dde77dff41d42c28","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720307411709","endTimeUnixNano":"1779351720307417375","durationMs":0.005666,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"701f26ca14445403a9f7a509d4500be0","spanId":"bc5c18e96fc0f3fd","parentSpanId":"dde77dff41d42c28","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720307445292","endTimeUnixNano":"1779351720307450584","durationMs":0.005292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"f783fd535a7f4b35f9887f1484131d4d","spanId":"5a297e0166218b94","parentSpanId":"1bdfc28167a4e664","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720307338459","endTimeUnixNano":"1779351720307477334","durationMs":0.138875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"55d3a48f3bfeae4512d899e4cfe00f74","spanId":"9041bea9c16b0f7a","parentSpanId":"643b45d396c0a868","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720307484792","endTimeUnixNano":"1779351720307490834","durationMs":0.006042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"56e8174716f64f489fcb96aac361e11b","spanId":"3e83a0923a10220c","parentSpanId":"195f4d1cdb2cba22","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720307545917","endTimeUnixNano":"1779351720307550500","durationMs":0.004583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"56e8174716f64f489fcb96aac361e11b","spanId":"545ced2050319e6b","parentSpanId":"195f4d1cdb2cba22","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720307581084","endTimeUnixNano":"1779351720307585584","durationMs":0.0045,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"55d3a48f3bfeae4512d899e4cfe00f74","spanId":"770e608dbe210536","parentSpanId":"643b45d396c0a868","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720307496834","endTimeUnixNano":"1779351720307613042","durationMs":0.116208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeCodexAppServerPatchedProtocol","traceId":"0ff4158d90808cd1580c858b545644e0","spanId":"a823e59f6cbd2973","parentSpanId":"a2b22ef6637cf0da","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720308038334","endTimeUnixNano":"1779351720308072750","durationMs":0.034416,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"effect-codex-app-server/CodexAppServerClient.make","traceId":"0ff4158d90808cd1580c858b545644e0","spanId":"a2b22ef6637cf0da","parentSpanId":"7796a5d8a5135f74","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720308028792","endTimeUnixNano":"1779351720308079917","durationMs":0.051125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"701f26ca14445403a9f7a509d4500be0","spanId":"dde77dff41d42c28","parentSpanId":"c3bf78f332227fa3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720307403584","endTimeUnixNano":"1779351720308862209","durationMs":1.458625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"701f26ca14445403a9f7a509d4500be0","spanId":"c3bf78f332227fa3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720307397167","endTimeUnixNano":"1779351720308867834","durationMs":1.470667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"f783fd535a7f4b35f9887f1484131d4d","spanId":"e17bde7452f6f5e8","parentSpanId":"7ed0b3087c7d8b79","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720306674209","endTimeUnixNano":"1779351720308887375","durationMs":2.213166,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"f783fd535a7f4b35f9887f1484131d4d","spanId":"7ed0b3087c7d8b79","parentSpanId":"cf7aafa0e28fc2d5","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720306660125","endTimeUnixNano":"1779351720308891500","durationMs":2.231375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshOneSource","traceId":"f783fd535a7f4b35f9887f1484131d4d","spanId":"cf7aafa0e28fc2d5","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720306547459","endTimeUnixNano":"1779351720308895167","durationMs":2.347708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"55d3a48f3bfeae4512d899e4cfe00f74","spanId":"a5b7776a38c6ed73","parentSpanId":"26a81e784ba4e09e","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720307118042","endTimeUnixNano":"1779351720308987875","durationMs":1.869833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"55d3a48f3bfeae4512d899e4cfe00f74","spanId":"26a81e784ba4e09e","parentSpanId":"7fcc8e4e185e0458","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720307111167","endTimeUnixNano":"1779351720308995500","durationMs":1.884333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshOneSource","traceId":"55d3a48f3bfeae4512d899e4cfe00f74","spanId":"7fcc8e4e185e0458","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720305441334","endTimeUnixNano":"1779351720308999125","durationMs":3.557791,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"56e8174716f64f489fcb96aac361e11b","spanId":"195f4d1cdb2cba22","parentSpanId":"ae71b98a8caa8b3c","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720307538125","endTimeUnixNano":"1779351720309058250","durationMs":1.520125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"56e8174716f64f489fcb96aac361e11b","spanId":"ae71b98a8caa8b3c","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720307528709","endTimeUnixNano":"1779351720309062542","durationMs":1.533833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"requestAllCodexModels","traceId":"0ff4158d90808cd1580c858b545644e0","spanId":"0034a5cb098cc28a","parentSpanId":"7796a5d8a5135f74","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720324485209","endTimeUnixNano":"1779351720325327250","durationMs":0.842041,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"probeCodexAppServerProvider","traceId":"0ff4158d90808cd1580c858b545644e0","spanId":"7796a5d8a5135f74","parentSpanId":"4fa9febf4bc64549","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720305317209","endTimeUnixNano":"1779351720354193417","durationMs":48.876208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"checkCodexProviderStatus","traceId":"0ff4158d90808cd1580c858b545644e0","spanId":"4fa9febf4bc64549","parentSpanId":"4b9d7050d349c239","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720305277125","endTimeUnixNano":"1779351720356866875","durationMs":51.58975,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"c53faf8945044dfce87183d5cf2db42b","spanId":"40cf76d6ba06fe80","parentSpanId":"bc1faebcbdd5206a","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720356953875","endTimeUnixNano":"1779351720356961959","durationMs":0.008084,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"c53faf8945044dfce87183d5cf2db42b","spanId":"2f43c835161be0d1","parentSpanId":"bc1faebcbdd5206a","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720357163959","endTimeUnixNano":"1779351720357175709","durationMs":0.01175,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"http.client GET","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"b7a29f0541252bfc","parentSpanId":"f3f9f13a5844d19d","sampled":true,"kind":"client","startTimeUnixNano":"1779351720293104584","endTimeUnixNano":"1779351720358471000","durationMs":65.366416,"attributes":{"http.request.method":"GET","server.address":"https://registry.npmjs.org","url.full":"https://registry.npmjs.org/%40openai%2Fcodex/latest","url.path":"/%40openai%2Fcodex/latest","url.scheme":"https","http.request.header.accept":"application/json"},"events":[],"links":[],"exit":{"_tag":"Interrupted","cause":"InterruptError: All fibers interrupted without error\n at http.client GET\n at fetchNpmLatestVersion (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:18204:25)\n at fetchNpmLatestVersion (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:18188:38)\n at resolveLatestProviderVersion (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:18222:31)\n at resolveLatestProviderVersion (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:18198:45)\n at enrichProviderSnapshotWithVersionAdvisory (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:48614:56)\n at enrichProviderSnapshotWithVersionAdvisory (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:18211:58)\n at restartSnapshotEnrichment (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30274:10)\n at restartSnapshotEnrichment (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30245:43)\n at applySnapshot (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30277:83) {\n [cause]: InterruptCause: The fiber was interrupted by:\n at fiber (#93)\n}"}} -{"type":"effect-span","name":"fetchNpmLatestVersion","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"f3f9f13a5844d19d","parentSpanId":"4cc1ffc7bbd393a8","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720292831959","endTimeUnixNano":"1779351720358873792","durationMs":66.041833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Interrupted","cause":"InterruptError: All fibers interrupted without error\n at fetchNpmLatestVersion (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:18204:25)\n at fetchNpmLatestVersion (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:18188:38)\n at resolveLatestProviderVersion (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:18222:31)\n at resolveLatestProviderVersion (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:18198:45)\n at enrichProviderSnapshotWithVersionAdvisory (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:48614:56)\n at enrichProviderSnapshotWithVersionAdvisory (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:18211:58)\n at restartSnapshotEnrichment (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30274:10)\n at restartSnapshotEnrichment (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30245:43)\n at applySnapshot (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30277:83)\n at applySnapshot (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30257:35) {\n [cause]: InterruptCause: The fiber was interrupted by:\n at fiber (#112)\n}"}} -{"type":"effect-span","name":"resolveLatestProviderVersion","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"4cc1ffc7bbd393a8","parentSpanId":"c368c0b155aad6c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720292789500","endTimeUnixNano":"1779351720358906917","durationMs":66.117417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Interrupted","cause":"InterruptError: All fibers interrupted without error\n at fetchNpmLatestVersion (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:18204:25)\n at fetchNpmLatestVersion (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:18188:38)\n at resolveLatestProviderVersion (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:18222:31)\n at resolveLatestProviderVersion (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:18198:45)\n at enrichProviderSnapshotWithVersionAdvisory (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:48614:56)\n at enrichProviderSnapshotWithVersionAdvisory (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:18211:58)\n at restartSnapshotEnrichment (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30274:10)\n at restartSnapshotEnrichment (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30245:43)\n at applySnapshot (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30277:83)\n at applySnapshot (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30257:35) {\n [cause]: InterruptCause: The fiber was interrupted by:\n at fiber (#112)\n}"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"c368c0b155aad6c4","parentSpanId":"84a18b8167e75b2b","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720292777292","endTimeUnixNano":"1779351720358926459","durationMs":66.149167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Interrupted","cause":"InterruptError: All fibers interrupted without error\n at fetchNpmLatestVersion (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:18204:25)\n at fetchNpmLatestVersion (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:18188:38)\n at resolveLatestProviderVersion (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:18222:31)\n at resolveLatestProviderVersion (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:18198:45)\n at enrichProviderSnapshotWithVersionAdvisory (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:48614:56)\n at enrichProviderSnapshotWithVersionAdvisory (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:18211:58)\n at restartSnapshotEnrichment (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30274:10)\n at restartSnapshotEnrichment (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30245:43)\n at applySnapshot (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30277:83)\n at applySnapshot (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30257:35) {\n [cause]: InterruptCause: The fiber was interrupted by:\n at fiber (#112)\n}"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"0ff4158d90808cd1580c858b545644e0","spanId":"52bdd38b52fbd0fa","parentSpanId":"4b9d7050d349c239","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720357265042","endTimeUnixNano":"1779351720358971042","durationMs":1.706,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"0ff4158d90808cd1580c858b545644e0","spanId":"4b9d7050d349c239","parentSpanId":"9000edaea3396596","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720305268709","endTimeUnixNano":"1779351720359156250","durationMs":53.887541,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"0ff4158d90808cd1580c858b545644e0","spanId":"9000edaea3396596","parentSpanId":"4487e989f8f4246f","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720305243792","endTimeUnixNano":"1779351720359162709","durationMs":53.918917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"0ff4158d90808cd1580c858b545644e0","spanId":"3d501ee2baa8972f","parentSpanId":"baa611eedfc55711","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720359201709","endTimeUnixNano":"1779351720359207459","durationMs":0.00575,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"0ff4158d90808cd1580c858b545644e0","spanId":"baa611eedfc55711","parentSpanId":"025678cc26d764cd","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720359188292","endTimeUnixNano":"1779351720359296500","durationMs":0.108208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"0ff4158d90808cd1580c858b545644e0","spanId":"025678cc26d764cd","parentSpanId":"4487e989f8f4246f","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720359177292","endTimeUnixNano":"1779351720359299792","durationMs":0.1225,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshOneSource","traceId":"0ff4158d90808cd1580c858b545644e0","spanId":"4487e989f8f4246f","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720305222167","endTimeUnixNano":"1779351720359302584","durationMs":54.080417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"c53faf8945044dfce87183d5cf2db42b","spanId":"bc1faebcbdd5206a","parentSpanId":"b21f74f22aeae376","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720356939625","endTimeUnixNano":"1779351720361337250","durationMs":4.397625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"c53faf8945044dfce87183d5cf2db42b","spanId":"b21f74f22aeae376","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720356925125","endTimeUnixNano":"1779351720361344209","durationMs":4.419084,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"http.client GET","traceId":"0ff4158d90808cd1580c858b545644e0","spanId":"27f0e5cfc3bb2cde","parentSpanId":"32bf124e96205b4e","sampled":true,"kind":"client","startTimeUnixNano":"1779351720359676500","endTimeUnixNano":"1779351720702652625","durationMs":342.976125,"attributes":{"http.request.method":"GET","server.address":"https://registry.npmjs.org","url.full":"https://registry.npmjs.org/%40openai%2Fcodex/latest","url.path":"/%40openai%2Fcodex/latest","url.scheme":"https","http.request.header.accept":"application/json","http.response.status_code":200,"http.response.header.access-control-allow-origin":"*","http.response.header.cf-cache-status":"DYNAMIC","http.response.header.cf-ray":"9ff22bbd1ef957dd-SYD","http.response.header.connection":"keep-alive","http.response.header.content-encoding":"gzip","http.response.header.content-type":"application/json","http.response.header.date":"Thu, 21 May 2026 08:22:00 GMT","http.response.header.server":"cloudflare","http.response.header.set-cookie":"","http.response.header.transfer-encoding":"chunked"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"fetchNpmLatestVersion","traceId":"0ff4158d90808cd1580c858b545644e0","spanId":"32bf124e96205b4e","parentSpanId":"621e5cf260a3930c","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720359639292","endTimeUnixNano":"1779351720704396042","durationMs":344.75675,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveLatestProviderVersion","traceId":"0ff4158d90808cd1580c858b545644e0","spanId":"621e5cf260a3930c","parentSpanId":"f4300cc44206d867","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720359627292","endTimeUnixNano":"1779351720704411209","durationMs":344.783917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"0ff4158d90808cd1580c858b545644e0","spanId":"f4300cc44206d867","parentSpanId":"52bdd38b52fbd0fa","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720359618042","endTimeUnixNano":"1779351720704460417","durationMs":344.842375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"38068c767a756bef28e0532bd17615e1","spanId":"65704bf3380e777a","parentSpanId":"61216ff5517aef29","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720704593250","endTimeUnixNano":"1779351720704601459","durationMs":0.008209,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"38068c767a756bef28e0532bd17615e1","spanId":"17af3fc1da0f39c5","parentSpanId":"61216ff5517aef29","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720704650792","endTimeUnixNano":"1779351720704661417","durationMs":0.010625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"0ff4158d90808cd1580c858b545644e0","spanId":"23aced0088c8cd6b","parentSpanId":"52bdd38b52fbd0fa","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720704488292","endTimeUnixNano":"1779351720704755584","durationMs":0.267292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"38068c767a756bef28e0532bd17615e1","spanId":"61216ff5517aef29","parentSpanId":"661c0c63f54b8975","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720704574709","endTimeUnixNano":"1779351720706027292","durationMs":1.452583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"38068c767a756bef28e0532bd17615e1","spanId":"661c0c63f54b8975","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720704558667","endTimeUnixNano":"1779351720706037625","durationMs":1.478958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"opencode.app.agents","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"ef7f77b4153d4c61","parentSpanId":"fc5f7b82deac458b","sampled":true,"kind":"internal","startTimeUnixNano":"1779351721083629709","endTimeUnixNano":"1779351721321537917","durationMs":237.908208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"opencode.provider.list","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"f0afc6b385d41fdc","parentSpanId":"fc5f7b82deac458b","sampled":true,"kind":"internal","startTimeUnixNano":"1779351721083259834","endTimeUnixNano":"1779351721446589709","durationMs":363.329875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"checkOpenCodeProviderStatus","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"fc5f7b82deac458b","parentSpanId":"167c145a5df1e30c","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720233738834","endTimeUnixNano":"1779351722450452209","durationMs":2216.713375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"f0f37a343f6b64e2d0db7d7ae658e62f","spanId":"9c7b5035b89e9124","parentSpanId":"d76a52caaabdeffb","sampled":true,"kind":"internal","startTimeUnixNano":"1779351722450827542","endTimeUnixNano":"1779351722450854584","durationMs":0.027042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"f0f37a343f6b64e2d0db7d7ae658e62f","spanId":"b6938e61f1899acf","parentSpanId":"d76a52caaabdeffb","sampled":true,"kind":"internal","startTimeUnixNano":"1779351722452138709","endTimeUnixNano":"1779351722452177667","durationMs":0.038958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"572f1eaf8222169f","parentSpanId":"167c145a5df1e30c","sampled":true,"kind":"internal","startTimeUnixNano":"1779351722452801125","endTimeUnixNano":"1779351722453052459","durationMs":0.251334,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"167c145a5df1e30c","parentSpanId":"2f989ef1cbf60c79","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720233731584","endTimeUnixNano":"1779351722453078125","durationMs":2219.346541,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"f0f37a343f6b64e2d0db7d7ae658e62f","spanId":"d76a52caaabdeffb","parentSpanId":"c6d02662f522b8b6","sampled":true,"kind":"internal","startTimeUnixNano":"1779351722450764584","endTimeUnixNano":"1779351722460846042","durationMs":10.081458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"f0f37a343f6b64e2d0db7d7ae658e62f","spanId":"c6d02662f522b8b6","sampled":true,"kind":"internal","startTimeUnixNano":"1779351722450700000","endTimeUnixNano":"1779351722460907542","durationMs":10.207542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"http.client GET","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"f3a8741b7e1dc539","parentSpanId":"f724cc0e76127b72","sampled":true,"kind":"client","startTimeUnixNano":"1779351722453426334","endTimeUnixNano":"1779351722544650875","durationMs":91.224541,"attributes":{"http.request.method":"GET","server.address":"https://registry.npmjs.org","url.full":"https://registry.npmjs.org/opencode-ai/latest","url.path":"/opencode-ai/latest","url.scheme":"https","http.request.header.accept":"application/json","http.response.status_code":200,"http.response.header.access-control-allow-origin":"*","http.response.header.age":"161","http.response.header.cache-control":"public, max-age=300","http.response.header.cf-cache-status":"HIT","http.response.header.cf-ray":"9ff22bca5c85e7e5-SYD","http.response.header.connection":"keep-alive","http.response.header.content-encoding":"gzip","http.response.header.content-type":"application/json","http.response.header.date":"Thu, 21 May 2026 08:22:02 GMT","http.response.header.last-modified":"Thu, 21 May 2026 08:19:21 GMT","http.response.header.server":"cloudflare","http.response.header.set-cookie":"","http.response.header.transfer-encoding":"chunked","http.response.header.vary":"accept-encoding, accept"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"fetchNpmLatestVersion","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"f724cc0e76127b72","parentSpanId":"d07acce8caa38e21","sampled":true,"kind":"internal","startTimeUnixNano":"1779351722453267334","endTimeUnixNano":"1779351722545046334","durationMs":91.779,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveLatestProviderVersion","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"d07acce8caa38e21","parentSpanId":"2afed0facc208a7b","sampled":true,"kind":"internal","startTimeUnixNano":"1779351722453220584","endTimeUnixNano":"1779351722545055500","durationMs":91.834916,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"2afed0facc208a7b","parentSpanId":"572f1eaf8222169f","sampled":true,"kind":"internal","startTimeUnixNano":"1779351722453171959","endTimeUnixNano":"1779351722545094792","durationMs":91.922833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"90d48b8be76987d94783a2630a4d3f0b","spanId":"0f4cafaf926d5403","parentSpanId":"cef2a4f9fbb80554","sampled":true,"kind":"internal","startTimeUnixNano":"1779351722545247917","endTimeUnixNano":"1779351722545255000","durationMs":0.007083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"90d48b8be76987d94783a2630a4d3f0b","spanId":"c1230bd73fe218a9","parentSpanId":"cef2a4f9fbb80554","sampled":true,"kind":"internal","startTimeUnixNano":"1779351722545308250","endTimeUnixNano":"1779351722545316834","durationMs":0.008584,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"dd17535d5b8d955e","parentSpanId":"572f1eaf8222169f","sampled":true,"kind":"internal","startTimeUnixNano":"1779351722545149334","endTimeUnixNano":"1779351722545467875","durationMs":0.318541,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"90d48b8be76987d94783a2630a4d3f0b","spanId":"cef2a4f9fbb80554","parentSpanId":"8bb23dc2d61687d7","sampled":true,"kind":"internal","startTimeUnixNano":"1779351722545233084","endTimeUnixNano":"1779351722546062084","durationMs":0.829,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"90d48b8be76987d94783a2630a4d3f0b","spanId":"8bb23dc2d61687d7","sampled":true,"kind":"internal","startTimeUnixNano":"1779351722545222792","endTimeUnixNano":"1779351722546071375","durationMs":0.848583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"opencode.app.agents","traceId":"2ad495f195142fdec383e80ef3928086","spanId":"623ee92cad4468e7","parentSpanId":"ee354f4cc30584b8","sampled":true,"kind":"internal","startTimeUnixNano":"1779351723178281584","endTimeUnixNano":"1779351723386501042","durationMs":208.219458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"opencode.provider.list","traceId":"2ad495f195142fdec383e80ef3928086","spanId":"2c00e4acfa95fd6d","parentSpanId":"ee354f4cc30584b8","sampled":true,"kind":"internal","startTimeUnixNano":"1779351723178178500","endTimeUnixNano":"1779351723497235000","durationMs":319.0565,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"checkOpenCodeProviderStatus","traceId":"2ad495f195142fdec383e80ef3928086","spanId":"ee354f4cc30584b8","parentSpanId":"e6abffabb840a537","sampled":true,"kind":"internal","startTimeUnixNano":"1779351722454883042","endTimeUnixNano":"1779351724499680709","durationMs":2044.797667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"12b3cf766b5f1dffd38ae4e9dbf94128","spanId":"0e39bba50ff8dc02","parentSpanId":"3bf99f989ad39d99","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724500159292","endTimeUnixNano":"1779351724500196875","durationMs":0.037583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"12b3cf766b5f1dffd38ae4e9dbf94128","spanId":"c03eb262582e803e","parentSpanId":"3bf99f989ad39d99","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724502161792","endTimeUnixNano":"1779351724502201584","durationMs":0.039792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"2ad495f195142fdec383e80ef3928086","spanId":"70da3c0529085b9b","parentSpanId":"e6abffabb840a537","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724502819292","endTimeUnixNano":"1779351724502945917","durationMs":0.126625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"2ad495f195142fdec383e80ef3928086","spanId":"e6abffabb840a537","parentSpanId":"57375938ad3384ed","sampled":true,"kind":"internal","startTimeUnixNano":"1779351722454845084","endTimeUnixNano":"1779351724502966084","durationMs":2048.121,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"2ad495f195142fdec383e80ef3928086","spanId":"57375938ad3384ed","parentSpanId":"bf834cf4e1c398de","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720306795000","endTimeUnixNano":"1779351724502988375","durationMs":4196.193375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"2ad495f195142fdec383e80ef3928086","spanId":"2111f162f30b8df5","parentSpanId":"404c2eaaa6974a4b","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724503081709","endTimeUnixNano":"1779351724503098959","durationMs":0.01725,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"2ad495f195142fdec383e80ef3928086","spanId":"404c2eaaa6974a4b","parentSpanId":"7aa9cd76e9d6ae9d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724503047375","endTimeUnixNano":"1779351724503280167","durationMs":0.232792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"2ad495f195142fdec383e80ef3928086","spanId":"7aa9cd76e9d6ae9d","parentSpanId":"bf834cf4e1c398de","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724503022750","endTimeUnixNano":"1779351724503297667","durationMs":0.274917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshOneSource","traceId":"2ad495f195142fdec383e80ef3928086","spanId":"bf834cf4e1c398de","sampled":true,"kind":"internal","startTimeUnixNano":"1779351720306788959","endTimeUnixNano":"1779351724503310834","durationMs":4196.521875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"57fa3ceb547178d65a9b155222a565db","spanId":"a430848ed7048bc5","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724503366834","endTimeUnixNano":"1779351724503405042","durationMs":0.038208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveLatestProviderVersion","traceId":"2ad495f195142fdec383e80ef3928086","spanId":"99efe57f6d45ef6f","parentSpanId":"670936a64b45b3c7","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724738905375","endTimeUnixNano":"1779351724738952792","durationMs":0.047417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"2ad495f195142fdec383e80ef3928086","spanId":"670936a64b45b3c7","parentSpanId":"70da3c0529085b9b","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724738853375","endTimeUnixNano":"1779351724739154959","durationMs":0.301584,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"2ad495f195142fdec383e80ef3928086","spanId":"5598adba667bb90c","parentSpanId":"70da3c0529085b9b","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724739183042","endTimeUnixNano":"1779351724739573375","durationMs":0.390333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeTerminalManagerWithOptions","traceId":"75dff94e00229c16952f88865face46f","spanId":"7508bc89d2396f33","parentSpanId":"588995a68c34391d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724737748042","endTimeUnixNano":"1779351724741600292","durationMs":3.85225,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeTerminalManager","traceId":"75dff94e00229c16952f88865face46f","spanId":"588995a68c34391d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724737538375","endTimeUnixNano":"1779351724741632417","durationMs":4.094042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeOrchestrationProjectionPipeline","traceId":"94c913a384fb61b7a5a98ef17c272aeb","spanId":"e4ededf6c8ea9504","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724744726417","endTimeUnixNano":"1779351724745128084","durationMs":0.401667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"0dd402b030f53281b59baf4d77bc6ddd","spanId":"05a8f6be96179b68","sampled":true,"kind":"client","startTimeUnixNano":"1779351724746003125","endTimeUnixNano":"1779351724746303000","durationMs":0.299875,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n projector,\n last_applied_sequence AS \"lastAppliedSequence\",\n updated_at AS \"updatedAt\"\n FROM projection_state\n WHERE projector = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"b9d5f81c3cf8b36a3b17e9a5b0957790","spanId":"6606625c56c0dd67","sampled":true,"kind":"client","startTimeUnixNano":"1779351724747127792","endTimeUnixNano":"1779351724747668709","durationMs":0.540917,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n sequence,\n event_id AS \"eventId\",\n event_type AS \"type\",\n aggregate_kind AS \"aggregateKind\",\n stream_id AS \"aggregateId\",\n occurred_at AS \"occurredAt\",\n command_id AS \"commandId\",\n causation_event_id AS \"causationEventId\",\n correlation_id AS \"correlationId\",\n payload_json AS \"payload\",\n metadata_json AS \"metadata\"\n FROM orchestration_events\n WHERE sequence > ?\n ORDER BY sequence ASC\n LIMIT ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"f57236bd18d018b63caa0919d93fc925","spanId":"c63d85661c298a5b","sampled":true,"kind":"client","startTimeUnixNano":"1779351724748069875","endTimeUnixNano":"1779351724748166750","durationMs":0.096875,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n projector,\n last_applied_sequence AS \"lastAppliedSequence\",\n updated_at AS \"updatedAt\"\n FROM projection_state\n WHERE projector = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"2e281e14070b435f323888bf52141ab4","spanId":"a9306e06ac7e1835","sampled":true,"kind":"client","startTimeUnixNano":"1779351724748272209","endTimeUnixNano":"1779351724748349334","durationMs":0.077125,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n sequence,\n event_id AS \"eventId\",\n event_type AS \"type\",\n aggregate_kind AS \"aggregateKind\",\n stream_id AS \"aggregateId\",\n occurred_at AS \"occurredAt\",\n command_id AS \"commandId\",\n causation_event_id AS \"causationEventId\",\n correlation_id AS \"correlationId\",\n payload_json AS \"payload\",\n metadata_json AS \"metadata\"\n FROM orchestration_events\n WHERE sequence > ?\n ORDER BY sequence ASC\n LIMIT ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"fd2b39a6f4dd0c62c580445a7c96c2c6","spanId":"c4b0a39b5ced0928","sampled":true,"kind":"client","startTimeUnixNano":"1779351724748397834","endTimeUnixNano":"1779351724748427875","durationMs":0.030041,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n projector,\n last_applied_sequence AS \"lastAppliedSequence\",\n updated_at AS \"updatedAt\"\n FROM projection_state\n WHERE projector = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"b36a36b9056d659b514611e325548abe","spanId":"1fcf4c73879ae530","sampled":true,"kind":"client","startTimeUnixNano":"1779351724748502459","endTimeUnixNano":"1779351724748555917","durationMs":0.053458,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n sequence,\n event_id AS \"eventId\",\n event_type AS \"type\",\n aggregate_kind AS \"aggregateKind\",\n stream_id AS \"aggregateId\",\n occurred_at AS \"occurredAt\",\n command_id AS \"commandId\",\n causation_event_id AS \"causationEventId\",\n correlation_id AS \"correlationId\",\n payload_json AS \"payload\",\n metadata_json AS \"metadata\"\n FROM orchestration_events\n WHERE sequence > ?\n ORDER BY sequence ASC\n LIMIT ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"e4a4ffa7f86e3f5a036a9fe32970e4be","spanId":"1ebd8bacd4073485","sampled":true,"kind":"client","startTimeUnixNano":"1779351724748594292","endTimeUnixNano":"1779351724748623042","durationMs":0.02875,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n projector,\n last_applied_sequence AS \"lastAppliedSequence\",\n updated_at AS \"updatedAt\"\n FROM projection_state\n WHERE projector = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"2f26cf4d5d58acae6514d6dbf52a452f","spanId":"87730579e261eae9","sampled":true,"kind":"client","startTimeUnixNano":"1779351724748661709","endTimeUnixNano":"1779351724748716000","durationMs":0.054291,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n sequence,\n event_id AS \"eventId\",\n event_type AS \"type\",\n aggregate_kind AS \"aggregateKind\",\n stream_id AS \"aggregateId\",\n occurred_at AS \"occurredAt\",\n command_id AS \"commandId\",\n causation_event_id AS \"causationEventId\",\n correlation_id AS \"correlationId\",\n payload_json AS \"payload\",\n metadata_json AS \"metadata\"\n FROM orchestration_events\n WHERE sequence > ?\n ORDER BY sequence ASC\n LIMIT ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"fef69afd083b3d2f82d721a917604ce8","spanId":"a5465214212db4ac","sampled":true,"kind":"client","startTimeUnixNano":"1779351724748760875","endTimeUnixNano":"1779351724748799750","durationMs":0.038875,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n projector,\n last_applied_sequence AS \"lastAppliedSequence\",\n updated_at AS \"updatedAt\"\n FROM projection_state\n WHERE projector = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"923465c3366a34926adc472f8b78c139","spanId":"75a0bbab0e60b8b7","sampled":true,"kind":"client","startTimeUnixNano":"1779351724748858292","endTimeUnixNano":"1779351724748920792","durationMs":0.0625,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n sequence,\n event_id AS \"eventId\",\n event_type AS \"type\",\n aggregate_kind AS \"aggregateKind\",\n stream_id AS \"aggregateId\",\n occurred_at AS \"occurredAt\",\n command_id AS \"commandId\",\n causation_event_id AS \"causationEventId\",\n correlation_id AS \"correlationId\",\n payload_json AS \"payload\",\n metadata_json AS \"metadata\"\n FROM orchestration_events\n WHERE sequence > ?\n ORDER BY sequence ASC\n LIMIT ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"29a5b581b625cf6db61415b4ecb4b371","spanId":"a55cc4f07e3aef84","sampled":true,"kind":"client","startTimeUnixNano":"1779351724748975334","endTimeUnixNano":"1779351724749002584","durationMs":0.02725,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n projector,\n last_applied_sequence AS \"lastAppliedSequence\",\n updated_at AS \"updatedAt\"\n FROM projection_state\n WHERE projector = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"811a7fb9e6bf7b85481fbfe70a157e13","spanId":"ae01f5e9ca47eeda","sampled":true,"kind":"client","startTimeUnixNano":"1779351724749037292","endTimeUnixNano":"1779351724749084167","durationMs":0.046875,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n sequence,\n event_id AS \"eventId\",\n event_type AS \"type\",\n aggregate_kind AS \"aggregateKind\",\n stream_id AS \"aggregateId\",\n occurred_at AS \"occurredAt\",\n command_id AS \"commandId\",\n causation_event_id AS \"causationEventId\",\n correlation_id AS \"correlationId\",\n payload_json AS \"payload\",\n metadata_json AS \"metadata\"\n FROM orchestration_events\n WHERE sequence > ?\n ORDER BY sequence ASC\n LIMIT ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"dacaea0fcd926c0973617d6ca7d484ca","spanId":"3775519dc35f2d38","sampled":true,"kind":"client","startTimeUnixNano":"1779351724749118750","endTimeUnixNano":"1779351724749144084","durationMs":0.025334,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n projector,\n last_applied_sequence AS \"lastAppliedSequence\",\n updated_at AS \"updatedAt\"\n FROM projection_state\n WHERE projector = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"bc83ed1ebd050d99318703443b69316c","spanId":"e922c80271e8cf7e","sampled":true,"kind":"client","startTimeUnixNano":"1779351724749179834","endTimeUnixNano":"1779351724749225084","durationMs":0.04525,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n sequence,\n event_id AS \"eventId\",\n event_type AS \"type\",\n aggregate_kind AS \"aggregateKind\",\n stream_id AS \"aggregateId\",\n occurred_at AS \"occurredAt\",\n command_id AS \"commandId\",\n causation_event_id AS \"causationEventId\",\n correlation_id AS \"correlationId\",\n payload_json AS \"payload\",\n metadata_json AS \"metadata\"\n FROM orchestration_events\n WHERE sequence > ?\n ORDER BY sequence ASC\n LIMIT ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"8e8f1f68d8976469495968f4e8e1d70b","spanId":"bc3fffd21aa63a97","sampled":true,"kind":"client","startTimeUnixNano":"1779351724749256250","endTimeUnixNano":"1779351724749281542","durationMs":0.025292,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n projector,\n last_applied_sequence AS \"lastAppliedSequence\",\n updated_at AS \"updatedAt\"\n FROM projection_state\n WHERE projector = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"a2944a9c9c9bd31f1272e88bd6f1df5f","spanId":"d578ef9ac99b0e3d","sampled":true,"kind":"client","startTimeUnixNano":"1779351724749320875","endTimeUnixNano":"1779351724749365709","durationMs":0.044834,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n sequence,\n event_id AS \"eventId\",\n event_type AS \"type\",\n aggregate_kind AS \"aggregateKind\",\n stream_id AS \"aggregateId\",\n occurred_at AS \"occurredAt\",\n command_id AS \"commandId\",\n causation_event_id AS \"causationEventId\",\n correlation_id AS \"correlationId\",\n payload_json AS \"payload\",\n metadata_json AS \"metadata\"\n FROM orchestration_events\n WHERE sequence > ?\n ORDER BY sequence ASC\n LIMIT ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5db4fd58826032df680e8b2fe410a48b","spanId":"cf9066bf4765b4a6","sampled":true,"kind":"client","startTimeUnixNano":"1779351724749403125","endTimeUnixNano":"1779351724749429209","durationMs":0.026084,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n projector,\n last_applied_sequence AS \"lastAppliedSequence\",\n updated_at AS \"updatedAt\"\n FROM projection_state\n WHERE projector = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"422431420ebecd00f59978043c5ca163","spanId":"7d9703ef91baf228","sampled":true,"kind":"client","startTimeUnixNano":"1779351724749476125","endTimeUnixNano":"1779351724749532750","durationMs":0.056625,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n sequence,\n event_id AS \"eventId\",\n event_type AS \"type\",\n aggregate_kind AS \"aggregateKind\",\n stream_id AS \"aggregateId\",\n occurred_at AS \"occurredAt\",\n command_id AS \"commandId\",\n causation_event_id AS \"causationEventId\",\n correlation_id AS \"correlationId\",\n payload_json AS \"payload\",\n metadata_json AS \"metadata\"\n FROM orchestration_events\n WHERE sequence > ?\n ORDER BY sequence ASC\n LIMIT ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"7531ddd26b0597e939430a0d8b118706","spanId":"e13c1f39ae0ceccd","parentSpanId":"f123cb00b162644a","sampled":true,"kind":"client","startTimeUnixNano":"1779351724750013417","endTimeUnixNano":"1779351724750110125","durationMs":0.096708,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n project_id AS \"projectId\",\n title,\n workspace_root AS \"workspaceRoot\",\n default_model_selection_json AS \"defaultModelSelection\",\n scripts_json AS \"scripts\",\n created_at AS \"createdAt\",\n updated_at AS \"updatedAt\",\n deleted_at AS \"deletedAt\"\n FROM projection_projects\n ORDER BY created_at ASC, project_id ASC\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"7531ddd26b0597e939430a0d8b118706","spanId":"b494b655c80a857d","parentSpanId":"f123cb00b162644a","sampled":true,"kind":"client","startTimeUnixNano":"1779351724750161125","endTimeUnixNano":"1779351724750265542","durationMs":0.104417,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n thread_id AS \"threadId\",\n project_id AS \"projectId\",\n title,\n model_selection_json AS \"modelSelection\",\n runtime_mode AS \"runtimeMode\",\n interaction_mode AS \"interactionMode\",\n branch,\n worktree_path AS \"worktreePath\",\n latest_turn_id AS \"latestTurnId\",\n created_at AS \"createdAt\",\n updated_at AS \"updatedAt\",\n archived_at AS \"archivedAt\",\n latest_user_message_at AS \"latestUserMessageAt\",\n pending_approval_count AS \"pendingApprovalCount\",\n pending_user_input_count AS \"pendingUserInputCount\",\n has_actionable_proposed_plan AS \"hasActionableProposedPlan\",\n deleted_at AS \"deletedAt\"\n FROM projection_threads\n ORDER BY created_at ASC, thread_id ASC\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"7531ddd26b0597e939430a0d8b118706","spanId":"3c5f64f36e701237","parentSpanId":"f123cb00b162644a","sampled":true,"kind":"client","startTimeUnixNano":"1779351724750299625","endTimeUnixNano":"1779351724750377959","durationMs":0.078334,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n plan_id AS \"planId\",\n thread_id AS \"threadId\",\n turn_id AS \"turnId\",\n plan_markdown AS \"planMarkdown\",\n implemented_at AS \"implementedAt\",\n implementation_thread_id AS \"implementationThreadId\",\n created_at AS \"createdAt\",\n updated_at AS \"updatedAt\"\n FROM projection_thread_proposed_plans\n ORDER BY thread_id ASC, created_at ASC, plan_id ASC\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"7531ddd26b0597e939430a0d8b118706","spanId":"c8e3b44747533e3c","parentSpanId":"f123cb00b162644a","sampled":true,"kind":"client","startTimeUnixNano":"1779351724750412875","endTimeUnixNano":"1779351724750487917","durationMs":0.075042,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n thread_id AS \"threadId\",\n status,\n provider_name AS \"providerName\",\n provider_instance_id AS \"providerInstanceId\",\n provider_session_id AS \"providerSessionId\",\n provider_thread_id AS \"providerThreadId\",\n runtime_mode AS \"runtimeMode\",\n active_turn_id AS \"activeTurnId\",\n last_error AS \"lastError\",\n updated_at AS \"updatedAt\"\n FROM projection_thread_sessions\n ORDER BY thread_id ASC\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"7531ddd26b0597e939430a0d8b118706","spanId":"c7e94fdf94de7746","parentSpanId":"f123cb00b162644a","sampled":true,"kind":"client","startTimeUnixNano":"1779351724750531875","endTimeUnixNano":"1779351724750629375","durationMs":0.0975,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n turns.thread_id AS \"threadId\",\n turns.turn_id AS \"turnId\",\n turns.state,\n turns.requested_at AS \"requestedAt\",\n turns.started_at AS \"startedAt\",\n turns.completed_at AS \"completedAt\",\n turns.assistant_message_id AS \"assistantMessageId\",\n turns.source_proposed_plan_thread_id AS \"sourceProposedPlanThreadId\",\n turns.source_proposed_plan_id AS \"sourceProposedPlanId\"\n FROM projection_threads threads\n JOIN projection_turns turns\n ON turns.thread_id = threads.thread_id\n AND turns.turn_id = threads.latest_turn_id\n WHERE threads.latest_turn_id IS NOT NULL\n ORDER BY turns.thread_id ASC\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"7531ddd26b0597e939430a0d8b118706","spanId":"62104f81873d4522","parentSpanId":"f123cb00b162644a","sampled":true,"kind":"client","startTimeUnixNano":"1779351724750660125","endTimeUnixNano":"1779351724750704250","durationMs":0.044125,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n projector,\n last_applied_sequence AS \"lastAppliedSequence\",\n updated_at AS \"updatedAt\"\n FROM projection_state\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.transaction","traceId":"7531ddd26b0597e939430a0d8b118706","spanId":"f123cb00b162644a","sampled":true,"kind":"client","startTimeUnixNano":"1779351724749890375","endTimeUnixNano":"1779351724750755250","durationMs":0.864875,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite"},"events":[{"name":"db.transaction.commit","timeUnixNano":"1779351724750725084","attributes":{}}],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeProviderAdapterRegistry","traceId":"10d60ca63a42428254e7cd17c10c18a2","spanId":"a74f6cc6deaf1803","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724751607042","endTimeUnixNano":"1779351724751718709","durationMs":0.111667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeProviderService","traceId":"9819a646e1942a0d1e9061ad3054e5af","spanId":"e3dac6c835a197fc","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724751755209","endTimeUnixNano":"1779351724752376459","durationMs":0.62125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeGitVcsDriverCore","traceId":"75f965cd6f5dafd8a6cd8cba2d46044c","spanId":"7ca5121f83118709","parentSpanId":"8fcebdd952e79523","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724752658084","endTimeUnixNano":"1779351724753239709","durationMs":0.581625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeGitVcsDriverService","traceId":"75f965cd6f5dafd8a6cd8cba2d46044c","spanId":"8fcebdd952e79523","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724752610917","endTimeUnixNano":"1779351724753277584","durationMs":0.666667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeAzureDevOpsCli","traceId":"d2fbc8063dd58867ee8434b2dc6d9db9","spanId":"16a40f73c99d1f53","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724753660709","endTimeUnixNano":"1779351724753788042","durationMs":0.127333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeBitbucketApi","traceId":"f7c993515ece5acce69c13e3d2d6e458","spanId":"a75442ee112ac2e5","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724753818375","endTimeUnixNano":"1779351724754251000","durationMs":0.432625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeGitHubCli","traceId":"ca72ef4ad5c87c4f626ecf08e8653336","spanId":"3d72f345093f93bc","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724754295709","endTimeUnixNano":"1779351724754434459","durationMs":0.13875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeGitLabCli","traceId":"a448b6cb42103924a78e624fec1c6e1f","spanId":"5b1f698b2f89f6c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724754471042","endTimeUnixNano":"1779351724754602167","durationMs":0.131125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeGitHubSourceControlProvider","traceId":"86232672c08c8890f01c124f0909579c","spanId":"83155a995bc1157d","parentSpanId":"fd7387f6ffa6bfe6","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724754715375","endTimeUnixNano":"1779351724754817959","durationMs":0.102584,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeGitLabSourceControlProvider","traceId":"86232672c08c8890f01c124f0909579c","spanId":"eacd8c1d9bd64944","parentSpanId":"fd7387f6ffa6bfe6","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724754838500","endTimeUnixNano":"1779351724754911375","durationMs":0.072875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeBitbucketSourceControlProvider","traceId":"86232672c08c8890f01c124f0909579c","spanId":"157e4271c7db1f85","parentSpanId":"fd7387f6ffa6bfe6","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724754929167","endTimeUnixNano":"1779351724755011375","durationMs":0.082208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeBitbucketSourceControlProviderDiscovery","traceId":"86232672c08c8890f01c124f0909579c","spanId":"7a432d5f34f4a842","parentSpanId":"fd7387f6ffa6bfe6","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724755028792","endTimeUnixNano":"1779351724755064834","durationMs":0.036042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeAzureDevOpsSourceControlProvider","traceId":"86232672c08c8890f01c124f0909579c","spanId":"79901d91a9e187c6","parentSpanId":"fd7387f6ffa6bfe6","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724755080750","endTimeUnixNano":"1779351724755155750","durationMs":0.075,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeSourceControlProviderRegistryWithProviders","traceId":"86232672c08c8890f01c124f0909579c","spanId":"3ae1d89ae99dbca7","parentSpanId":"fd7387f6ffa6bfe6","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724755180625","endTimeUnixNano":"1779351724755483750","durationMs":0.303125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeSourceControlProviderRegistry","traceId":"86232672c08c8890f01c124f0909579c","spanId":"fd7387f6ffa6bfe6","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724754640750","endTimeUnixNano":"1779351724755492334","durationMs":0.851584,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeGitManager","traceId":"b504c411cfaca35f3e9bb96105d46ad9","spanId":"8c1cb6ebff835248","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724755611917","endTimeUnixNano":"1779351724755915167","durationMs":0.30325,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeGitWorkflowService","traceId":"06ff17f62e057c1ff9fc62583c5c46d9","spanId":"01922f60e8e2f4bd","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724755991292","endTimeUnixNano":"1779351724756138542","durationMs":0.14725,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeSourceControlRepositoryService","traceId":"e101d64a3959a21fb0464a5e90bcaacf","spanId":"b18281e92e615a0e","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724756470709","endTimeUnixNano":"1779351724756574917","durationMs":0.104208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeVcsProvisioningService","traceId":"8b96247f0c88e745d84657f976998d9c","spanId":"5521b361a448312e","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724756829834","endTimeUnixNano":"1779351724756861875","durationMs":0.032041,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"server.startup.keybindings.start","traceId":"9c222a79013464bbed30efe9f66a4107","spanId":"24c69dd453cbefe8","parentSpanId":"0056b60dfb515e9e","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724770487417","endTimeUnixNano":"1779351724770535084","durationMs":0.047667,"attributes":{"server.mode":"desktop","server.port":14124,"server.host":"127.0.0.1"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"server.startup.settings.start","traceId":"9c222a79013464bbed30efe9f66a4107","spanId":"9b32331e7c56d7c3","parentSpanId":"0056b60dfb515e9e","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724770561959","endTimeUnixNano":"1779351724770601750","durationMs":0.039791,"attributes":{"server.mode":"desktop","server.port":14124,"server.host":"127.0.0.1"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"start","traceId":"9c222a79013464bbed30efe9f66a4107","spanId":"02bc1709635397f9","parentSpanId":"b3fc878a7aa36b26","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724770796000","endTimeUnixNano":"1779351724770836167","durationMs":0.040167,"attributes":{"server.mode":"desktop","server.port":14124,"server.host":"127.0.0.1","startup.phase":"reactors.start"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"start","traceId":"9c222a79013464bbed30efe9f66a4107","spanId":"3c37af21c3202a8f","parentSpanId":"b3fc878a7aa36b26","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724770856292","endTimeUnixNano":"1779351724770902084","durationMs":0.045792,"attributes":{"server.mode":"desktop","server.port":14124,"server.host":"127.0.0.1","startup.phase":"reactors.start"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"start","traceId":"9c222a79013464bbed30efe9f66a4107","spanId":"a178620fdc14db43","parentSpanId":"b3fc878a7aa36b26","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724770928792","endTimeUnixNano":"1779351724770958875","durationMs":0.030083,"attributes":{"server.mode":"desktop","server.port":14124,"server.host":"127.0.0.1","startup.phase":"reactors.start"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"start","traceId":"9c222a79013464bbed30efe9f66a4107","spanId":"b3fc878a7aa36b26","parentSpanId":"bdaa4ceb2b2577ba","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724770689000","endTimeUnixNano":"1779351724770966750","durationMs":0.27775,"attributes":{"server.mode":"desktop","server.port":14124,"server.host":"127.0.0.1","startup.phase":"reactors.start"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"server.startup.reactors.start","traceId":"9c222a79013464bbed30efe9f66a4107","spanId":"bdaa4ceb2b2577ba","parentSpanId":"0056b60dfb515e9e","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724770617542","endTimeUnixNano":"1779351724771330250","durationMs":0.712708,"attributes":{"server.mode":"desktop","server.port":14124,"server.host":"127.0.0.1"},"events":[{"name":"[\n \"provider.session.reaper.started\",\n {\n \"inactivityThresholdMs\": 1800000,\n \"sweepIntervalMs\": 300000\n }\n]","timeUnixNano":"1779351724771323417","attributes":{"effect.fiberId":221,"effect.logLevel":"INFO"}}],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"server.startup.welcome.publish","traceId":"9c222a79013464bbed30efe9f66a4107","spanId":"1300e3f4fcb72565","parentSpanId":"0056b60dfb515e9e","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724771459959","endTimeUnixNano":"1779351724771525042","durationMs":0.065083,"attributes":{"server.mode":"desktop","server.port":14124,"server.host":"127.0.0.1"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"server.startup","traceId":"9c222a79013464bbed30efe9f66a4107","spanId":"0056b60dfb515e9e","sampled":true,"kind":"server","startTimeUnixNano":"1779351724770326542","endTimeUnixNano":"1779351724771534459","durationMs":1.207917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"server.startup.http.wait","traceId":"09596df92b004c7b82e3c5ed5097b8d7","spanId":"202466da6a2477ca","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724771574000","endTimeUnixNano":"1779351724771618792","durationMs":0.044792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"server.startup.ready.publish","traceId":"db5574eccfa041eb123ccda2f5258721","spanId":"4f095a690d46d032","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724771645875","endTimeUnixNano":"1779351724771689750","durationMs":0.043875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"server.startup.browser.open","traceId":"f6a72837a00e6b9cff1f476f679b18c3","spanId":"85a389b1dc77d6e1","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724771768500","endTimeUnixNano":"1779351724771819750","durationMs":0.05125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"http.server GET","traceId":"e16fc91fcd31b9f52a039efc57aa057e","spanId":"3ea070d0aa3407a6","parentSpanId":"b359e8dc109d7f0b","sampled":true,"kind":"server","startTimeUnixNano":"1779351724768168500","endTimeUnixNano":"1779351724769738209","durationMs":1.569709,"attributes":{"http.route":"/.well-known/t3/environment","http.request.method":"GET","url.full":"http://127.0.0.1:14124/.well-known/t3/environment","url.path":"/.well-known/t3/environment","url.scheme":"http","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"keep-alive","http.request.header.b3":"e16fc91fcd31b9f52a039efc57aa057e-b359e8dc109d7f0b-1-bf86a4316ccb76d5","http.request.header.traceparent":"00-e16fc91fcd31b9f52a039efc57aa057e-b359e8dc109d7f0b-01","client.address":"127.0.0.1","http.response.status_code":200,"http.response.header.access-control-allow-origin":"*","http.response.header.access-control-allow-methods":"GET, POST, OPTIONS","http.response.header.access-control-allow-headers":"authorization, b3, traceparent, content-type","http.response.header.content-type":"application/json","http.response.header.content-length":"198"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"9c222a79013464bbed30efe9f66a4107","spanId":"9e5eaeac19c66d8d","parentSpanId":"bdaa4ceb2b2577ba","sampled":true,"kind":"client","startTimeUnixNano":"1779351724773070542","endTimeUnixNano":"1779351724773258792","durationMs":0.18825,"attributes":{"server.mode":"desktop","server.port":14124,"server.host":"127.0.0.1","startup.phase":"reactors.start","db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n thread_id AS \"threadId\",\n provider_name AS \"providerName\",\n provider_instance_id AS \"providerInstanceId\",\n adapter_key AS \"adapterKey\",\n runtime_mode AS \"runtimeMode\",\n status,\n last_seen_at AS \"lastSeenAt\",\n resume_cursor_json AS \"resumeCursor\",\n runtime_payload_json AS \"runtimePayload\"\n FROM provider_session_runtime\n ORDER BY last_seen_at ASC, thread_id ASC\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"7aeedf6bd754ba8051f60d82cd0a5a5e","spanId":"fb940cf0c1c2fe7b","parentSpanId":"a240b1be637ff655","sampled":true,"kind":"client","startTimeUnixNano":"1779351724773677000","endTimeUnixNano":"1779351724773796209","durationMs":0.119209,"attributes":{"startup.phase":"heartbeat.record","db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n (SELECT COUNT(*) FROM projection_projects) AS \"projectCount\",\n (SELECT COUNT(*) FROM projection_threads) AS \"threadCount\"\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"record","traceId":"7aeedf6bd754ba8051f60d82cd0a5a5e","spanId":"3bc63e773dc3fffb","parentSpanId":"a240b1be637ff655","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724773921917","endTimeUnixNano":"1779351724774082667","durationMs":0.16075,"attributes":{"startup.phase":"heartbeat.record"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"server.startup.heartbeat.record","traceId":"7aeedf6bd754ba8051f60d82cd0a5a5e","spanId":"a240b1be637ff655","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724773499084","endTimeUnixNano":"1779351724774098125","durationMs":0.599041,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"12b3cf766b5f1dffd38ae4e9dbf94128","spanId":"3bf99f989ad39d99","parentSpanId":"65eab547105e0eb8","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724500068417","endTimeUnixNano":"1779351724777838875","durationMs":277.770458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"12b3cf766b5f1dffd38ae4e9dbf94128","spanId":"65eab547105e0eb8","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724499975917","endTimeUnixNano":"1779351724777870125","durationMs":277.894208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"ce4548b2f875185d3908e6731327bb9d","spanId":"476f7a0bdff72982","parentSpanId":"743ded6294866428","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724778016584","endTimeUnixNano":"1779351724778035792","durationMs":0.019208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"ce4548b2f875185d3908e6731327bb9d","spanId":"a3c56738f056d185","parentSpanId":"743ded6294866428","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724778182459","endTimeUnixNano":"1779351724778202167","durationMs":0.019708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"ce4548b2f875185d3908e6731327bb9d","spanId":"743ded6294866428","parentSpanId":"7658b3fbf1e54de2","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724777976792","endTimeUnixNano":"1779351724787815417","durationMs":9.838625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"ce4548b2f875185d3908e6731327bb9d","spanId":"7658b3fbf1e54de2","sampled":true,"kind":"internal","startTimeUnixNano":"1779351724777943917","endTimeUnixNano":"1779351724787840209","durationMs":9.896292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"45314b2d07dceb15","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351725215092000","endTimeUnixNano":"1779351725261035875","durationMs":45.943875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"http.client POST","traceId":"33234013898b6a619a84ebb8d69b4cb7","spanId":"ff84065c026fbc25","parentSpanId":"fd48b06913c1b2bb","sampled":true,"kind":"client","startTimeUnixNano":"1779351725192691334","endTimeUnixNano":"1779351725855235875","durationMs":662.544541,"attributes":{"http.request.method":"POST","server.address":"https://us.i.posthog.com","url.full":"https://us.i.posthog.com/batch/","url.path":"/batch/","url.scheme":"https","http.request.header.content-type":"application/json","http.request.header.content-length":"392","http.response.status_code":200,"http.response.header.access-control-allow-credentials":"true","http.response.header.connection":"keep-alive","http.response.header.content-length":"15","http.response.header.content-type":"application/json","http.response.header.date":"Thu, 21 May 2026 08:22:05 GMT","http.response.header.server":"envoy","http.response.header.strict-transport-security":"max-age=31536000; includeSubDomains","http.response.header.vary":"origin, access-control-request-method, access-control-request-headers","http.response.header.x-envoy-upstream-service-time":"21"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sendBatch","traceId":"33234013898b6a619a84ebb8d69b4cb7","spanId":"fd48b06913c1b2bb","sampled":true,"kind":"internal","startTimeUnixNano":"1779351725192199334","endTimeUnixNano":"1779351725855343167","durationMs":663.143833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"4a73560720def7a7","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351730263014792","endTimeUnixNano":"1779351730290641209","durationMs":27.626417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"http.server GET","traceId":"da2c9f462efcc38ece9e5e9dcfdc61f7","spanId":"ae872c828b44cfa7","sampled":true,"kind":"server","startTimeUnixNano":"1779351731704114417","endTimeUnixNano":"1779351731704334209","durationMs":0.219792,"attributes":{"http.route":"/.well-known/t3/environment","http.request.method":"GET","url.full":"http://127.0.0.1:14124/.well-known/t3/environment","url.path":"/.well-known/t3/environment","url.scheme":"http","user_agent.original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"close","http.request.header.sec-ch-ua-platform":"\"macOS\"","http.request.header.user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.sec-ch-ua":"\"Not-A.Brand\";v=\"24\", \"Chromium\";v=\"146\"","http.request.header.sec-ch-ua-mobile":"?0","http.request.header.accept":"*/*","http.request.header.sec-fetch-site":"same-origin","http.request.header.sec-fetch-mode":"cors","http.request.header.sec-fetch-dest":"empty","http.request.header.referer":"http://127.0.0.1:6084/","http.request.header.accept-encoding":"gzip, deflate, br, zstd","http.request.header.accept-language":"en-GB","http.response.status_code":200,"http.response.header.access-control-allow-origin":"*","http.response.header.access-control-allow-methods":"GET, POST, OPTIONS","http.response.header.access-control-allow-headers":"authorization, b3, traceparent, content-type","http.response.header.content-type":"application/json","http.response.header.content-length":"198"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"http.server GET","traceId":"8e5e0f45d1218863b5b92fcdd37049dd","spanId":"b43d80afa0da7f96","sampled":true,"kind":"server","startTimeUnixNano":"1779351731704593667","endTimeUnixNano":"1779351731704917292","durationMs":0.323625,"attributes":{"http.route":"/api/auth/session","http.request.method":"GET","url.full":"http://127.0.0.1:14124/api/auth/session","url.path":"/api/auth/session","url.scheme":"http","user_agent.original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"close","http.request.header.sec-ch-ua-platform":"\"macOS\"","http.request.header.user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.sec-ch-ua":"\"Not-A.Brand\";v=\"24\", \"Chromium\";v=\"146\"","http.request.header.sec-ch-ua-mobile":"?0","http.request.header.accept":"*/*","http.request.header.sec-fetch-site":"same-origin","http.request.header.sec-fetch-mode":"cors","http.request.header.sec-fetch-dest":"empty","http.request.header.referer":"http://127.0.0.1:6084/","http.request.header.accept-encoding":"gzip, deflate, br, zstd","http.request.header.accept-language":"en-GB","http.response.status_code":200,"http.response.header.access-control-allow-origin":"*","http.response.header.access-control-allow-methods":"GET, POST, OPTIONS","http.response.header.access-control-allow-headers":"authorization, b3, traceparent, content-type","http.response.header.content-type":"application/json","http.response.header.content-length":"212"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"1541893ec9797670053ac485980e94b8","spanId":"e34ae2dd358203f8","parentSpanId":"8dcf45cc189f2350","sampled":true,"kind":"client","startTimeUnixNano":"1779351731710730875","endTimeUnixNano":"1779351731711276250","durationMs":0.545375,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n INSERT INTO auth_sessions (\n session_id,\n subject,\n role,\n method,\n client_label,\n client_ip_address,\n client_user_agent,\n client_device_type,\n client_os,\n client_browser,\n issued_at,\n expires_at,\n revoked_at\n )\n VALUES (\n ?,\n ?,\n ?,\n ?,\n ?,\n ?,\n ?,\n ?,\n ?,\n ?,\n ?,\n ?,\n NULL\n )\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"http.server POST","traceId":"1541893ec9797670053ac485980e94b8","spanId":"8dcf45cc189f2350","sampled":true,"kind":"server","startTimeUnixNano":"1779351731708027917","endTimeUnixNano":"1779351731711789417","durationMs":3.7615,"attributes":{"http.route":"/api/auth/bootstrap","http.request.method":"POST","url.full":"http://127.0.0.1:14124/api/auth/bootstrap","url.path":"/api/auth/bootstrap","url.scheme":"http","user_agent.original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"close","http.request.header.content-length":"65","http.request.header.sec-ch-ua-platform":"\"macOS\"","http.request.header.user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.sec-ch-ua":"\"Not-A.Brand\";v=\"24\", \"Chromium\";v=\"146\"","http.request.header.content-type":"application/json","http.request.header.sec-ch-ua-mobile":"?0","http.request.header.accept":"*/*","http.request.header.origin":"http://127.0.0.1:6084","http.request.header.sec-fetch-site":"same-origin","http.request.header.sec-fetch-mode":"cors","http.request.header.sec-fetch-dest":"empty","http.request.header.referer":"http://127.0.0.1:6084/","http.request.header.accept-encoding":"gzip, deflate, br, zstd","http.request.header.accept-language":"en-GB","client.address":"127.0.0.1","http.response.status_code":200,"http.response.header.access-control-allow-origin":"*","http.response.header.access-control-allow-methods":"GET, POST, OPTIONS","http.response.header.access-control-allow-headers":"authorization, b3, traceparent, content-type","http.response.header.content-type":"application/json","http.response.header.content-length":"117"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"7c9889b345928ac7404755e421d6f99a","spanId":"81b1f95bd30773ae","parentSpanId":"ffd7c1cd3befdf30","sampled":true,"kind":"client","startTimeUnixNano":"1779351731715825667","endTimeUnixNano":"1779351731715951584","durationMs":0.125917,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n session_id AS \"sessionId\",\n subject AS \"subject\",\n role AS \"role\",\n method AS \"method\",\n client_label AS \"clientLabel\",\n client_ip_address AS \"clientIpAddress\",\n client_user_agent AS \"clientUserAgent\",\n client_device_type AS \"clientDeviceType\",\n client_os AS \"clientOs\",\n client_browser AS \"clientBrowser\",\n issued_at AS \"issuedAt\",\n expires_at AS \"expiresAt\",\n last_connected_at AS \"lastConnectedAt\",\n revoked_at AS \"revokedAt\"\n FROM auth_sessions\n WHERE session_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"http.server GET","traceId":"7c9889b345928ac7404755e421d6f99a","spanId":"ffd7c1cd3befdf30","sampled":true,"kind":"server","startTimeUnixNano":"1779351731715408125","endTimeUnixNano":"1779351731716385625","durationMs":0.9775,"attributes":{"http.route":"/api/auth/session","http.request.method":"GET","url.full":"http://127.0.0.1:14124/api/auth/session","url.path":"/api/auth/session","url.scheme":"http","user_agent.original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"close","http.request.header.sec-ch-ua-platform":"\"macOS\"","http.request.header.user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.sec-ch-ua":"\"Not-A.Brand\";v=\"24\", \"Chromium\";v=\"146\"","http.request.header.sec-ch-ua-mobile":"?0","http.request.header.accept":"*/*","http.request.header.sec-fetch-site":"same-origin","http.request.header.sec-fetch-mode":"cors","http.request.header.sec-fetch-dest":"empty","http.request.header.referer":"http://127.0.0.1:6084/","http.request.header.accept-encoding":"gzip, deflate, br, zstd","http.request.header.accept-language":"en-GB","http.request.header.cookie":"","http.response.status_code":200,"http.response.header.access-control-allow-origin":"*","http.response.header.access-control-allow-methods":"GET, POST, OPTIONS","http.response.header.access-control-allow-headers":"authorization, b3, traceparent, content-type","http.response.header.content-type":"application/json","http.response.header.content-length":"306"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"758b9cecc84bb2da","parentSpanId":"eb7a24ce917240d8","sampled":true,"kind":"client","startTimeUnixNano":"1779351731809847792","endTimeUnixNano":"1779351731810021459","durationMs":0.173667,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n session_id AS \"sessionId\",\n subject AS \"subject\",\n role AS \"role\",\n method AS \"method\",\n client_label AS \"clientLabel\",\n client_ip_address AS \"clientIpAddress\",\n client_user_agent AS \"clientUserAgent\",\n client_device_type AS \"clientDeviceType\",\n client_os AS \"clientOs\",\n client_browser AS \"clientBrowser\",\n issued_at AS \"issuedAt\",\n expires_at AS \"expiresAt\",\n last_connected_at AS \"lastConnectedAt\",\n revoked_at AS \"revokedAt\"\n FROM auth_sessions\n WHERE session_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeProviderMaintenanceCommandCoordinator","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"3a2c1441495de08b","parentSpanId":"232eb0f47a97d3e0","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731812509792","endTimeUnixNano":"1779351731812551667","durationMs":0.041875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProviderMaintenanceRunner.make","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"232eb0f47a97d3e0","parentSpanId":"eb7a24ce917240d8","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731812439709","endTimeUnixNano":"1779351731812569125","durationMs":0.129416,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"4b6fe2f3da9d7555","parentSpanId":"eb7a24ce917240d8","sampled":true,"kind":"client","startTimeUnixNano":"1779351731814329917","endTimeUnixNano":"1779351731814538750","durationMs":0.208833,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n UPDATE auth_sessions\n SET last_connected_at = ?\n WHERE session_id = ?\n AND revoked_at IS NULL\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"d3f966c1be6bbc17","parentSpanId":"eb7a24ce917240d8","sampled":true,"kind":"client","startTimeUnixNano":"1779351731814634834","endTimeUnixNano":"1779351731814673250","durationMs":0.038416,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n session_id AS \"sessionId\",\n subject AS \"subject\",\n role AS \"role\",\n method AS \"method\",\n client_label AS \"clientLabel\",\n client_ip_address AS \"clientIpAddress\",\n client_user_agent AS \"clientUserAgent\",\n client_device_type AS \"clientDeviceType\",\n client_os AS \"clientOs\",\n client_browser AS \"clientBrowser\",\n issued_at AS \"issuedAt\",\n expires_at AS \"expiresAt\",\n last_connected_at AS \"lastConnectedAt\",\n revoked_at AS \"revokedAt\"\n FROM auth_sessions\n WHERE session_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"c510f973efb384d9","parentSpanId":"e7dcab720fdcb3d3","sampled":true,"kind":"client","startTimeUnixNano":"1779351731818529792","endTimeUnixNano":"1779351731818558375","durationMs":0.028583,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n project_id AS \"projectId\",\n title,\n workspace_root AS \"workspaceRoot\",\n default_model_selection_json AS \"defaultModelSelection\",\n scripts_json AS \"scripts\",\n created_at AS \"createdAt\",\n updated_at AS \"updatedAt\",\n deleted_at AS \"deletedAt\"\n FROM projection_projects\n ORDER BY created_at ASC, project_id ASC\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"24c7d4ab0775bf55","parentSpanId":"e7dcab720fdcb3d3","sampled":true,"kind":"client","startTimeUnixNano":"1779351731818589334","endTimeUnixNano":"1779351731818667584","durationMs":0.07825,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n thread_id AS \"threadId\",\n project_id AS \"projectId\",\n title,\n model_selection_json AS \"modelSelection\",\n runtime_mode AS \"runtimeMode\",\n interaction_mode AS \"interactionMode\",\n branch,\n worktree_path AS \"worktreePath\",\n latest_turn_id AS \"latestTurnId\",\n created_at AS \"createdAt\",\n updated_at AS \"updatedAt\",\n archived_at AS \"archivedAt\",\n latest_user_message_at AS \"latestUserMessageAt\",\n pending_approval_count AS \"pendingApprovalCount\",\n pending_user_input_count AS \"pendingUserInputCount\",\n has_actionable_proposed_plan AS \"hasActionableProposedPlan\",\n deleted_at AS \"deletedAt\"\n FROM projection_threads\n WHERE deleted_at IS NULL\n AND archived_at IS NULL\n ORDER BY project_id ASC, created_at ASC, thread_id ASC\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"08eb2c48d741e0b5","parentSpanId":"e7dcab720fdcb3d3","sampled":true,"kind":"client","startTimeUnixNano":"1779351731818686792","endTimeUnixNano":"1779351731818732625","durationMs":0.045833,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n sessions.thread_id AS \"threadId\",\n sessions.status,\n sessions.provider_name AS \"providerName\",\n sessions.provider_instance_id AS \"providerInstanceId\",\n sessions.provider_session_id AS \"providerSessionId\",\n sessions.provider_thread_id AS \"providerThreadId\",\n sessions.runtime_mode AS \"runtimeMode\",\n sessions.active_turn_id AS \"activeTurnId\",\n sessions.last_error AS \"lastError\",\n sessions.updated_at AS \"updatedAt\"\n FROM projection_thread_sessions sessions\n INNER JOIN projection_threads threads\n ON threads.thread_id = sessions.thread_id\n WHERE threads.deleted_at IS NULL\n AND threads.archived_at IS NULL\n ORDER BY sessions.thread_id ASC\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"9fcbece19fc5cba1","parentSpanId":"e7dcab720fdcb3d3","sampled":true,"kind":"client","startTimeUnixNano":"1779351731818746834","endTimeUnixNano":"1779351731818789917","durationMs":0.043083,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n turns.thread_id AS \"threadId\",\n turns.turn_id AS \"turnId\",\n turns.state,\n turns.requested_at AS \"requestedAt\",\n turns.started_at AS \"startedAt\",\n turns.completed_at AS \"completedAt\",\n turns.assistant_message_id AS \"assistantMessageId\",\n turns.source_proposed_plan_thread_id AS \"sourceProposedPlanThreadId\",\n turns.source_proposed_plan_id AS \"sourceProposedPlanId\"\n FROM projection_threads threads\n JOIN projection_turns turns\n ON turns.thread_id = threads.thread_id\n AND turns.turn_id = threads.latest_turn_id\n WHERE threads.deleted_at IS NULL\n AND threads.archived_at IS NULL\n AND threads.latest_turn_id IS NOT NULL\n ORDER BY turns.thread_id ASC\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"efa49a41a4383667","parentSpanId":"e7dcab720fdcb3d3","sampled":true,"kind":"client","startTimeUnixNano":"1779351731818798250","endTimeUnixNano":"1779351731818807125","durationMs":0.008875,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n projector,\n last_applied_sequence AS \"lastAppliedSequence\",\n updated_at AS \"updatedAt\"\n FROM projection_state\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.transaction","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"e7dcab720fdcb3d3","parentSpanId":"a924f711f34aec51","sampled":true,"kind":"client","startTimeUnixNano":"1779351731818477750","endTimeUnixNano":"1779351731818826792","durationMs":0.349042,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite"},"events":[{"name":"db.transaction.commit","timeUnixNano":"1779351731818814375","attributes":{}}],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectionSnapshotQuery.resolveRepositoryIdentitiesForProjects","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"ccdf6118c5348d45","parentSpanId":"a924f711f34aec51","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731818902750","endTimeUnixNano":"1779351731818928959","durationMs":0.026209,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.server.getConfig","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"50aa80f1bc446bba","parentSpanId":"eb7a24ce917240d8","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731820784417","endTimeUnixNano":"1779351731825162459","durationMs":4.378042,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"server.getConfig","rpc.aggregate":"server"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.server.getConfig","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"70b22c1d732ec1a1","parentSpanId":"eb7a24ce917240d8","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731842459542","endTimeUnixNano":"1779351731847486542","durationMs":5.027,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"server.getConfig","rpc.aggregate":"server"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeClaudeEnvironment","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"fc9a160a07b34207","parentSpanId":"7e616c9b61517824","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731852838375","endTimeUnixNano":"1779351731852844750","durationMs":0.006375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"checkCursorProviderStatus","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"9a30d10d14e85078","parentSpanId":"e498e7214f307b05","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731860759459","endTimeUnixNano":"1779351731860798667","durationMs":0.039208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"c38ab817ea3df2a4693c1e2d08def3a6","spanId":"36b6c3cd17f85f42","parentSpanId":"8b0593235134ed8d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731860883459","endTimeUnixNano":"1779351731860890125","durationMs":0.006666,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"c38ab817ea3df2a4693c1e2d08def3a6","spanId":"9584a47571baa722","parentSpanId":"8b0593235134ed8d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731860957167","endTimeUnixNano":"1779351731860965834","durationMs":0.008667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"57cf6df24f7c77dd","parentSpanId":"e498e7214f307b05","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731861016042","endTimeUnixNano":"1779351731861052667","durationMs":0.036625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"e498e7214f307b05","parentSpanId":"9910299d0ea0cba6","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731860745500","endTimeUnixNano":"1779351731861056500","durationMs":0.311,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"9910299d0ea0cba6","parentSpanId":"128841ff70ef526f","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731860723625","endTimeUnixNano":"1779351731861060917","durationMs":0.337292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"b37308ac7c22edf6","parentSpanId":"40c15c07277cb144","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731861093084","endTimeUnixNano":"1779351731861098750","durationMs":0.005666,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"40c15c07277cb144","parentSpanId":"dfa1b02c9ae580d5","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731861079250","endTimeUnixNano":"1779351731861127959","durationMs":0.048709,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"dfa1b02c9ae580d5","parentSpanId":"128841ff70ef526f","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731861070250","endTimeUnixNano":"1779351731861130959","durationMs":0.060709,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshOneSource","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"128841ff70ef526f","parentSpanId":"ae787b2caa0b520b","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731860695709","endTimeUnixNano":"1779351731861133459","durationMs":0.43775,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runClaudeCommand","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"7e616c9b61517824","parentSpanId":"6513f5690da99056","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731852830250","endTimeUnixNano":"1779351731862122625","durationMs":9.292375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"PlatformError: NotFound: ChildProcess.spawn (claude --version)\n at Module.systemError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/PlatformError.js:59:39)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/internal/utils.js:28:24\n at toPlatformError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:25:54)\n at ChildProcess. (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:230:26)\n at ChildProcess.emit (node:events:509:28)\n at ChildProcess._handle.onexit (node:internal/child_process:293:12)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n at runClaudeCommand (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:27894:30)\n at runClaudeCommand (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:27870:33)\n at checkClaudeProviderStatus (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30400:25)\n at checkClaudeProviderStatus (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:27878:42)\n at applySnapshot (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30277:83)\n at applySnapshot (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30257:35)\n at refreshSnapshot (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30287:12)\n at refreshSnapshot (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30278:33)\n at refreshOneSource (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:60480:53)\n at refreshOneSource (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:60475:34) {\n [cause]: Error: spawn claude ENOENT\n at ChildProcess._handle.onexit (node:internal/child_process:287:19)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n}"}} -{"type":"effect-span","name":"checkClaudeProviderStatus","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"6513f5690da99056","parentSpanId":"cfbba8fe86c03c70","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731852811917","endTimeUnixNano":"1779351731862247250","durationMs":9.435333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"c5df783be5294d942b459390f06bd26c","spanId":"6319c7c8af93c179","parentSpanId":"f6ebded4b5a8ba71","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731862302625","endTimeUnixNano":"1779351731862307959","durationMs":0.005334,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"c5df783be5294d942b459390f06bd26c","spanId":"ce6c103646dde400","parentSpanId":"f6ebded4b5a8ba71","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731862341167","endTimeUnixNano":"1779351731862347334","durationMs":0.006167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"9ed4e0293282e619","parentSpanId":"cfbba8fe86c03c70","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731862394167","endTimeUnixNano":"1779351731862415542","durationMs":0.021375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"cfbba8fe86c03c70","parentSpanId":"ec22b9133510b6f0","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731852802709","endTimeUnixNano":"1779351731862419000","durationMs":9.616291,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"ec22b9133510b6f0","parentSpanId":"27d20d9e72ab3f43","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731852792625","endTimeUnixNano":"1779351731862423542","durationMs":9.630917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"6220fbd2cc2e6f85","parentSpanId":"643598c84fed1539","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731863017084","endTimeUnixNano":"1779351731863038209","durationMs":0.021125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"643598c84fed1539","parentSpanId":"fb374df3d7f1d124","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731862977500","endTimeUnixNano":"1779351731863128875","durationMs":0.151375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"fb374df3d7f1d124","parentSpanId":"27d20d9e72ab3f43","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731862931125","endTimeUnixNano":"1779351731863139209","durationMs":0.208084,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshOneSource","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"27d20d9e72ab3f43","parentSpanId":"ae787b2caa0b520b","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731852784167","endTimeUnixNano":"1779351731863150459","durationMs":10.366292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeCodexAppServerPatchedProtocol","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"55a3b0ba17da4260","parentSpanId":"b2f17ab1a6f19f54","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731867372625","endTimeUnixNano":"1779351731867511459","durationMs":0.138834,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"effect-codex-app-server/CodexAppServerClient.make","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"b2f17ab1a6f19f54","parentSpanId":"05fe8ebef9f80a88","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731867343750","endTimeUnixNano":"1779351731867534792","durationMs":0.191042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"3869138202a979ce","parentSpanId":"57cf6df24f7c77dd","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731867877417","endTimeUnixNano":"1779351731867900125","durationMs":0.022708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"4eecab8931ac2b16","parentSpanId":"57cf6df24f7c77dd","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731867920834","endTimeUnixNano":"1779351731867968667","durationMs":0.047833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"e442e2ca01582ca6","parentSpanId":"9ed4e0293282e619","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731867982959","endTimeUnixNano":"1779351731867992750","durationMs":0.009791,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"39598d57cd921512","parentSpanId":"9ed4e0293282e619","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731868001542","endTimeUnixNano":"1779351731868020709","durationMs":0.019167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"c38ab817ea3df2a4693c1e2d08def3a6","spanId":"8b0593235134ed8d","parentSpanId":"b031e0aa2a03e4f8","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731860865000","endTimeUnixNano":"1779351731869292959","durationMs":8.427959,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"c38ab817ea3df2a4693c1e2d08def3a6","spanId":"b031e0aa2a03e4f8","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731860854167","endTimeUnixNano":"1779351731869300917","durationMs":8.44675,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"b08f8d6babea8cf939589f96482eedb0","spanId":"34bdab1b69107f64","parentSpanId":"cd3e1974df0cd039","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731869341792","endTimeUnixNano":"1779351731869348875","durationMs":0.007083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"b08f8d6babea8cf939589f96482eedb0","spanId":"357de87d77257c46","parentSpanId":"cd3e1974df0cd039","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731869384167","endTimeUnixNano":"1779351731869390709","durationMs":0.006542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"c5df783be5294d942b459390f06bd26c","spanId":"f6ebded4b5a8ba71","parentSpanId":"ed73e23045939746","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731862292042","endTimeUnixNano":"1779351731869437292","durationMs":7.14525,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"c5df783be5294d942b459390f06bd26c","spanId":"ed73e23045939746","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731862282334","endTimeUnixNano":"1779351731869441875","durationMs":7.159541,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"68d64e6c744dee89ab48904c133096ba","spanId":"b128b435f1484ade","parentSpanId":"3202ee9735a3d769","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731869464250","endTimeUnixNano":"1779351731869468792","durationMs":0.004542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"68d64e6c744dee89ab48904c133096ba","spanId":"d1d8980bb522be3e","parentSpanId":"3202ee9735a3d769","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731869488750","endTimeUnixNano":"1779351731869493084","durationMs":0.004334,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"68d64e6c744dee89ab48904c133096ba","spanId":"3202ee9735a3d769","parentSpanId":"d4afaeeb5bfc1996","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731869456917","endTimeUnixNano":"1779351731870864334","durationMs":1.407417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"68d64e6c744dee89ab48904c133096ba","spanId":"d4afaeeb5bfc1996","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731869450417","endTimeUnixNano":"1779351731870869209","durationMs":1.418792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"b08f8d6babea8cf939589f96482eedb0","spanId":"cd3e1974df0cd039","parentSpanId":"949f0a6353c36b70","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731869329084","endTimeUnixNano":"1779351731870944750","durationMs":1.615666,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"b08f8d6babea8cf939589f96482eedb0","spanId":"949f0a6353c36b70","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731869319000","endTimeUnixNano":"1779351731870954625","durationMs":1.635625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"requestAllCodexModels","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"39c5be2b62418abb","parentSpanId":"05fe8ebef9f80a88","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731895823334","endTimeUnixNano":"1779351731896849125","durationMs":1.025791,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"probeCodexAppServerProvider","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"05fe8ebef9f80a88","parentSpanId":"38b8502e10d63dcd","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731852646209","endTimeUnixNano":"1779351731943279334","durationMs":90.633125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"checkCodexProviderStatus","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"38b8502e10d63dcd","parentSpanId":"40232390b9caff06","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731852603292","endTimeUnixNano":"1779351731947014084","durationMs":94.410792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"02cd461778dec86f98a1bd664f7924d7","spanId":"3cafee49fec4cac9","parentSpanId":"16059cac66f01dff","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731947203000","endTimeUnixNano":"1779351731947215167","durationMs":0.012167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"02cd461778dec86f98a1bd664f7924d7","spanId":"35992c20e5c53c1d","parentSpanId":"16059cac66f01dff","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731947358000","endTimeUnixNano":"1779351731947369667","durationMs":0.011667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"1426aff7c68f5e3b","parentSpanId":"40232390b9caff06","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731947556875","endTimeUnixNano":"1779351731947608334","durationMs":0.051459,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"40232390b9caff06","parentSpanId":"3e34506c479bdd03","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731852593084","endTimeUnixNano":"1779351731947616917","durationMs":95.023833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"3e34506c479bdd03","parentSpanId":"708cc9ee7895a1e1","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731852576917","endTimeUnixNano":"1779351731947623709","durationMs":95.046792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"3d069729891644ff","parentSpanId":"4ac58ffcfa6c1899","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731947661584","endTimeUnixNano":"1779351731947668542","durationMs":0.006958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"4ac58ffcfa6c1899","parentSpanId":"15a86c901bd14f78","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731947649000","endTimeUnixNano":"1779351731947705959","durationMs":0.056959,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"15a86c901bd14f78","parentSpanId":"708cc9ee7895a1e1","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731947637959","endTimeUnixNano":"1779351731947861834","durationMs":0.223875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshOneSource","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"708cc9ee7895a1e1","parentSpanId":"ae787b2caa0b520b","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731852566709","endTimeUnixNano":"1779351731947868125","durationMs":95.301416,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveLatestProviderVersion","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"5dab2c81bbac3006","parentSpanId":"a6dde4585c8e11cc","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731947928084","endTimeUnixNano":"1779351731947945834","durationMs":0.01775,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"a6dde4585c8e11cc","parentSpanId":"1426aff7c68f5e3b","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731947910167","endTimeUnixNano":"1779351731947989875","durationMs":0.079708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"33b0a39ad5d87964","parentSpanId":"1426aff7c68f5e3b","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731948004167","endTimeUnixNano":"1779351731948033292","durationMs":0.029125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"02cd461778dec86f98a1bd664f7924d7","spanId":"16059cac66f01dff","parentSpanId":"3cfebd2938404e54","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731947181125","endTimeUnixNano":"1779351731949008917","durationMs":1.827792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"02cd461778dec86f98a1bd664f7924d7","spanId":"3cfebd2938404e54","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731947138417","endTimeUnixNano":"1779351731949036750","durationMs":1.898333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"7552704d87507298099e577339efc530","spanId":"99209693372300ce","parentSpanId":"705d9a4de5ce8d88","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731949220959","endTimeUnixNano":"1779351731949233000","durationMs":0.012041,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"7552704d87507298099e577339efc530","spanId":"d50493186304b133","parentSpanId":"705d9a4de5ce8d88","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731949285334","endTimeUnixNano":"1779351731949293375","durationMs":0.008041,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"7552704d87507298099e577339efc530","spanId":"705d9a4de5ce8d88","parentSpanId":"6fa0f7247d75ba2a","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731949139917","endTimeUnixNano":"1779351731959879625","durationMs":10.739708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"7552704d87507298099e577339efc530","spanId":"6fa0f7247d75ba2a","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731949087459","endTimeUnixNano":"1779351731959896292","durationMs":10.808833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"opencode.app.agents","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"ad233947c62f9c6e","parentSpanId":"4d993f7fe87d6bec","sampled":true,"kind":"internal","startTimeUnixNano":"1779351732728156709","endTimeUnixNano":"1779351732954183375","durationMs":226.026666,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"opencode.provider.list","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"225d655470211359","parentSpanId":"4d993f7fe87d6bec","sampled":true,"kind":"internal","startTimeUnixNano":"1779351732728056334","endTimeUnixNano":"1779351733079154667","durationMs":351.098333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"checkOpenCodeProviderStatus","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"4d993f7fe87d6bec","parentSpanId":"c3aa34797b09d177","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731861172375","endTimeUnixNano":"1779351734082497625","durationMs":2221.32525,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"19149422b27dd679738e93973b791543","spanId":"d2de139e8772e1b7","parentSpanId":"62765d7a46daabcd","sampled":true,"kind":"internal","startTimeUnixNano":"1779351734083012625","endTimeUnixNano":"1779351734083051959","durationMs":0.039334,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"19149422b27dd679738e93973b791543","spanId":"297b8da058172f6f","parentSpanId":"62765d7a46daabcd","sampled":true,"kind":"internal","startTimeUnixNano":"1779351734085093042","endTimeUnixNano":"1779351734085133834","durationMs":0.040792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"fb48796f3b1c2400","parentSpanId":"c3aa34797b09d177","sampled":true,"kind":"internal","startTimeUnixNano":"1779351734085767792","endTimeUnixNano":"1779351734085898584","durationMs":0.130792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"c3aa34797b09d177","parentSpanId":"2a1bde10b16abd3f","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731861163209","endTimeUnixNano":"1779351734085917000","durationMs":2224.753791,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"2a1bde10b16abd3f","parentSpanId":"6b35f933b82e87e9","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731861150584","endTimeUnixNano":"1779351734085938542","durationMs":2224.787958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"468a88989be2a07d","parentSpanId":"9b9c454fd483c3c9","sampled":true,"kind":"internal","startTimeUnixNano":"1779351734086038084","endTimeUnixNano":"1779351734086056459","durationMs":0.018375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"9b9c454fd483c3c9","parentSpanId":"3f5ca2bf2d2fa803","sampled":true,"kind":"internal","startTimeUnixNano":"1779351734086001250","endTimeUnixNano":"1779351734086210875","durationMs":0.209625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"3f5ca2bf2d2fa803","parentSpanId":"6b35f933b82e87e9","sampled":true,"kind":"internal","startTimeUnixNano":"1779351734085971792","endTimeUnixNano":"1779351734086222750","durationMs":0.250958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshOneSource","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"6b35f933b82e87e9","parentSpanId":"ae787b2caa0b520b","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731861141584","endTimeUnixNano":"1779351734086235584","durationMs":2225.094,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshAll","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"ae787b2caa0b520b","parentSpanId":"7fcc2f50b853bc70","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731852366417","endTimeUnixNano":"1779351734086261917","durationMs":2233.8955,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refresh","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"7fcc2f50b853bc70","parentSpanId":"d3454221c9fe9083","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731852314250","endTimeUnixNano":"1779351734086274917","durationMs":2233.960667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveLatestProviderVersion","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"e68f3fa12b1c5e4f","parentSpanId":"8fbb8e081325a9b8","sampled":true,"kind":"internal","startTimeUnixNano":"1779351734086396917","endTimeUnixNano":"1779351734086445750","durationMs":0.048833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"8fbb8e081325a9b8","parentSpanId":"fb48796f3b1c2400","sampled":true,"kind":"internal","startTimeUnixNano":"1779351734086360959","endTimeUnixNano":"1779351734086600125","durationMs":0.239166,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"25d67758ffb6c4d7","parentSpanId":"fb48796f3b1c2400","sampled":true,"kind":"internal","startTimeUnixNano":"1779351734086629084","endTimeUnixNano":"1779351734086698542","durationMs":0.069458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"19149422b27dd679738e93973b791543","spanId":"62765d7a46daabcd","parentSpanId":"64799adadec86bb1","sampled":true,"kind":"internal","startTimeUnixNano":"1779351734082893959","endTimeUnixNano":"1779351734088840459","durationMs":5.9465,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"19149422b27dd679738e93973b791543","spanId":"64799adadec86bb1","sampled":true,"kind":"internal","startTimeUnixNano":"1779351734082800334","endTimeUnixNano":"1779351734088886292","durationMs":6.085958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"290876304e024c8b2f088a69bba22895","spanId":"a752ea4bf1f3bbd9","parentSpanId":"ffd6a00bd7574547","sampled":true,"kind":"internal","startTimeUnixNano":"1779351734089014000","endTimeUnixNano":"1779351734089031167","durationMs":0.017167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"290876304e024c8b2f088a69bba22895","spanId":"2aa4098e33036ca1","parentSpanId":"ffd6a00bd7574547","sampled":true,"kind":"internal","startTimeUnixNano":"1779351734089327000","endTimeUnixNano":"1779351734089367875","durationMs":0.040875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"290876304e024c8b2f088a69bba22895","spanId":"ffd6a00bd7574547","parentSpanId":"e6be17e9302210dc","sampled":true,"kind":"internal","startTimeUnixNano":"1779351734088981292","endTimeUnixNano":"1779351734092120000","durationMs":3.138708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"290876304e024c8b2f088a69bba22895","spanId":"e6be17e9302210dc","sampled":true,"kind":"internal","startTimeUnixNano":"1779351734088950292","endTimeUnixNano":"1779351734092151667","durationMs":3.201375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"0d5e8a2777f4a851","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351735292898834","endTimeUnixNano":"1779351735351556292","durationMs":58.657458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"cd8d5797ec1c3b9e","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351740353265334","endTimeUnixNano":"1779351740378776959","durationMs":25.511625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"9167cd9460a28716","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351745379446750","endTimeUnixNano":"1779351745442925500","durationMs":63.47875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"9dfd8e73ed6bc46e","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351750445523542","endTimeUnixNano":"1779351750505629542","durationMs":60.106,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"057b279440ce3c12","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351755506691792","endTimeUnixNano":"1779351755565715959","durationMs":59.024167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"aa17dc38721d8579","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351760565743209","endTimeUnixNano":"1779351760623957209","durationMs":58.214,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"4110b4adb803152f","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351765626831834","endTimeUnixNano":"1779351765687055709","durationMs":60.223875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"1a2c6590631f7eab","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351770688759709","endTimeUnixNano":"1779351770746738292","durationMs":57.978583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"f890d4e6cf0fd8ba","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351775747905084","endTimeUnixNano":"1779351775804397792","durationMs":56.492708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"afee131f8ce0ec4d","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351780806083667","endTimeUnixNano":"1779351780864182334","durationMs":58.098667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"b103f4b3e054d1fa","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351785866440542","endTimeUnixNano":"1779351785926898959","durationMs":60.458417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"7116192c89d16ef7","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351790928933584","endTimeUnixNano":"1779351790990119834","durationMs":61.18625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"3e7be3b1b6b63266","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351795991582917","endTimeUnixNano":"1779351796048789750","durationMs":57.206833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"65dac8edbf2e1478","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351801050442750","endTimeUnixNano":"1779351801108140750","durationMs":57.698,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"e1e08d62c12e2137","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351806110087000","endTimeUnixNano":"1779351806167879084","durationMs":57.792084,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"50be07bf148ff5f5","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351811169067084","endTimeUnixNano":"1779351811199421542","durationMs":30.354458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"14aad89c4a36f130","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351816200666000","endTimeUnixNano":"1779351816257684792","durationMs":57.018792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"a41a868ef675589a","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351821258924292","endTimeUnixNano":"1779351821320613542","durationMs":61.68925,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"b21d20f9adf93066","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351826321831917","endTimeUnixNano":"1779351826382033917","durationMs":60.202,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"9d0f70d2dbb1db43","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351831384161042","endTimeUnixNano":"1779351831442863625","durationMs":58.702583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"876b8f5491abd212","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351836444254292","endTimeUnixNano":"1779351836502298542","durationMs":58.04425,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"a2320d236fa06662","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351841504680125","endTimeUnixNano":"1779351841558442750","durationMs":53.762625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"8f823abf697b7589","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351846559543625","endTimeUnixNano":"1779351846616580625","durationMs":57.037,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"979d3de195aff174","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351851618409584","endTimeUnixNano":"1779351851675503792","durationMs":57.094208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"09682663068958f9","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351856677479167","endTimeUnixNano":"1779351856734692459","durationMs":57.213292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"f278e4eb35c5a2d8","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351861736103209","endTimeUnixNano":"1779351861795553959","durationMs":59.45075,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"dac658a0c6bfd8e0","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351866797717709","endTimeUnixNano":"1779351866855196584","durationMs":57.478875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"c9e85bc68fbd3cdc","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351871857671084","endTimeUnixNano":"1779351871916204542","durationMs":58.533458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"4610568749813a5d","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351876917475792","endTimeUnixNano":"1779351876972820875","durationMs":55.345083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"805e37aafcea2604","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351881974733667","endTimeUnixNano":"1779351882046944875","durationMs":72.211208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"42af05d9484daef2","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351887048243667","endTimeUnixNano":"1779351887099070834","durationMs":50.827167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"6477df3a28ff608f","parentSpanId":"80c5b176bd5448ee","sampled":true,"kind":"internal","startTimeUnixNano":"1779351890454512375","endTimeUnixNano":"1779351890457498417","durationMs":2.986042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"ProcessSpawnError: \n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14166:38\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/effect.js:1309:96\n at ~effect/Utils/internal (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Utils.js:69:12)\n at processRunner.runProcessCore (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14219:44)\n at processRunner.runProcessCore (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14155:31)\n at VcsProcess.run (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:24401:18)\n at VcsProcess.run (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19834:21)\n at ws.rpc.server.discoverSourceControl (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:17831:111) {\n [cause]: PlatformError: NotFound: ChildProcess.spawn (jj --version)\n at Module.systemError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/PlatformError.js:59:39)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/internal/utils.js:28:24\n at toPlatformError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:25:54)\n at ChildProcess. (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:230:26)\n at ChildProcess.emit (node:events:509:28)\n at ChildProcess._handle.onexit (node:internal/child_process:293:12)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {\n [cause]: Error: spawn jj ENOENT\n at ChildProcess._handle.onexit (node:internal/child_process:287:19)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n }\n}"}} -{"type":"effect-span","name":"VcsProcess.run","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"80c5b176bd5448ee","parentSpanId":"cf93101a5668c38a","sampled":true,"kind":"internal","startTimeUnixNano":"1779351890454486250","endTimeUnixNano":"1779351890458103209","durationMs":3.616959,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"VcsProcessSpawnError: VCS process failed to spawn in source-control.discovery.probe: jj --version (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69)\n at VcsProcessSpawnError.fromProcessSpawnError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:3950:10)\n at Object.ProcessSpawnError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19854:55)\n at Object.evaluate (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:170:101)\n at i (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:236:37)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:281:20\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:133:10\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Function.js:97:18\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/effect.js:1309:96\n at ~effect/Utils/internal (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Utils.js:69:12)\n at VcsProcess.run (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:24401:18)\n at VcsProcess.run (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19834:21)\n at ws.rpc.server.discoverSourceControl (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:17831:111) {\n [cause]: PlatformError: NotFound: ChildProcess.spawn (jj --version)\n at Module.systemError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/PlatformError.js:59:39)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/internal/utils.js:28:24\n at toPlatformError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:25:54)\n at ChildProcess. (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:230:26)\n at ChildProcess.emit (node:events:509:28)\n at ChildProcess._handle.onexit (node:internal/child_process:293:12)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {\n [cause]: Error: spawn jj ENOENT\n at ChildProcess._handle.onexit (node:internal/child_process:287:19)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n }\n}"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"e9c3b361209be09e","parentSpanId":"f96f2265c955e48e","sampled":true,"kind":"internal","startTimeUnixNano":"1779351890455389375","endTimeUnixNano":"1779351890462404417","durationMs":7.015042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"2c8367c3ec3518dc","parentSpanId":"f96f2265c955e48e","sampled":true,"kind":"internal","startTimeUnixNano":"1779351890455344417","endTimeUnixNano":"1779351890462462834","durationMs":7.118417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"f96f2265c955e48e","parentSpanId":"bbcba247f40b2de7","sampled":true,"kind":"internal","startTimeUnixNano":"1779351890454434667","endTimeUnixNano":"1779351890462497042","durationMs":8.062375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProcess.run","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"bbcba247f40b2de7","parentSpanId":"cf93101a5668c38a","sampled":true,"kind":"internal","startTimeUnixNano":"1779351890454278167","endTimeUnixNano":"1779351890462547459","durationMs":8.269292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"5a8bd1587229b34d","parentSpanId":"fdda13ac5b34ea68","sampled":true,"kind":"internal","startTimeUnixNano":"1779351890462747125","endTimeUnixNano":"1779351890477189834","durationMs":14.442709,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"ProcessSpawnError: \n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14166:38\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/effect.js:1309:96\n at ~effect/Utils/internal (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Utils.js:69:12)\n at processRunner.runProcessCore (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14219:44)\n at processRunner.runProcessCore (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14155:31)\n at VcsProcess.run (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:20703:23)\n at VcsProcess.run (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19834:21)\n at ws.rpc.server.discoverSourceControl (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:17831:111) {\n [cause]: PlatformError: NotFound: ChildProcess.spawn (glab --version)\n at Module.systemError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/PlatformError.js:59:39)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/internal/utils.js:28:24\n at toPlatformError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:25:54)\n at ChildProcess. (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:230:26)\n at ChildProcess.emit (node:events:509:28)\n at ChildProcess._handle.onexit (node:internal/child_process:293:12)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {\n [cause]: Error: spawn glab ENOENT\n at ChildProcess._handle.onexit (node:internal/child_process:287:19)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n }\n}"}} -{"type":"effect-span","name":"VcsProcess.run","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"fdda13ac5b34ea68","parentSpanId":"cf93101a5668c38a","sampled":true,"kind":"internal","startTimeUnixNano":"1779351890462725542","endTimeUnixNano":"1779351890477395834","durationMs":14.670292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"VcsProcessSpawnError: VCS process failed to spawn in source-control.discovery.probe: glab --version (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69)\n at VcsProcessSpawnError.fromProcessSpawnError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:3950:10)\n at Object.ProcessSpawnError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19854:55)\n at Object.evaluate (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:170:101)\n at i (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:236:37)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:281:20\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:133:10\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Function.js:97:18\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/effect.js:1309:96\n at ~effect/Utils/internal (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Utils.js:69:12)\n at VcsProcess.run (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:20703:23)\n at VcsProcess.run (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19834:21)\n at ws.rpc.server.discoverSourceControl (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:17831:111) {\n [cause]: PlatformError: NotFound: ChildProcess.spawn (glab --version)\n at Module.systemError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/PlatformError.js:59:39)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/internal/utils.js:28:24\n at toPlatformError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:25:54)\n at ChildProcess. (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:230:26)\n at ChildProcess.emit (node:events:509:28)\n at ChildProcess._handle.onexit (node:internal/child_process:293:12)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {\n [cause]: Error: spawn glab ENOENT\n at ChildProcess._handle.onexit (node:internal/child_process:287:19)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n }\n}"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"b0b0de2c4436829c","parentSpanId":"4cf332b0de427c9f","sampled":true,"kind":"internal","startTimeUnixNano":"1779351890462784375","endTimeUnixNano":"1779351890479643584","durationMs":16.859209,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"ProcessSpawnError: \n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14166:38\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/effect.js:1309:96\n at ~effect/Utils/internal (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Utils.js:69:12)\n at processRunner.runProcessCore (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14219:44)\n at processRunner.runProcessCore (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14155:31)\n at VcsProcess.run (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:20703:23)\n at VcsProcess.run (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19834:21)\n at ws.rpc.server.discoverSourceControl (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:17831:111) {\n [cause]: PlatformError: NotFound: ChildProcess.spawn (az --version)\n at Module.systemError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/PlatformError.js:59:39)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/internal/utils.js:28:24\n at toPlatformError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:25:54)\n at ChildProcess. (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:230:26)\n at ChildProcess.emit (node:events:509:28)\n at ChildProcess._handle.onexit (node:internal/child_process:293:12)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {\n [cause]: Error: spawn az ENOENT\n at ChildProcess._handle.onexit (node:internal/child_process:287:19)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n }\n}"}} -{"type":"effect-span","name":"VcsProcess.run","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"4cf332b0de427c9f","parentSpanId":"cf93101a5668c38a","sampled":true,"kind":"internal","startTimeUnixNano":"1779351890462763542","endTimeUnixNano":"1779351890479884459","durationMs":17.120917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"VcsProcessSpawnError: VCS process failed to spawn in source-control.discovery.probe: az --version (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69)\n at VcsProcessSpawnError.fromProcessSpawnError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:3950:10)\n at Object.ProcessSpawnError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19854:55)\n at Object.evaluate (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:170:101)\n at i (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:236:37)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:281:20\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:133:10\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Function.js:97:18\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/effect.js:1309:96\n at ~effect/Utils/internal (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Utils.js:69:12)\n at VcsProcess.run (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:20703:23)\n at VcsProcess.run (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19834:21)\n at ws.rpc.server.discoverSourceControl (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:17831:111) {\n [cause]: PlatformError: NotFound: ChildProcess.spawn (az --version)\n at Module.systemError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/PlatformError.js:59:39)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/internal/utils.js:28:24\n at toPlatformError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:25:54)\n at ChildProcess. (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:230:26)\n at ChildProcess.emit (node:events:509:28)\n at ChildProcess._handle.onexit (node:internal/child_process:293:12)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {\n [cause]: Error: spawn az ENOENT\n at ChildProcess._handle.onexit (node:internal/child_process:287:19)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n }\n}"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"599ffdbbf89e749b","parentSpanId":"f715fade2b2218da","sampled":true,"kind":"internal","startTimeUnixNano":"1779351890465003209","endTimeUnixNano":"1779351890498148417","durationMs":33.145208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"a141e6b1464b8218","parentSpanId":"f715fade2b2218da","sampled":true,"kind":"internal","startTimeUnixNano":"1779351890464855250","endTimeUnixNano":"1779351890498200000","durationMs":33.34475,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"f715fade2b2218da","parentSpanId":"924325ee9ce6ae10","sampled":true,"kind":"internal","startTimeUnixNano":"1779351890462685709","endTimeUnixNano":"1779351890498237209","durationMs":35.5515,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProcess.run","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"924325ee9ce6ae10","parentSpanId":"cf93101a5668c38a","sampled":true,"kind":"internal","startTimeUnixNano":"1779351890462645917","endTimeUnixNano":"1779351890498283167","durationMs":35.63725,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"http.client GET","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"693c7200b7601bd3","parentSpanId":"cf93101a5668c38a","sampled":true,"kind":"client","startTimeUnixNano":"1779351890462836792","endTimeUnixNano":"1779351890845116084","durationMs":382.279292,"attributes":{"http.request.method":"GET","server.address":"https://api.bitbucket.org","url.full":"https://api.bitbucket.org/2.0/user","url.path":"/2.0/user","url.scheme":"https","http.request.header.accept":"application/json","http.response.status_code":401,"http.response.header.age":"0","http.response.header.atl-request-id":"f6a0ef41-05ee-434b-88ee-9a80dee02e3f","http.response.header.atl-traceid":"f6a0ef4105ee434b88ee9a80dee02e3f","http.response.header.content-length":"0","http.response.header.content-type":"text/html; charset=utf-8","http.response.header.date":"Thu, 21 May 2026 08:24:50 GMT","http.response.header.nel":"{\"failure_fraction\": 0.01, \"include_subdomains\": true, \"max_age\": 600, \"report_to\": \"endpoint-1\"}","http.response.header.report-to":"{\"endpoints\": [{\"url\": \"https://dz8aopenkvv6s.cloudfront.net\"}], \"group\": \"endpoint-1\", \"include_subdomains\": true, \"max_age\": 600}","http.response.header.server":"AtlassianEdge","http.response.header.server-timing":"atl-edge;dur=250,atl-edge-internal;dur=9,atl-edge-upstream;dur=242,atl-edge-pop;desc=\"aws-ap-southeast-2\"","http.response.header.strict-transport-security":"max-age=63072000; includeSubDomains; preload","http.response.header.vary":"Authorization, origin","http.response.header.www-authenticate":"BitbucketCustom realm=Bitbucket.org HTTP","http.response.header.x-accepted-oauth-scopes":"account","http.response.header.x-asap-succeeded":"True","http.response.header.x-b3-spanid":"3f2de2e03677a06e","http.response.header.x-b3-traceid":"f6a0ef4105ee434b88ee9a80dee02e3f","http.response.header.x-cache":"MISS","http.response.header.x-content-type-options":"nosniff","http.response.header.x-credential-type":"unauthenticated_identity","http.response.header.x-dc-location":"Micros-3","http.response.header.x-envoy-attempt-count":"1","http.response.header.x-frame-options":"SAMEORIGIN","http.response.header.x-ratelimit-limit":"60, 60;w=3600","http.response.header.x-ratelimit-remaining":"59","http.response.header.x-ratelimit-reset":"2110","http.response.header.x-render-time":"0.022046804428100586","http.response.header.x-request-count":"2706","http.response.header.x-served-by":"ffc8ae780a54","http.response.header.x-static-version":"51d05f3ab3e8","http.response.header.x-usage-input-ops":"0","http.response.header.x-usage-output-ops":"0","http.response.header.x-usage-system-time":"0.000000","http.response.header.x-usage-user-time":"0.020908","http.response.header.x-used-mesh":"False","http.response.header.x-version":"51d05f3ab3e8","http.response.header.x-view-name":"bitbucket.apps.bb.api.v20.handlers.CurrentUserHandler","http.response.header.x-xss-protection":"1; mode=block"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"bb0ea77e4f168425","parentSpanId":"c1d9c475399f5fee","sampled":true,"kind":"internal","startTimeUnixNano":"1779351890499130084","endTimeUnixNano":"1779351890920545042","durationMs":421.414958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"d7a7d718802e3975","parentSpanId":"c1d9c475399f5fee","sampled":true,"kind":"internal","startTimeUnixNano":"1779351890499093417","endTimeUnixNano":"1779351890920601209","durationMs":421.507792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"c1d9c475399f5fee","parentSpanId":"6f4ffbbf4d81bdb4","sampled":true,"kind":"internal","startTimeUnixNano":"1779351890498427959","endTimeUnixNano":"1779351890920639125","durationMs":422.211166,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProcess.run","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"6f4ffbbf4d81bdb4","parentSpanId":"cf93101a5668c38a","sampled":true,"kind":"internal","startTimeUnixNano":"1779351890498385584","endTimeUnixNano":"1779351890920698750","durationMs":422.313166,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.server.discoverSourceControl","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"cf93101a5668c38a","parentSpanId":"eb7a24ce917240d8","sampled":true,"kind":"internal","startTimeUnixNano":"1779351890454138375","endTimeUnixNano":"1779351890921179875","durationMs":467.0415,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"server.discoverSourceControl","rpc.aggregate":"server"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"61e4535babf465541b5dd0d9178167b8","spanId":"71f0f6e610aab5d7","parentSpanId":"1379ac4a1e7e66f8","sampled":true,"kind":"client","startTimeUnixNano":"1779351891770721209","endTimeUnixNano":"1779351891770989834","durationMs":0.268625,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n session_id AS \"sessionId\",\n subject AS \"subject\",\n role AS \"role\",\n method AS \"method\",\n client_label AS \"clientLabel\",\n client_ip_address AS \"clientIpAddress\",\n client_user_agent AS \"clientUserAgent\",\n client_device_type AS \"clientDeviceType\",\n client_os AS \"clientOs\",\n client_browser AS \"clientBrowser\",\n issued_at AS \"issuedAt\",\n expires_at AS \"expiresAt\",\n last_connected_at AS \"lastConnectedAt\",\n revoked_at AS \"revokedAt\"\n FROM auth_sessions\n WHERE session_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"otlp-span","name":"RpcClient.server.discoverSourceControl","traceId":"aea53a3975b11e1764fceb32c1bfb8bb","spanId":"b2509c63b1f3453f","sampled":true,"kind":"internal","startTimeUnixNano":"1779351890452700000","endTimeUnixNano":"1779351890922800000","durationMs":470.1,"attributes":{},"resourceAttributes":{"service.runtime":"t3-web","service.mode":"electron","service.name":"t3-web","service.version":"0.0.24"},"scope":{"name":"t3-web","attributes":{}},"events":[],"links":[],"status":{"code":"1"}} -{"type":"effect-span","name":"http.server POST","traceId":"61e4535babf465541b5dd0d9178167b8","spanId":"1379ac4a1e7e66f8","sampled":true,"kind":"server","startTimeUnixNano":"1779351891769744709","endTimeUnixNano":"1779351891772761792","durationMs":3.017083,"attributes":{"http.route":"/api/observability/v1/traces","http.request.method":"POST","url.full":"http://127.0.0.1:14124/api/observability/v1/traces","url.path":"/api/observability/v1/traces","url.scheme":"http","user_agent.original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"close","http.request.header.content-length":"706","http.request.header.sec-ch-ua-platform":"\"macOS\"","http.request.header.user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.sec-ch-ua":"\"Not-A.Brand\";v=\"24\", \"Chromium\";v=\"146\"","http.request.header.content-type":"application/json","http.request.header.sec-ch-ua-mobile":"?0","http.request.header.accept":"*/*","http.request.header.origin":"http://127.0.0.1:6084","http.request.header.sec-fetch-site":"same-origin","http.request.header.sec-fetch-mode":"cors","http.request.header.sec-fetch-dest":"empty","http.request.header.referer":"http://127.0.0.1:6084/","http.request.header.accept-encoding":"gzip, deflate, br, zstd","http.request.header.accept-language":"en-GB","http.request.header.cookie":"","http.response.status_code":204},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"ed33492190d9d7ff","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351892100993542","endTimeUnixNano":"1779351892159159334","durationMs":58.165792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"WorkspaceEntries.browse","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"e2a244f0e4cc8949","parentSpanId":"6337e8046fe0d826","sampled":true,"kind":"internal","startTimeUnixNano":"1779351892563956459","endTimeUnixNano":"1779351892564953500","durationMs":0.997041,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.filesystem.browse","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"6337e8046fe0d826","parentSpanId":"eb7a24ce917240d8","sampled":true,"kind":"internal","startTimeUnixNano":"1779351892563909500","endTimeUnixNano":"1779351892565080250","durationMs":1.17075,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"filesystem.browse","rpc.aggregate":"workspace"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"a7d44933b9b7884bf334c395158cee5e","spanId":"46a669ffc01c3a53","parentSpanId":"253ebb319f37fc3f","sampled":true,"kind":"client","startTimeUnixNano":"1779351892782455375","endTimeUnixNano":"1779351892782626375","durationMs":0.171,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n session_id AS \"sessionId\",\n subject AS \"subject\",\n role AS \"role\",\n method AS \"method\",\n client_label AS \"clientLabel\",\n client_ip_address AS \"clientIpAddress\",\n client_user_agent AS \"clientUserAgent\",\n client_device_type AS \"clientDeviceType\",\n client_os AS \"clientOs\",\n client_browser AS \"clientBrowser\",\n issued_at AS \"issuedAt\",\n expires_at AS \"expiresAt\",\n last_connected_at AS \"lastConnectedAt\",\n revoked_at AS \"revokedAt\"\n FROM auth_sessions\n WHERE session_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"otlp-span","name":"RpcClient.filesystem.browse","traceId":"f50810fbcc6d5269c2f5b425d36bcd2c","spanId":"51a951186125c32f","sampled":true,"kind":"internal","startTimeUnixNano":"1779351892563000000","endTimeUnixNano":"1779351892579000000","durationMs":16,"attributes":{},"resourceAttributes":{"service.runtime":"t3-web","service.mode":"electron","service.name":"t3-web","service.version":"0.0.24"},"scope":{"name":"t3-web","attributes":{}},"events":[],"links":[],"status":{"code":"1"}} -{"type":"effect-span","name":"http.server POST","traceId":"a7d44933b9b7884bf334c395158cee5e","spanId":"253ebb319f37fc3f","sampled":true,"kind":"server","startTimeUnixNano":"1779351892781936125","endTimeUnixNano":"1779351892783381834","durationMs":1.445709,"attributes":{"http.route":"/api/observability/v1/traces","http.request.method":"POST","url.full":"http://127.0.0.1:14124/api/observability/v1/traces","url.path":"/api/observability/v1/traces","url.scheme":"http","user_agent.original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"close","http.request.header.content-length":"695","http.request.header.sec-ch-ua-platform":"\"macOS\"","http.request.header.user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.sec-ch-ua":"\"Not-A.Brand\";v=\"24\", \"Chromium\";v=\"146\"","http.request.header.content-type":"application/json","http.request.header.sec-ch-ua-mobile":"?0","http.request.header.accept":"*/*","http.request.header.origin":"http://127.0.0.1:6084","http.request.header.sec-fetch-site":"same-origin","http.request.header.sec-fetch-mode":"cors","http.request.header.sec-fetch-dest":"empty","http.request.header.referer":"http://127.0.0.1:6084/","http.request.header.accept-encoding":"gzip, deflate, br, zstd","http.request.header.accept-language":"en-GB","http.request.header.cookie":"","http.response.status_code":204},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"WorkspaceEntries.browse","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"67d1363f69d686bb","parentSpanId":"f12b28d1f6e58a85","sampled":true,"kind":"internal","startTimeUnixNano":"1779351893133135292","endTimeUnixNano":"1779351893133438709","durationMs":0.303417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.filesystem.browse","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"f12b28d1f6e58a85","parentSpanId":"eb7a24ce917240d8","sampled":true,"kind":"internal","startTimeUnixNano":"1779351893133090750","endTimeUnixNano":"1779351893133562459","durationMs":0.471709,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"filesystem.browse","rpc.aggregate":"workspace"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"WorkspaceEntries.browse","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"b0087eabc5d21a96","parentSpanId":"fbe59be7d04e35bd","sampled":true,"kind":"internal","startTimeUnixNano":"1779351893265720500","endTimeUnixNano":"1779351893307855834","durationMs":42.135334,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.filesystem.browse","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"fbe59be7d04e35bd","parentSpanId":"eb7a24ce917240d8","sampled":true,"kind":"internal","startTimeUnixNano":"1779351893265583250","endTimeUnixNano":"1779351893307981125","durationMs":42.397875,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"filesystem.browse","rpc.aggregate":"workspace"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"WorkspaceEntries.browse","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"ef689600d7922212","parentSpanId":"4949a381187a853a","sampled":true,"kind":"internal","startTimeUnixNano":"1779351893649077584","endTimeUnixNano":"1779351893661763084","durationMs":12.6855,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.filesystem.browse","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"4949a381187a853a","parentSpanId":"eb7a24ce917240d8","sampled":true,"kind":"internal","startTimeUnixNano":"1779351893649016959","endTimeUnixNano":"1779351893661987167","durationMs":12.970208,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"filesystem.browse","rpc.aggregate":"workspace"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"60a98f924bb80d5d959b791255612e89","spanId":"472967046860e23e","parentSpanId":"739bfc9cb495cf1b","sampled":true,"kind":"client","startTimeUnixNano":"1779351893789758792","endTimeUnixNano":"1779351893789871125","durationMs":0.112333,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n session_id AS \"sessionId\",\n subject AS \"subject\",\n role AS \"role\",\n method AS \"method\",\n client_label AS \"clientLabel\",\n client_ip_address AS \"clientIpAddress\",\n client_user_agent AS \"clientUserAgent\",\n client_device_type AS \"clientDeviceType\",\n client_os AS \"clientOs\",\n client_browser AS \"clientBrowser\",\n issued_at AS \"issuedAt\",\n expires_at AS \"expiresAt\",\n last_connected_at AS \"lastConnectedAt\",\n revoked_at AS \"revokedAt\"\n FROM auth_sessions\n WHERE session_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"otlp-span","name":"RpcClient.filesystem.browse","traceId":"4a8337b4401ffbe728aa0deffd4a622a","spanId":"af23ef0b2a3f61f0","sampled":true,"kind":"internal","startTimeUnixNano":"1779351893132800000","endTimeUnixNano":"1779351893134900000","durationMs":2.1,"attributes":{},"resourceAttributes":{"service.runtime":"t3-web","service.mode":"electron","service.name":"t3-web","service.version":"0.0.24"},"scope":{"name":"t3-web","attributes":{}},"events":[],"links":[],"status":{"code":"1"}} -{"type":"otlp-span","name":"RpcClient.filesystem.browse","traceId":"cb4971cdcd4b3990a87e4a9c92c6b7ba","spanId":"72962fa4cd7bd9f1","sampled":true,"kind":"internal","startTimeUnixNano":"1779351893265400000","endTimeUnixNano":"1779351893308600000","durationMs":43.2,"attributes":{},"resourceAttributes":{"service.runtime":"t3-web","service.mode":"electron","service.name":"t3-web","service.version":"0.0.24"},"scope":{"name":"t3-web","attributes":{}},"events":[],"links":[],"status":{"code":"1"}} -{"type":"otlp-span","name":"RpcClient.filesystem.browse","traceId":"abe3cde54980c50fe57160a54e37f325","spanId":"8bf7e62d44937bbc","sampled":true,"kind":"internal","startTimeUnixNano":"1779351893648500000","endTimeUnixNano":"1779351893662700000","durationMs":14.2,"attributes":{},"resourceAttributes":{"service.runtime":"t3-web","service.mode":"electron","service.name":"t3-web","service.version":"0.0.24"},"scope":{"name":"t3-web","attributes":{}},"events":[],"links":[],"status":{"code":"1"}} -{"type":"effect-span","name":"http.server POST","traceId":"60a98f924bb80d5d959b791255612e89","spanId":"739bfc9cb495cf1b","sampled":true,"kind":"server","startTimeUnixNano":"1779351893789434500","endTimeUnixNano":"1779351893790510000","durationMs":1.0755,"attributes":{"http.route":"/api/observability/v1/traces","http.request.method":"POST","url.full":"http://127.0.0.1:14124/api/observability/v1/traces","url.path":"/api/observability/v1/traces","url.scheme":"http","user_agent.original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"close","http.request.header.content-length":"1363","http.request.header.sec-ch-ua-platform":"\"macOS\"","http.request.header.user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.sec-ch-ua":"\"Not-A.Brand\";v=\"24\", \"Chromium\";v=\"146\"","http.request.header.content-type":"application/json","http.request.header.sec-ch-ua-mobile":"?0","http.request.header.accept":"*/*","http.request.header.origin":"http://127.0.0.1:6084","http.request.header.sec-fetch-site":"same-origin","http.request.header.sec-fetch-mode":"cors","http.request.header.sec-fetch-dest":"empty","http.request.header.referer":"http://127.0.0.1:6084/","http.request.header.accept-encoding":"gzip, deflate, br, zstd","http.request.header.accept-language":"en-GB","http.request.header.cookie":"","http.response.status_code":204},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"WorkspaceEntries.browse","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"4726d4e9f25dede3","parentSpanId":"413882d5f8a62657","sampled":true,"kind":"internal","startTimeUnixNano":"1779351893922451209","endTimeUnixNano":"1779351893936869750","durationMs":14.418541,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.filesystem.browse","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"413882d5f8a62657","parentSpanId":"eb7a24ce917240d8","sampled":true,"kind":"internal","startTimeUnixNano":"1779351893922388209","endTimeUnixNano":"1779351893936956875","durationMs":14.568666,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"filesystem.browse","rpc.aggregate":"workspace"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"d1b2ed2f13fd2ff3ad0b7aab0d441cfd","spanId":"5d9636df16d29c81","parentSpanId":"f0d4e6e75091afbb","sampled":true,"kind":"client","startTimeUnixNano":"1779351894796427792","endTimeUnixNano":"1779351894796564000","durationMs":0.136208,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n session_id AS \"sessionId\",\n subject AS \"subject\",\n role AS \"role\",\n method AS \"method\",\n client_label AS \"clientLabel\",\n client_ip_address AS \"clientIpAddress\",\n client_user_agent AS \"clientUserAgent\",\n client_device_type AS \"clientDeviceType\",\n client_os AS \"clientOs\",\n client_browser AS \"clientBrowser\",\n issued_at AS \"issuedAt\",\n expires_at AS \"expiresAt\",\n last_connected_at AS \"lastConnectedAt\",\n revoked_at AS \"revokedAt\"\n FROM auth_sessions\n WHERE session_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"otlp-span","name":"RpcClient.filesystem.browse","traceId":"454ef65d4c82d8719252a19a29a57e3f","spanId":"493a936a349d75a6","sampled":true,"kind":"internal","startTimeUnixNano":"1779351893921900000","endTimeUnixNano":"1779351893937700000","durationMs":15.8,"attributes":{},"resourceAttributes":{"service.runtime":"t3-web","service.mode":"electron","service.name":"t3-web","service.version":"0.0.24"},"scope":{"name":"t3-web","attributes":{}},"events":[],"links":[],"status":{"code":"1"}} -{"type":"effect-span","name":"http.server POST","traceId":"d1b2ed2f13fd2ff3ad0b7aab0d441cfd","spanId":"f0d4e6e75091afbb","sampled":true,"kind":"server","startTimeUnixNano":"1779351894796001042","endTimeUnixNano":"1779351894797145709","durationMs":1.144667,"attributes":{"http.route":"/api/observability/v1/traces","http.request.method":"POST","url.full":"http://127.0.0.1:14124/api/observability/v1/traces","url.path":"/api/observability/v1/traces","url.scheme":"http","user_agent.original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"close","http.request.header.content-length":"695","http.request.header.sec-ch-ua-platform":"\"macOS\"","http.request.header.user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.sec-ch-ua":"\"Not-A.Brand\";v=\"24\", \"Chromium\";v=\"146\"","http.request.header.content-type":"application/json","http.request.header.sec-ch-ua-mobile":"?0","http.request.header.accept":"*/*","http.request.header.origin":"http://127.0.0.1:6084","http.request.header.sec-fetch-site":"same-origin","http.request.header.sec-fetch-mode":"cors","http.request.header.sec-fetch-dest":"empty","http.request.header.referer":"http://127.0.0.1:6084/","http.request.header.accept-encoding":"gzip, deflate, br, zstd","http.request.header.accept-language":"en-GB","http.request.header.cookie":"","http.response.status_code":204},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"WorkspacePaths.normalizeWorkspaceRoot","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"ae15349f93137c2c","parentSpanId":"a7606e184694b678","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896302072959","endTimeUnixNano":"1779351896302598042","durationMs":0.525083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"6c8b3163fecf5ffb","parentSpanId":"68b18dd8a47b1e1b","sampled":true,"kind":"client","startTimeUnixNano":"1779351896303750917","endTimeUnixNano":"1779351896304128875","durationMs":0.377958,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n command_id AS \"commandId\",\n aggregate_kind AS \"aggregateKind\",\n aggregate_id AS \"aggregateId\",\n accepted_at AS \"acceptedAt\",\n result_sequence AS \"resultSequence\",\n status,\n error\n FROM orchestration_command_receipts\n WHERE command_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"decideOrchestrationCommand","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"b9aa830f679d4940","parentSpanId":"68b18dd8a47b1e1b","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896304209250","endTimeUnixNano":"1779351896304977250","durationMs":0.768,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"6d294eef2cb8be61","parentSpanId":"0c70120b1f0d4a9e","sampled":true,"kind":"client","startTimeUnixNano":"1779351896305809625","endTimeUnixNano":"1779351896306512042","durationMs":0.702417,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n INSERT INTO orchestration_events (\n event_id,\n aggregate_kind,\n stream_id,\n stream_version,\n event_type,\n occurred_at,\n command_id,\n causation_event_id,\n correlation_id,\n actor_kind,\n payload_json,\n metadata_json\n )\n VALUES (\n ?,\n ?,\n ?,\n COALESCE(\n (\n SELECT stream_version + 1\n FROM orchestration_events\n WHERE aggregate_kind = ?\n AND stream_id = ?\n ORDER BY stream_version DESC\n LIMIT 1\n ),\n 0\n ),\n ?,\n ?,\n ?,\n ?,\n ?,\n ?,\n ?,\n ?\n )\n RETURNING\n sequence,\n event_id AS \"eventId\",\n event_type AS \"type\",\n aggregate_kind AS \"aggregateKind\",\n stream_id AS \"aggregateId\",\n occurred_at AS \"occurredAt\",\n command_id AS \"commandId\",\n causation_event_id AS \"causationEventId\",\n correlation_id AS \"correlationId\",\n payload_json AS \"payload\",\n metadata_json AS \"metadata\"\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"d0e0a447b1aaca29","parentSpanId":"30101a0176fd4636","sampled":true,"kind":"client","startTimeUnixNano":"1779351896308673292","endTimeUnixNano":"1779351896309042750","durationMs":0.369458,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n INSERT INTO projection_projects (\n project_id,\n title,\n workspace_root,\n default_model_selection_json,\n scripts_json,\n created_at,\n updated_at,\n deleted_at\n )\n VALUES (\n ?,\n ?,\n ?,\n ?,\n ?,\n ?,\n ?,\n ?\n )\n ON CONFLICT (project_id)\n DO UPDATE SET\n title = excluded.title,\n workspace_root = excluded.workspace_root,\n default_model_selection_json = excluded.default_model_selection_json,\n scripts_json = excluded.scripts_json,\n created_at = excluded.created_at,\n updated_at = excluded.updated_at,\n deleted_at = excluded.deleted_at\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProjectsProjection","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"30101a0176fd4636","parentSpanId":"b890fc4e0a24d90e","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896308363417","endTimeUnixNano":"1779351896309103584","durationMs":0.740167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"292dcbba21fb97a0","parentSpanId":"b890fc4e0a24d90e","sampled":true,"kind":"client","startTimeUnixNano":"1779351896309297917","endTimeUnixNano":"1779351896309444792","durationMs":0.146875,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n INSERT INTO projection_state (\n projector,\n last_applied_sequence,\n updated_at\n )\n VALUES (\n ?,\n ?,\n ?\n )\n ON CONFLICT (projector)\n DO UPDATE SET\n last_applied_sequence = excluded.last_applied_sequence,\n updated_at = excluded.updated_at\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.transaction","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"b890fc4e0a24d90e","parentSpanId":"973adfe91348405c","sampled":true,"kind":"client","startTimeUnixNano":"1779351896308205292","endTimeUnixNano":"1779351896309483000","durationMs":1.277708,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite"},"events":[{"name":"db.transaction.savepoint","timeUnixNano":"1779351896309469834","attributes":{}}],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runAttachmentSideEffects","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"3e8b4c7252a76276","parentSpanId":"973adfe91348405c","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896309541292","endTimeUnixNano":"1779351896309792167","durationMs":0.250875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProjectorForEvent","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"973adfe91348405c","parentSpanId":"0c70120b1f0d4a9e","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896308083959","endTimeUnixNano":"1779351896309801750","durationMs":1.717791,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyThreadMessagesProjection","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"eda77ee9dd8c81b9","parentSpanId":"cbfed5d0073b9c57","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896309911917","endTimeUnixNano":"1779351896310076584","durationMs":0.164667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"b72692002fe8cf63","parentSpanId":"cbfed5d0073b9c57","sampled":true,"kind":"client","startTimeUnixNano":"1779351896310111042","endTimeUnixNano":"1779351896310160167","durationMs":0.049125,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n INSERT INTO projection_state (\n projector,\n last_applied_sequence,\n updated_at\n )\n VALUES (\n ?,\n ?,\n ?\n )\n ON CONFLICT (projector)\n DO UPDATE SET\n last_applied_sequence = excluded.last_applied_sequence,\n updated_at = excluded.updated_at\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.transaction","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"cbfed5d0073b9c57","parentSpanId":"65b21ace5148ba9e","sampled":true,"kind":"client","startTimeUnixNano":"1779351896309850334","endTimeUnixNano":"1779351896310178709","durationMs":0.328375,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite"},"events":[{"name":"db.transaction.savepoint","timeUnixNano":"1779351896310174334","attributes":{}}],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runAttachmentSideEffects","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"a9ed6c81bbc29c49","parentSpanId":"65b21ace5148ba9e","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896310203750","endTimeUnixNano":"1779351896310240792","durationMs":0.037042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProjectorForEvent","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"65b21ace5148ba9e","parentSpanId":"0c70120b1f0d4a9e","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896309823792","endTimeUnixNano":"1779351896310247750","durationMs":0.423958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyThreadProposedPlansProjection","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"6fa572d614754fdc","parentSpanId":"0f0431a7fa403d8d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896310325209","endTimeUnixNano":"1779351896310414042","durationMs":0.088833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"7351330386b5835f","parentSpanId":"0f0431a7fa403d8d","sampled":true,"kind":"client","startTimeUnixNano":"1779351896310437417","endTimeUnixNano":"1779351896310465792","durationMs":0.028375,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n INSERT INTO projection_state (\n projector,\n last_applied_sequence,\n updated_at\n )\n VALUES (\n ?,\n ?,\n ?\n )\n ON CONFLICT (projector)\n DO UPDATE SET\n last_applied_sequence = excluded.last_applied_sequence,\n updated_at = excluded.updated_at\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.transaction","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"0f0431a7fa403d8d","parentSpanId":"001b25882dff67e1","sampled":true,"kind":"client","startTimeUnixNano":"1779351896310281000","endTimeUnixNano":"1779351896310482500","durationMs":0.2015,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite"},"events":[{"name":"db.transaction.savepoint","timeUnixNano":"1779351896310477250","attributes":{}}],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runAttachmentSideEffects","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"16b439dfa5ed958a","parentSpanId":"001b25882dff67e1","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896310505250","endTimeUnixNano":"1779351896311152459","durationMs":0.647209,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProjectorForEvent","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"001b25882dff67e1","parentSpanId":"0c70120b1f0d4a9e","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896310263292","endTimeUnixNano":"1779351896311162042","durationMs":0.89875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyThreadActivitiesProjection","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"2bd805edec022ba4","parentSpanId":"776eb9bb33fcf663","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896311249250","endTimeUnixNano":"1779351896311335167","durationMs":0.085917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"469b8ab7d6ff6168","parentSpanId":"776eb9bb33fcf663","sampled":true,"kind":"client","startTimeUnixNano":"1779351896311360084","endTimeUnixNano":"1779351896311396375","durationMs":0.036291,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n INSERT INTO projection_state (\n projector,\n last_applied_sequence,\n updated_at\n )\n VALUES (\n ?,\n ?,\n ?\n )\n ON CONFLICT (projector)\n DO UPDATE SET\n last_applied_sequence = excluded.last_applied_sequence,\n updated_at = excluded.updated_at\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.transaction","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"776eb9bb33fcf663","parentSpanId":"ef416122ee793f9e","sampled":true,"kind":"client","startTimeUnixNano":"1779351896311202292","endTimeUnixNano":"1779351896311424542","durationMs":0.22225,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite"},"events":[{"name":"db.transaction.savepoint","timeUnixNano":"1779351896311409834","attributes":{}}],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runAttachmentSideEffects","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"c16d053d1f8dbe4f","parentSpanId":"ef416122ee793f9e","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896311456167","endTimeUnixNano":"1779351896311487584","durationMs":0.031417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProjectorForEvent","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"ef416122ee793f9e","parentSpanId":"0c70120b1f0d4a9e","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896311183625","endTimeUnixNano":"1779351896311494667","durationMs":0.311042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyThreadSessionsProjection","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"1a8c24cd66409a44","parentSpanId":"38848459fea92cf9","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896311583875","endTimeUnixNano":"1779351896311630625","durationMs":0.04675,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"d2b45084cd16d830","parentSpanId":"38848459fea92cf9","sampled":true,"kind":"client","startTimeUnixNano":"1779351896311650542","endTimeUnixNano":"1779351896311718125","durationMs":0.067583,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n INSERT INTO projection_state (\n projector,\n last_applied_sequence,\n updated_at\n )\n VALUES (\n ?,\n ?,\n ?\n )\n ON CONFLICT (projector)\n DO UPDATE SET\n last_applied_sequence = excluded.last_applied_sequence,\n updated_at = excluded.updated_at\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.transaction","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"38848459fea92cf9","parentSpanId":"c2a231b96a4726ee","sampled":true,"kind":"client","startTimeUnixNano":"1779351896311526292","endTimeUnixNano":"1779351896311757209","durationMs":0.230917,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite"},"events":[{"name":"db.transaction.savepoint","timeUnixNano":"1779351896311751292","attributes":{}}],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runAttachmentSideEffects","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"0b651d760f232f09","parentSpanId":"c2a231b96a4726ee","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896311812209","endTimeUnixNano":"1779351896311881125","durationMs":0.068916,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProjectorForEvent","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"c2a231b96a4726ee","parentSpanId":"0c70120b1f0d4a9e","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896311508792","endTimeUnixNano":"1779351896311892167","durationMs":0.383375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyThreadTurnsProjection","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"33b56792a097fc39","parentSpanId":"df4d5eccd4de4947","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896312034875","endTimeUnixNano":"1779351896312498000","durationMs":0.463125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"a37d37f5101ac68a","parentSpanId":"df4d5eccd4de4947","sampled":true,"kind":"client","startTimeUnixNano":"1779351896312563667","endTimeUnixNano":"1779351896313355542","durationMs":0.791875,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n INSERT INTO projection_state (\n projector,\n last_applied_sequence,\n updated_at\n )\n VALUES (\n ?,\n ?,\n ?\n )\n ON CONFLICT (projector)\n DO UPDATE SET\n last_applied_sequence = excluded.last_applied_sequence,\n updated_at = excluded.updated_at\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.transaction","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"df4d5eccd4de4947","parentSpanId":"4d6a41faf1db1a49","sampled":true,"kind":"client","startTimeUnixNano":"1779351896311936709","endTimeUnixNano":"1779351896313676250","durationMs":1.739541,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite"},"events":[{"name":"db.transaction.savepoint","timeUnixNano":"1779351896313663292","attributes":{}}],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runAttachmentSideEffects","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"eb977e78a6de8562","parentSpanId":"4d6a41faf1db1a49","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896313714417","endTimeUnixNano":"1779351896313764250","durationMs":0.049833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProjectorForEvent","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"4d6a41faf1db1a49","parentSpanId":"0c70120b1f0d4a9e","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896311911209","endTimeUnixNano":"1779351896313773042","durationMs":1.861833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"da79bee8e35178f2","parentSpanId":"f19c4ab996c778c8","sampled":true,"kind":"client","startTimeUnixNano":"1779351896313896875","endTimeUnixNano":"1779351896313962709","durationMs":0.065834,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n INSERT INTO projection_state (\n projector,\n last_applied_sequence,\n updated_at\n )\n VALUES (\n ?,\n ?,\n ?\n )\n ON CONFLICT (projector)\n DO UPDATE SET\n last_applied_sequence = excluded.last_applied_sequence,\n updated_at = excluded.updated_at\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.transaction","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"f19c4ab996c778c8","parentSpanId":"2eea38cc151203bd","sampled":true,"kind":"client","startTimeUnixNano":"1779351896313833750","endTimeUnixNano":"1779351896313978834","durationMs":0.145084,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite"},"events":[{"name":"db.transaction.savepoint","timeUnixNano":"1779351896313976584","attributes":{}}],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runAttachmentSideEffects","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"d793e4848bb0981c","parentSpanId":"2eea38cc151203bd","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896314003709","endTimeUnixNano":"1779351896314051250","durationMs":0.047541,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProjectorForEvent","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"2eea38cc151203bd","parentSpanId":"0c70120b1f0d4a9e","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896313792042","endTimeUnixNano":"1779351896314058167","durationMs":0.266125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyPendingApprovalsProjection","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"6986e162405448fd","parentSpanId":"6c74cb1b0e1bd047","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896314129125","endTimeUnixNano":"1779351896314278667","durationMs":0.149542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"853b694a903c5869","parentSpanId":"6c74cb1b0e1bd047","sampled":true,"kind":"client","startTimeUnixNano":"1779351896314299667","endTimeUnixNano":"1779351896314353250","durationMs":0.053583,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n INSERT INTO projection_state (\n projector,\n last_applied_sequence,\n updated_at\n )\n VALUES (\n ?,\n ?,\n ?\n )\n ON CONFLICT (projector)\n DO UPDATE SET\n last_applied_sequence = excluded.last_applied_sequence,\n updated_at = excluded.updated_at\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.transaction","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"6c74cb1b0e1bd047","parentSpanId":"09da6271d55aab86","sampled":true,"kind":"client","startTimeUnixNano":"1779351896314098042","endTimeUnixNano":"1779351896314365292","durationMs":0.26725,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite"},"events":[{"name":"db.transaction.savepoint","timeUnixNano":"1779351896314363792","attributes":{}}],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runAttachmentSideEffects","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"db119ba137e20927","parentSpanId":"09da6271d55aab86","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896314383000","endTimeUnixNano":"1779351896314427542","durationMs":0.044542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProjectorForEvent","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"09da6271d55aab86","parentSpanId":"0c70120b1f0d4a9e","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896314080417","endTimeUnixNano":"1779351896314434167","durationMs":0.35375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyThreadsProjection","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"70afaf0a8692dee1","parentSpanId":"7e4e116c2e64a49f","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896314493917","endTimeUnixNano":"1779351896314722875","durationMs":0.228958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"94b00de47e53a13a","parentSpanId":"7e4e116c2e64a49f","sampled":true,"kind":"client","startTimeUnixNano":"1779351896314746667","endTimeUnixNano":"1779351896314797709","durationMs":0.051042,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n INSERT INTO projection_state (\n projector,\n last_applied_sequence,\n updated_at\n )\n VALUES (\n ?,\n ?,\n ?\n )\n ON CONFLICT (projector)\n DO UPDATE SET\n last_applied_sequence = excluded.last_applied_sequence,\n updated_at = excluded.updated_at\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.transaction","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"7e4e116c2e64a49f","parentSpanId":"af5ba866b602fe78","sampled":true,"kind":"client","startTimeUnixNano":"1779351896314461084","endTimeUnixNano":"1779351896314811292","durationMs":0.350208,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite"},"events":[{"name":"db.transaction.savepoint","timeUnixNano":"1779351896314808250","attributes":{}}],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runAttachmentSideEffects","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"29b2b47f63029cd2","parentSpanId":"af5ba866b602fe78","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896314830292","endTimeUnixNano":"1779351896314865584","durationMs":0.035292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProjectorForEvent","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"af5ba866b602fe78","parentSpanId":"0c70120b1f0d4a9e","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896314448292","endTimeUnixNano":"1779351896314871417","durationMs":0.423125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"5f3c63255a963d35","parentSpanId":"0c70120b1f0d4a9e","sampled":true,"kind":"client","startTimeUnixNano":"1779351896315011959","endTimeUnixNano":"1779351896315159792","durationMs":0.147833,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n INSERT INTO orchestration_command_receipts (\n command_id,\n aggregate_kind,\n aggregate_id,\n accepted_at,\n result_sequence,\n status,\n error\n )\n VALUES (\n ?,\n ?,\n ?,\n ?,\n ?,\n ?,\n ?\n )\n ON CONFLICT (command_id)\n DO UPDATE SET\n aggregate_kind = excluded.aggregate_kind,\n aggregate_id = excluded.aggregate_id,\n accepted_at = excluded.accepted_at,\n result_sequence = excluded.result_sequence,\n status = excluded.status,\n error = excluded.error\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.transaction","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"0c70120b1f0d4a9e","parentSpanId":"68b18dd8a47b1e1b","sampled":true,"kind":"client","startTimeUnixNano":"1779351896305038292","endTimeUnixNano":"1779351896315702834","durationMs":10.664542,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite"},"events":[{"name":"db.transaction.commit","timeUnixNano":"1779351896315179917","attributes":{}}],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processEvent","traceId":"9c222a79013464bbed30efe9f66a4107","spanId":"0c7297926500201b","parentSpanId":"02bc1709635397f9","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896315817459","endTimeUnixNano":"1779351896315859292","durationMs":0.041833,"attributes":{"server.mode":"desktop","server.port":14124,"server.host":"127.0.0.1","startup.phase":"reactors.start"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"6a2ed079e81c9c5e","parentSpanId":"a924f711f34aec51","sampled":true,"kind":"client","startTimeUnixNano":"1779351896316098459","endTimeUnixNano":"1779351896316236250","durationMs":0.137791,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n project_id AS \"projectId\",\n title,\n workspace_root AS \"workspaceRoot\",\n default_model_selection_json AS \"defaultModelSelection\",\n scripts_json AS \"scripts\",\n created_at AS \"createdAt\",\n updated_at AS \"updatedAt\",\n deleted_at AS \"deletedAt\"\n FROM projection_projects\n WHERE project_id = ?\n AND deleted_at IS NULL\n LIMIT 1\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"orchestration.command.project.create","traceId":"3c0655cdb80a68511ff55cfae73e865b","spanId":"68b18dd8a47b1e1b","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896303262709","endTimeUnixNano":"1779351896318409584","durationMs":15.146875,"attributes":{"orchestration.command_id":"3ba164f7-bf47-4a66-b21e-0e04f0681a4c","orchestration.command_type":"project.create","orchestration.aggregate_kind":"project","orchestration.aggregate_id":"7d50e4c9-595d-48f1-9f2f-fe427aab3d43"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.orchestration.dispatchCommand","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"a7606e184694b678","parentSpanId":"eb7a24ce917240d8","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896301476542","endTimeUnixNano":"1779351896318692167","durationMs":17.215625,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"orchestration.dispatchCommand","rpc.aggregate":"orchestration"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"ced3a2f233ab6500","parentSpanId":"93c0a7ea4c3d8ac3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896319197334","endTimeUnixNano":"1779351896325926625","durationMs":6.729291,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"3f25098e428154db","parentSpanId":"93c0a7ea4c3d8ac3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896319096625","endTimeUnixNano":"1779351896326005042","durationMs":6.908417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"93c0a7ea4c3d8ac3","parentSpanId":"5f599cb9e808ba1a","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896316624709","endTimeUnixNano":"1779351896326056542","durationMs":9.431833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveRepositoryIdentityCacheKey","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"5f599cb9e808ba1a","parentSpanId":"5f644bceff00eee3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896316503042","endTimeUnixNano":"1779351896326271084","durationMs":9.768042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"96a2dd969b8fa32a","parentSpanId":"585167675bdb8a97","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896327149667","endTimeUnixNano":"1779351896332005500","durationMs":4.855833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"af49f1ce370aba7c","parentSpanId":"585167675bdb8a97","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896327098917","endTimeUnixNano":"1779351896332071292","durationMs":4.972375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"585167675bdb8a97","parentSpanId":"901a35f57cfd0462","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896326437542","endTimeUnixNano":"1779351896332117125","durationMs":5.679583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveRepositoryIdentityFromCacheKey","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"901a35f57cfd0462","parentSpanId":"5f644bceff00eee3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896326328875","endTimeUnixNano":"1779351896332231292","durationMs":5.902417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"RepositoryIdentityResolver.resolve","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"5f644bceff00eee3","parentSpanId":"a924f711f34aec51","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896316444875","endTimeUnixNano":"1779351896332267792","durationMs":15.822917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"a9b34e5111d5a888","parentSpanId":"730ac897b05adc73","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896447694125","endTimeUnixNano":"1779351896449584459","durationMs":1.890334,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"ProcessSpawnError: \n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14166:38\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/effect.js:1309:96\n at ~effect/Utils/internal (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Utils.js:69:12)\n at processRunner.runProcessCore (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14219:44)\n at processRunner.runProcessCore (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14155:31)\n at VcsProcess.run (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:24401:18)\n at VcsProcess.run (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19834:21)\n at ws.rpc.server.discoverSourceControl (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:17831:111) {\n [cause]: PlatformError: NotFound: ChildProcess.spawn (jj --version)\n at Module.systemError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/PlatformError.js:59:39)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/internal/utils.js:28:24\n at toPlatformError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:25:54)\n at ChildProcess. (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:230:26)\n at ChildProcess.emit (node:events:509:28)\n at ChildProcess._handle.onexit (node:internal/child_process:293:12)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {\n [cause]: Error: spawn jj ENOENT\n at ChildProcess._handle.onexit (node:internal/child_process:287:19)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n }\n}"}} -{"type":"effect-span","name":"VcsProcess.run","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"730ac897b05adc73","parentSpanId":"b5c60472d691a9af","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896447673917","endTimeUnixNano":"1779351896449745334","durationMs":2.071417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"VcsProcessSpawnError: VCS process failed to spawn in source-control.discovery.probe: jj --version (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69)\n at VcsProcessSpawnError.fromProcessSpawnError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:3950:10)\n at Object.ProcessSpawnError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19854:55)\n at Object.evaluate (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:170:101)\n at i (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:236:37)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:281:20\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:133:10\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Function.js:97:18\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/effect.js:1309:96\n at ~effect/Utils/internal (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Utils.js:69:12)\n at VcsProcess.run (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:24401:18)\n at VcsProcess.run (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19834:21)\n at ws.rpc.server.discoverSourceControl (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:17831:111) {\n [cause]: PlatformError: NotFound: ChildProcess.spawn (jj --version)\n at Module.systemError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/PlatformError.js:59:39)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/internal/utils.js:28:24\n at toPlatformError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:25:54)\n at ChildProcess. (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:230:26)\n at ChildProcess.emit (node:events:509:28)\n at ChildProcess._handle.onexit (node:internal/child_process:293:12)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {\n [cause]: Error: spawn jj ENOENT\n at ChildProcess._handle.onexit (node:internal/child_process:287:19)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n }\n}"}} -{"type":"effect-span","name":"sql.execute","traceId":"06a4a75e28fe7ec70bbe9e200d5ff79b","spanId":"728b19b58e491920","parentSpanId":"8bc7282601fd4b0a","sampled":true,"kind":"client","startTimeUnixNano":"1779351896450952417","endTimeUnixNano":"1779351896451001125","durationMs":0.048708,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n session_id AS \"sessionId\",\n subject AS \"subject\",\n role AS \"role\",\n method AS \"method\",\n client_label AS \"clientLabel\",\n client_ip_address AS \"clientIpAddress\",\n client_user_agent AS \"clientUserAgent\",\n client_device_type AS \"clientDeviceType\",\n client_os AS \"clientOs\",\n client_browser AS \"clientBrowser\",\n issued_at AS \"issuedAt\",\n expires_at AS \"expiresAt\",\n last_connected_at AS \"lastConnectedAt\",\n revoked_at AS \"revokedAt\"\n FROM auth_sessions\n WHERE session_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.getCachedStatus","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"422be50acd7e0746","parentSpanId":"1b3f800a1a13806f","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896451410834","endTimeUnixNano":"1779351896451428917","durationMs":0.018083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"06a4a75e28fe7ec70bbe9e200d5ff79b","spanId":"4ed4a8fc7dc50b0a","parentSpanId":"ad9337b6e4d91e84","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896451213875","endTimeUnixNano":"1779351896451733542","durationMs":0.519667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProjectConfig.findConfigPath","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"b13ef0c0ab345b98","parentSpanId":"8b62fae51cea2262","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896450615542","endTimeUnixNano":"1779351896451765917","durationMs":1.150375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProjectConfig.resolveKind","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"8b62fae51cea2262","parentSpanId":"767ba492b7c97f35","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896450596000","endTimeUnixNano":"1779351896451770334","durationMs":1.174334,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"06a4a75e28fe7ec70bbe9e200d5ff79b","spanId":"cd042f8847ce6062","parentSpanId":"ad9337b6e4d91e84","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896451744334","endTimeUnixNano":"1779351896460150417","durationMs":8.406083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"3661595d4ea463c8","parentSpanId":"65b0be676efeb90d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896448663709","endTimeUnixNano":"1779351896461384584","durationMs":12.720875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"a8b465ee846f5c41","parentSpanId":"65b0be676efeb90d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896448597042","endTimeUnixNano":"1779351896461458167","durationMs":12.861125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"65b0be676efeb90d","parentSpanId":"9377f1e929c336ce","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896447623959","endTimeUnixNano":"1779351896461475792","durationMs":13.851833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProcess.run","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"9377f1e929c336ce","parentSpanId":"b5c60472d691a9af","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896447576000","endTimeUnixNano":"1779351896461528917","durationMs":13.952917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"06a4a75e28fe7ec70bbe9e200d5ff79b","spanId":"80e56dc56cc4fce1","parentSpanId":"ad9337b6e4d91e84","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896460195334","endTimeUnixNano":"1779351896462716750","durationMs":2.521416,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"bf1690d350b0c2ca","parentSpanId":"9b59051ce6f908e3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896461807167","endTimeUnixNano":"1779351896467020417","durationMs":5.21325,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"ProcessSpawnError: \n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14166:38\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/effect.js:1309:96\n at ~effect/Utils/internal (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Utils.js:69:12)\n at processRunner.runProcessCore (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14219:44)\n at processRunner.runProcessCore (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14155:31)\n at VcsProcess.run (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:20703:23)\n at VcsProcess.run (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19834:21)\n at ws.rpc.server.discoverSourceControl (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:17831:111) {\n [cause]: PlatformError: NotFound: ChildProcess.spawn (glab --version)\n at Module.systemError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/PlatformError.js:59:39)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/internal/utils.js:28:24\n at toPlatformError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:25:54)\n at ChildProcess. (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:230:26)\n at ChildProcess.emit (node:events:509:28)\n at ChildProcess._handle.onexit (node:internal/child_process:293:12)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {\n [cause]: Error: spawn glab ENOENT\n at ChildProcess._handle.onexit (node:internal/child_process:287:19)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n }\n}"}} -{"type":"effect-span","name":"VcsProcess.run","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"9b59051ce6f908e3","parentSpanId":"b5c60472d691a9af","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896461622375","endTimeUnixNano":"1779351896467193667","durationMs":5.571292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"VcsProcessSpawnError: VCS process failed to spawn in source-control.discovery.probe: glab --version (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69)\n at VcsProcessSpawnError.fromProcessSpawnError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:3950:10)\n at Object.ProcessSpawnError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19854:55)\n at Object.evaluate (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:170:101)\n at i (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:236:37)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:281:20\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:133:10\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Function.js:97:18\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/effect.js:1309:96\n at ~effect/Utils/internal (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Utils.js:69:12)\n at VcsProcess.run (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:20703:23)\n at VcsProcess.run (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19834:21)\n at ws.rpc.server.discoverSourceControl (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:17831:111) {\n [cause]: PlatformError: NotFound: ChildProcess.spawn (glab --version)\n at Module.systemError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/PlatformError.js:59:39)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/internal/utils.js:28:24\n at toPlatformError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:25:54)\n at ChildProcess. (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:230:26)\n at ChildProcess.emit (node:events:509:28)\n at ChildProcess._handle.onexit (node:internal/child_process:293:12)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {\n [cause]: Error: spawn glab ENOENT\n at ChildProcess._handle.onexit (node:internal/child_process:287:19)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n }\n}"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"ac08dc2d1c8dffcc","parentSpanId":"f9e5850c7ff98209","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896461884667","endTimeUnixNano":"1779351896468601917","durationMs":6.71725,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"ProcessSpawnError: \n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14166:38\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/effect.js:1309:96\n at ~effect/Utils/internal (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Utils.js:69:12)\n at processRunner.runProcessCore (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14219:44)\n at processRunner.runProcessCore (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14155:31)\n at VcsProcess.run (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:20703:23)\n at VcsProcess.run (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19834:21)\n at ws.rpc.server.discoverSourceControl (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:17831:111) {\n [cause]: PlatformError: NotFound: ChildProcess.spawn (az --version)\n at Module.systemError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/PlatformError.js:59:39)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/internal/utils.js:28:24\n at toPlatformError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:25:54)\n at ChildProcess. (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:230:26)\n at ChildProcess.emit (node:events:509:28)\n at ChildProcess._handle.onexit (node:internal/child_process:293:12)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {\n [cause]: Error: spawn az ENOENT\n at ChildProcess._handle.onexit (node:internal/child_process:287:19)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n }\n}"}} -{"type":"effect-span","name":"VcsProcess.run","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"f9e5850c7ff98209","parentSpanId":"b5c60472d691a9af","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896461840292","endTimeUnixNano":"1779351896468734292","durationMs":6.894,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"VcsProcessSpawnError: VCS process failed to spawn in source-control.discovery.probe: az --version (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69)\n at VcsProcessSpawnError.fromProcessSpawnError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:3950:10)\n at Object.ProcessSpawnError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19854:55)\n at Object.evaluate (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:170:101)\n at i (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:236:37)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:281:20\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:133:10\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Function.js:97:18\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/effect.js:1309:96\n at ~effect/Utils/internal (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Utils.js:69:12)\n at VcsProcess.run (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:20703:23)\n at VcsProcess.run (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19834:21)\n at ws.rpc.server.discoverSourceControl (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:17831:111) {\n [cause]: PlatformError: NotFound: ChildProcess.spawn (az --version)\n at Module.systemError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/PlatformError.js:59:39)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/internal/utils.js:28:24\n at toPlatformError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:25:54)\n at ChildProcess. (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:230:26)\n at ChildProcess.emit (node:events:509:28)\n at ChildProcess._handle.onexit (node:internal/child_process:293:12)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {\n [cause]: Error: spawn az ENOENT\n at ChildProcess._handle.onexit (node:internal/child_process:287:19)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n }\n}"}} -{"type":"effect-span","name":"VcsProjectConfig.findConfigPath","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"4ca4af5dcc74daf9","parentSpanId":"8ee9910b1fc11e0d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896451688292","endTimeUnixNano":"1779351896468818042","durationMs":17.12975,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProjectConfig.resolveKind","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"8ee9910b1fc11e0d","parentSpanId":"b5285b25f83a6a4c","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896451656375","endTimeUnixNano":"1779351896468823417","durationMs":17.167042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"06a4a75e28fe7ec70bbe9e200d5ff79b","spanId":"c3c040159bf60c07","parentSpanId":"ad9337b6e4d91e84","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896462768542","endTimeUnixNano":"1779351896468851584","durationMs":6.083042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"cb63ef854f223d21","parentSpanId":"1295f9814f949ead","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896461216750","endTimeUnixNano":"1779351896469177000","durationMs":7.96025,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"5edb0ebb8305f581","parentSpanId":"1295f9814f949ead","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896461270875","endTimeUnixNano":"1779351896469283875","durationMs":8.013,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"1295f9814f949ead","parentSpanId":"21bd503ba44db7f3","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896451986542","endTimeUnixNano":"1779351896469297542","durationMs":17.311,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProcess.run","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"21bd503ba44db7f3","parentSpanId":"f34ec3b641dbbbec","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896451912459","endTimeUnixNano":"1779351896469500584","durationMs":17.588125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"detectRepository","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"f34ec3b641dbbbec","parentSpanId":"9c366fa4514472ab","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896451848417","endTimeUnixNano":"1779351896469528875","durationMs":17.680458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsDriverRegistry.detectWithDriver","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"9c366fa4514472ab","parentSpanId":"86b45229aa54c825","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896451833334","endTimeUnixNano":"1779351896469532167","durationMs":17.698833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsDriverRegistry.detectResolvedKind","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"86b45229aa54c825","parentSpanId":"767ba492b7c97f35","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896451808917","endTimeUnixNano":"1779351896469535042","durationMs":17.726125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsDriverRegistry.detect","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"b5285b25f83a6a4c","parentSpanId":"7f1bb6dff86a1e94","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896451583709","endTimeUnixNano":"1779351896469539709","durationMs":17.956,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"GitWorkflowService.detectGitRepositoryForStatus","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"7f1bb6dff86a1e94","parentSpanId":"1294a206326d048d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896451459625","endTimeUnixNano":"1779351896469543417","durationMs":18.083792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.updateCachedLocalStatus","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"cef8664c4751a64c","parentSpanId":"1294a206326d048d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896469578750","endTimeUnixNano":"1779351896469642500","durationMs":0.06375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.loadLocalStatus","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"1294a206326d048d","parentSpanId":"1b3f800a1a13806f","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896451437792","endTimeUnixNano":"1779351896469646667","durationMs":18.208875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.getOrLoadLocalStatus","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"1b3f800a1a13806f","parentSpanId":"2f47d784f13b08ef","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896451393834","endTimeUnixNano":"1779351896469649834","durationMs":18.256,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.getCachedStatus","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"a2f7d5060fe0a6d5","parentSpanId":"2f47d784f13b08ef","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896469658042","endTimeUnixNano":"1779351896469666084","durationMs":0.008042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.retainRemotePoller","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"0de046848fef93a1","parentSpanId":"2f47d784f13b08ef","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896469679667","endTimeUnixNano":"1779351896469780417","durationMs":0.10075,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsDriverRegistry.detect","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"767ba492b7c97f35","parentSpanId":"efb919c85619900f","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896450572459","endTimeUnixNano":"1779351896469986792","durationMs":19.414333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"GitWorkflowService.detectGitRepositoryForCommand","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"efb919c85619900f","parentSpanId":"fbb49a5abb96cc4d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896450540750","endTimeUnixNano":"1779351896469991750","durationMs":19.451,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.vcs.listRefs","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"fbb49a5abb96cc4d","parentSpanId":"eb7a24ce917240d8","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896450525167","endTimeUnixNano":"1779351896470172584","durationMs":19.647417,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"vcs.listRefs","rpc.aggregate":"vcs"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"06a4a75e28fe7ec70bbe9e200d5ff79b","spanId":"10810b848d73cf11","parentSpanId":"ad9337b6e4d91e84","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896468876417","endTimeUnixNano":"1779351896470563292","durationMs":1.686875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"06a4a75e28fe7ec70bbe9e200d5ff79b","spanId":"99d5e897ed702d07","parentSpanId":"ad9337b6e4d91e84","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896470614875","endTimeUnixNano":"1779351896471128000","durationMs":0.513125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"06a4a75e28fe7ec70bbe9e200d5ff79b","spanId":"3c2e807fe400593c","parentSpanId":"ad9337b6e4d91e84","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896471139417","endTimeUnixNano":"1779351896471194792","durationMs":0.055375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"invalidateRemoteStatus","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"aaef458919700bfb","parentSpanId":"f225ed1e950d177b","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896471020667","endTimeUnixNano":"1779351896471234125","durationMs":0.213458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"06a4a75e28fe7ec70bbe9e200d5ff79b","spanId":"063ce7280544ee94","parentSpanId":"ad9337b6e4d91e84","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896471212625","endTimeUnixNano":"1779351896471310584","durationMs":0.097959,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"06a4a75e28fe7ec70bbe9e200d5ff79b","spanId":"5e2c0d21ec902078","parentSpanId":"ad9337b6e4d91e84","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896471322750","endTimeUnixNano":"1779351896471945917","durationMs":0.623167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"06a4a75e28fe7ec70bbe9e200d5ff79b","spanId":"324adab846e110cb","parentSpanId":"ad9337b6e4d91e84","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896472006959","endTimeUnixNano":"1779351896472166334","durationMs":0.159375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProjectConfig.findConfigPath","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"637d4e28883ef250","parentSpanId":"1c1b297a609bdb45","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896471285292","endTimeUnixNano":"1779351896472246667","durationMs":0.961375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProjectConfig.resolveKind","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"1c1b297a609bdb45","parentSpanId":"a9cd81460e184284","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896471276834","endTimeUnixNano":"1779351896472255375","durationMs":0.978541,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsDriverRegistry.detect","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"a9cd81460e184284","parentSpanId":"12cd9e2b5979fdaa","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896471267750","endTimeUnixNano":"1779351896472275834","durationMs":1.008084,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"GitWorkflowService.detectGitRepositoryForStatus","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"12cd9e2b5979fdaa","parentSpanId":"f225ed1e950d177b","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896471250500","endTimeUnixNano":"1779351896472283500","durationMs":1.033,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.updateCachedRemoteStatus","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"c4071c32ea415bff","parentSpanId":"f225ed1e950d177b","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896472338417","endTimeUnixNano":"1779351896472619000","durationMs":0.280583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.refreshRemoteStatus","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"f225ed1e950d177b","parentSpanId":"0de046848fef93a1","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896470996500","endTimeUnixNano":"1779351896472627917","durationMs":1.631417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"06a4a75e28fe7ec70bbe9e200d5ff79b","spanId":"f0f1b173f63f788e","parentSpanId":"ad9337b6e4d91e84","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896472199167","endTimeUnixNano":"1779351896473408459","durationMs":1.209292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"06a4a75e28fe7ec70bbe9e200d5ff79b","spanId":"cf2ff0b1eca13e5d","parentSpanId":"ad9337b6e4d91e84","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896473474917","endTimeUnixNano":"1779351896473574209","durationMs":0.099292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"06a4a75e28fe7ec70bbe9e200d5ff79b","spanId":"893e0339ec2686b3","parentSpanId":"ad9337b6e4d91e84","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896473600375","endTimeUnixNano":"1779351896473650334","durationMs":0.049959,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"06a4a75e28fe7ec70bbe9e200d5ff79b","spanId":"4c57954871049bf1","parentSpanId":"ad9337b6e4d91e84","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896473670375","endTimeUnixNano":"1779351896473712375","durationMs":0.042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"06a4a75e28fe7ec70bbe9e200d5ff79b","spanId":"5a0da5eb75911088","parentSpanId":"ad9337b6e4d91e84","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896473732792","endTimeUnixNano":"1779351896473772959","durationMs":0.040167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"06a4a75e28fe7ec70bbe9e200d5ff79b","spanId":"d1c13e8f6ecb7162","parentSpanId":"ad9337b6e4d91e84","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896473964959","endTimeUnixNano":"1779351896474064292","durationMs":0.099333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"06a4a75e28fe7ec70bbe9e200d5ff79b","spanId":"1fbd7013e467cf5e","parentSpanId":"ad9337b6e4d91e84","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896474088500","endTimeUnixNano":"1779351896474138959","durationMs":0.050459,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"06a4a75e28fe7ec70bbe9e200d5ff79b","spanId":"3281f7740fb2a382","parentSpanId":"ad9337b6e4d91e84","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896474157750","endTimeUnixNano":"1779351896474207542","durationMs":0.049792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"06a4a75e28fe7ec70bbe9e200d5ff79b","spanId":"72ac5365fcafa0be","parentSpanId":"ad9337b6e4d91e84","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896474226167","endTimeUnixNano":"1779351896474266667","durationMs":0.0405,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"06a4a75e28fe7ec70bbe9e200d5ff79b","spanId":"b8018cbf76bcf810","parentSpanId":"ad9337b6e4d91e84","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896474284584","endTimeUnixNano":"1779351896474323500","durationMs":0.038916,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"06a4a75e28fe7ec70bbe9e200d5ff79b","spanId":"8a15326d9be1a18d","parentSpanId":"ad9337b6e4d91e84","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896474341375","endTimeUnixNano":"1779351896474383125","durationMs":0.04175,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.resolvePath","traceId":"06a4a75e28fe7ec70bbe9e200d5ff79b","spanId":"ad9337b6e4d91e84","parentSpanId":"8bc7282601fd4b0a","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896451143500","endTimeUnixNano":"1779351896474855500","durationMs":23.712,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"http.server GET","traceId":"06a4a75e28fe7ec70bbe9e200d5ff79b","spanId":"8bc7282601fd4b0a","sampled":true,"kind":"server","startTimeUnixNano":"1779351896450814667","endTimeUnixNano":"1779351896475165000","durationMs":24.350333,"attributes":{"http.route":"/api/project-favicon","http.request.method":"GET","url.full":"http://127.0.0.1:14124/api/project-favicon?cwd=%2FUsers%2Fharrydawson","url.path":"/api/project-favicon","url.query":"cwd=%2FUsers%2Fharrydawson","url.scheme":"http","user_agent.original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"keep-alive","http.request.header.sec-ch-ua-platform":"\"macOS\"","http.request.header.user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.sec-ch-ua":"\"Not-A.Brand\";v=\"24\", \"Chromium\";v=\"146\"","http.request.header.sec-ch-ua-mobile":"?0","http.request.header.accept":"image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8","http.request.header.sec-fetch-site":"same-site","http.request.header.sec-fetch-mode":"no-cors","http.request.header.sec-fetch-dest":"image","http.request.header.referer":"http://127.0.0.1:6084/","http.request.header.accept-encoding":"gzip, deflate, br, zstd","http.request.header.accept-language":"en-GB","http.request.header.cookie":"","client.address":"127.0.0.1","http.response.status_code":200,"http.response.header.cache-control":"public, max-age=3600","http.response.header.content-type":"image/svg+xml","http.response.header.content-length":"306"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"c05c0fed6d09b22f","parentSpanId":"093cf33dc42dfaff","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896465277792","endTimeUnixNano":"1779351896490643875","durationMs":25.366083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"426b2501cf26b5d9","parentSpanId":"093cf33dc42dfaff","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896465198875","endTimeUnixNano":"1779351896490718042","durationMs":25.519167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"093cf33dc42dfaff","parentSpanId":"a7b1e3d0fd6bda5f","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896461588334","endTimeUnixNano":"1779351896490753417","durationMs":29.165083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProcess.run","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"a7b1e3d0fd6bda5f","parentSpanId":"b5c60472d691a9af","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896461558000","endTimeUnixNano":"1779351896490798917","durationMs":29.240917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"http.client GET","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"f42c770317bc4bb8","parentSpanId":"b5c60472d691a9af","sampled":true,"kind":"client","startTimeUnixNano":"1779351896461935834","endTimeUnixNano":"1779351896757248584","durationMs":295.31275,"attributes":{"http.request.method":"GET","server.address":"https://api.bitbucket.org","url.full":"https://api.bitbucket.org/2.0/user","url.path":"/2.0/user","url.scheme":"https","http.request.header.accept":"application/json","http.response.status_code":401,"http.response.header.age":"0","http.response.header.atl-request-id":"b8ad3b33-4cfc-41da-ba6e-7626ab78af04","http.response.header.atl-traceid":"b8ad3b334cfc41daba6e7626ab78af04","http.response.header.content-length":"0","http.response.header.content-type":"text/html; charset=utf-8","http.response.header.date":"Thu, 21 May 2026 08:24:56 GMT","http.response.header.nel":"{\"failure_fraction\": 0.01, \"include_subdomains\": true, \"max_age\": 600, \"report_to\": \"endpoint-1\"}","http.response.header.report-to":"{\"endpoints\": [{\"url\": \"https://dz8aopenkvv6s.cloudfront.net\"}], \"group\": \"endpoint-1\", \"include_subdomains\": true, \"max_age\": 600}","http.response.header.server":"AtlassianEdge","http.response.header.server-timing":"atl-edge;dur=255,atl-edge-internal;dur=11,atl-edge-upstream;dur=245,atl-edge-pop;desc=\"aws-ap-southeast-2\"","http.response.header.strict-transport-security":"max-age=63072000; includeSubDomains; preload","http.response.header.vary":"Authorization, origin","http.response.header.www-authenticate":"BitbucketCustom realm=Bitbucket.org HTTP","http.response.header.x-accepted-oauth-scopes":"account","http.response.header.x-asap-succeeded":"True","http.response.header.x-b3-spanid":"250693102f491b4a","http.response.header.x-b3-traceid":"b8ad3b334cfc41daba6e7626ab78af04","http.response.header.x-cache":"MISS","http.response.header.x-content-type-options":"nosniff","http.response.header.x-credential-type":"unauthenticated_identity","http.response.header.x-dc-location":"Micros-3","http.response.header.x-envoy-attempt-count":"1","http.response.header.x-frame-options":"SAMEORIGIN","http.response.header.x-ratelimit-limit":"60, 60;w=3600","http.response.header.x-ratelimit-remaining":"59","http.response.header.x-ratelimit-reset":"2104","http.response.header.x-render-time":"0.021967411041259766","http.response.header.x-request-count":"2990","http.response.header.x-served-by":"cca95c2b2829","http.response.header.x-static-version":"51d05f3ab3e8","http.response.header.x-usage-input-ops":"0","http.response.header.x-usage-output-ops":"0","http.response.header.x-usage-system-time":"0.000403","http.response.header.x-usage-user-time":"0.025637","http.response.header.x-used-mesh":"False","http.response.header.x-version":"51d05f3ab3e8","http.response.header.x-view-name":"bitbucket.apps.bb.api.v20.handlers.CurrentUserHandler","http.response.header.x-xss-protection":"1; mode=block"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"a797d442e122007944b2c9bf77fdcc5a","spanId":"e18402764db0103d","parentSpanId":"5b6aa52b54e209bb","sampled":true,"kind":"client","startTimeUnixNano":"1779351896801539959","endTimeUnixNano":"1779351896801594917","durationMs":0.054958,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n session_id AS \"sessionId\",\n subject AS \"subject\",\n role AS \"role\",\n method AS \"method\",\n client_label AS \"clientLabel\",\n client_ip_address AS \"clientIpAddress\",\n client_user_agent AS \"clientUserAgent\",\n client_device_type AS \"clientDeviceType\",\n client_os AS \"clientOs\",\n client_browser AS \"clientBrowser\",\n issued_at AS \"issuedAt\",\n expires_at AS \"expiresAt\",\n last_connected_at AS \"lastConnectedAt\",\n revoked_at AS \"revokedAt\"\n FROM auth_sessions\n WHERE session_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"otlp-span","name":"RpcClient.orchestration.dispatchCommand","traceId":"c7303beda978da770002cc82bb27320f","spanId":"f90f2f9b56c2e38c","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896294900000","endTimeUnixNano":"1779351896319900000","durationMs":25,"attributes":{},"resourceAttributes":{"service.runtime":"t3-web","service.mode":"electron","service.name":"t3-web","service.version":"0.0.24"},"scope":{"name":"t3-web","attributes":{}},"events":[],"links":[],"status":{"code":"1"}} -{"type":"otlp-span","name":"RpcClient.vcs.listRefs","traceId":"0a461d4fa3bda6ae600f9646fdcf4fd7","spanId":"7af0ba3c8ec26945","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896448300000","endTimeUnixNano":"1779351896482700000","durationMs":34.4,"attributes":{},"resourceAttributes":{"service.runtime":"t3-web","service.mode":"electron","service.name":"t3-web","service.version":"0.0.24"},"scope":{"name":"t3-web","attributes":{}},"events":[],"links":[],"status":{"code":"1"}} -{"type":"effect-span","name":"http.server POST","traceId":"a797d442e122007944b2c9bf77fdcc5a","spanId":"5b6aa52b54e209bb","sampled":true,"kind":"server","startTimeUnixNano":"1779351896801369084","endTimeUnixNano":"1779351896801809209","durationMs":0.440125,"attributes":{"http.route":"/api/observability/v1/traces","http.request.method":"POST","url.full":"http://127.0.0.1:14124/api/observability/v1/traces","url.path":"/api/observability/v1/traces","url.scheme":"http","user_agent.original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"close","http.request.header.content-length":"1036","http.request.header.sec-ch-ua-platform":"\"macOS\"","http.request.header.user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.sec-ch-ua":"\"Not-A.Brand\";v=\"24\", \"Chromium\";v=\"146\"","http.request.header.content-type":"application/json","http.request.header.sec-ch-ua-mobile":"?0","http.request.header.accept":"*/*","http.request.header.origin":"http://127.0.0.1:6084","http.request.header.sec-fetch-site":"same-origin","http.request.header.sec-fetch-mode":"cors","http.request.header.sec-fetch-dest":"empty","http.request.header.referer":"http://127.0.0.1:6084/","http.request.header.accept-encoding":"gzip, deflate, br, zstd","http.request.header.accept-language":"en-GB","http.request.header.cookie":"","http.response.status_code":204},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"aacf0f6b9603a7af","parentSpanId":"d5b4de7f7eb4c5ce","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896492004875","endTimeUnixNano":"1779351896873376834","durationMs":381.371959,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"44e1659fb41a71fe","parentSpanId":"d5b4de7f7eb4c5ce","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896491970584","endTimeUnixNano":"1779351896873440917","durationMs":381.470333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"d5b4de7f7eb4c5ce","parentSpanId":"c199afdd26b6ffec","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896490870084","endTimeUnixNano":"1779351896873478792","durationMs":382.608708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProcess.run","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"c199afdd26b6ffec","parentSpanId":"b5c60472d691a9af","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896490834500","endTimeUnixNano":"1779351896873533875","durationMs":382.699375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.server.discoverSourceControl","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"b5c60472d691a9af","parentSpanId":"eb7a24ce917240d8","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896447467417","endTimeUnixNano":"1779351896873700334","durationMs":426.232917,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"server.discoverSourceControl","rpc.aggregate":"server"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"adfd096e4266bc2b","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351897161176209","endTimeUnixNano":"1779351897219054875","durationMs":57.878666,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"15d9ac3cc41e84decff67da43068d6d7","spanId":"b79473ddfb25630c","parentSpanId":"009fa65c91604cd4","sampled":true,"kind":"client","startTimeUnixNano":"1779351897810316042","endTimeUnixNano":"1779351897810500875","durationMs":0.184833,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n session_id AS \"sessionId\",\n subject AS \"subject\",\n role AS \"role\",\n method AS \"method\",\n client_label AS \"clientLabel\",\n client_ip_address AS \"clientIpAddress\",\n client_user_agent AS \"clientUserAgent\",\n client_device_type AS \"clientDeviceType\",\n client_os AS \"clientOs\",\n client_browser AS \"clientBrowser\",\n issued_at AS \"issuedAt\",\n expires_at AS \"expiresAt\",\n last_connected_at AS \"lastConnectedAt\",\n revoked_at AS \"revokedAt\"\n FROM auth_sessions\n WHERE session_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"otlp-span","name":"RpcClient.server.discoverSourceControl","traceId":"9285e899a53ffa8b7b17d0ef9088ddd4","spanId":"573cdcae9e5168e5","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896447400000","endTimeUnixNano":"1779351896874600000","durationMs":427.2,"attributes":{},"resourceAttributes":{"service.runtime":"t3-web","service.mode":"electron","service.name":"t3-web","service.version":"0.0.24"},"scope":{"name":"t3-web","attributes":{}},"events":[],"links":[],"status":{"code":"1"}} -{"type":"effect-span","name":"http.server POST","traceId":"15d9ac3cc41e84decff67da43068d6d7","spanId":"009fa65c91604cd4","sampled":true,"kind":"server","startTimeUnixNano":"1779351897809716084","endTimeUnixNano":"1779351897811303917","durationMs":1.587833,"attributes":{"http.route":"/api/observability/v1/traces","http.request.method":"POST","url.full":"http://127.0.0.1:14124/api/observability/v1/traces","url.path":"/api/observability/v1/traces","url.scheme":"http","user_agent.original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"close","http.request.header.content-length":"706","http.request.header.sec-ch-ua-platform":"\"macOS\"","http.request.header.user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.sec-ch-ua":"\"Not-A.Brand\";v=\"24\", \"Chromium\";v=\"146\"","http.request.header.content-type":"application/json","http.request.header.sec-ch-ua-mobile":"?0","http.request.header.accept":"*/*","http.request.header.origin":"http://127.0.0.1:6084","http.request.header.sec-fetch-site":"same-origin","http.request.header.sec-fetch-mode":"cors","http.request.header.sec-fetch-dest":"empty","http.request.header.referer":"http://127.0.0.1:6084/","http.request.header.accept-encoding":"gzip, deflate, br, zstd","http.request.header.accept-language":"en-GB","http.request.header.cookie":"","http.response.status_code":204},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"a6fbea1b1c092f35","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351902221657042","endTimeUnixNano":"1779351902278834792","durationMs":57.17775,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"64943b7a8077c4a8","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351907279830584","endTimeUnixNano":"1779351907337388792","durationMs":57.558208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"343e0ad94f786b44","parentSpanId":"eb7a24ce917240d8","sampled":true,"kind":"client","startTimeUnixNano":"1779351912234373292","endTimeUnixNano":"1779351912234468792","durationMs":0.0955,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n session_id AS \"sessionId\",\n subject AS \"subject\",\n role AS \"role\",\n method AS \"method\",\n client_label AS \"clientLabel\",\n client_ip_address AS \"clientIpAddress\",\n client_user_agent AS \"clientUserAgent\",\n client_device_type AS \"clientDeviceType\",\n client_os AS \"clientOs\",\n client_browser AS \"clientBrowser\",\n issued_at AS \"issuedAt\",\n expires_at AS \"expiresAt\",\n last_connected_at AS \"lastConnectedAt\",\n revoked_at AS \"revokedAt\"\n FROM auth_sessions\n WHERE session_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.orchestration.subscribeShell","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"a924f711f34aec51","parentSpanId":"eb7a24ce917240d8","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731818325584","endTimeUnixNano":"1779351912235331834","durationMs":180417.00625,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"orchestration.subscribeShell","rpc.aggregate":"orchestration"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.subscribeTerminalEvents","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"4980392a57efe91d","parentSpanId":"eb7a24ce917240d8","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731819759584","endTimeUnixNano":"1779351912236502459","durationMs":180416.742875,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"subscribeTerminalEvents","rpc.aggregate":"terminal"},"events":[],"links":[],"exit":{"_tag":"Interrupted","cause":"InterruptError: All fibers interrupted without error {\n [cause]: InterruptCause: The fiber was interrupted by:\n at fiber (#370)\n}"}} -{"type":"effect-span","name":"ws.rpc.subscribeServerLifecycle","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"9c8c2c353b6f6489","parentSpanId":"eb7a24ce917240d8","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731830544292","endTimeUnixNano":"1779351912236934459","durationMs":180406.390167,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"subscribeServerLifecycle","rpc.aggregate":"server"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.subscribeServerConfig","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"d3454221c9fe9083","parentSpanId":"eb7a24ce917240d8","sampled":true,"kind":"internal","startTimeUnixNano":"1779351731833626584","endTimeUnixNano":"1779351912237469000","durationMs":180403.842416,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"subscribeServerConfig","rpc.aggregate":"server"},"events":[],"links":[],"exit":{"_tag":"Interrupted","cause":"InterruptError: All fibers interrupted without error {\n [cause]: InterruptCause: The fiber was interrupted by:\n at fiber (#370)\n}"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.releaseRemotePoller","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"8bc66c6994fd9804","parentSpanId":"2f47d784f13b08ef","sampled":true,"kind":"internal","startTimeUnixNano":"1779351912237688709","endTimeUnixNano":"1779351912237834042","durationMs":0.145333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.subscribeVcsStatus","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"2f47d784f13b08ef","parentSpanId":"eb7a24ce917240d8","sampled":true,"kind":"internal","startTimeUnixNano":"1779351896450217959","endTimeUnixNano":"1779351912237904250","durationMs":15787.686291,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"subscribeVcsStatus","rpc.aggregate":"vcs"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"http.server GET","traceId":"4c0bb07d55604c979f8fd015146be547","spanId":"eb7a24ce917240d8","sampled":true,"kind":"server","startTimeUnixNano":"1779351731807761292","endTimeUnixNano":"1779351912234734375","durationMs":180426.973083,"attributes":{"http.route":"/ws","http.request.method":"GET","url.full":"http://127.0.0.1:14124/ws","url.path":"/ws","url.scheme":"http","user_agent.original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"Upgrade","http.request.header.pragma":"no-cache","http.request.header.cache-control":"no-cache","http.request.header.user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.upgrade":"websocket","http.request.header.origin":"http://127.0.0.1:6084","http.request.header.sec-websocket-version":"13","http.request.header.accept-encoding":"gzip, deflate, br, zstd","http.request.header.accept-language":"en-GB","http.request.header.cookie":"","http.request.header.sec-websocket-key":"h+jrTgDYh3EWaoI8M4TNXQ==","http.request.header.sec-websocket-extensions":"permessage-deflate; client_max_window_bits","http.response.status_code":204},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"e3156fe92f6a34b6","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351912338554209","endTimeUnixNano":"1779351912383036084","durationMs":44.481875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"c8ccf01dcdf2355e","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351917385190750","endTimeUnixNano":"1779351917443413334","durationMs":58.222584,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"58c77e5adaeea9f5","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351922445499500","endTimeUnixNano":"1779351922504079209","durationMs":58.579709,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"24b45a84103f807a","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351927506201417","endTimeUnixNano":"1779351927566475584","durationMs":60.274167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"4ef02dfe577e90b8","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351932567871625","endTimeUnixNano":"1779351932626652667","durationMs":58.781042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"be0582ac2f096292","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351937628185959","endTimeUnixNano":"1779351937685937209","durationMs":57.75125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"69340e136a0239bf","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351942687442292","endTimeUnixNano":"1779351942749178709","durationMs":61.736417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"2e930c4b3d51c661","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351947751597000","endTimeUnixNano":"1779351947809719542","durationMs":58.122542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"327d8749ae651d65","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351952810555125","endTimeUnixNano":"1779351952852004459","durationMs":41.449334,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"5cb90499677250a5","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351957852833375","endTimeUnixNano":"1779351957913128000","durationMs":60.294625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"dd5e51f68be6607a","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351962915261000","endTimeUnixNano":"1779351962973567750","durationMs":58.30675,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"f1b60e9f0a5909dc","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351967975765167","endTimeUnixNano":"1779351968034507375","durationMs":58.742208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"b8f563174fc042ea","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351973036744000","endTimeUnixNano":"1779351973096855167","durationMs":60.111167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"70af424646e55303","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351978097773750","endTimeUnixNano":"1779351978157741584","durationMs":59.967834,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"f58056836842eea1","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351983159449709","endTimeUnixNano":"1779351983199199542","durationMs":39.749833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"7201382323f54733","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351988201431292","endTimeUnixNano":"1779351988260641042","durationMs":59.20975,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"8ddaefcf296c7de4","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351993261457334","endTimeUnixNano":"1779351993318451542","durationMs":56.994208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"35be9449eebc58c6","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779351998319509584","endTimeUnixNano":"1779351998357720709","durationMs":38.211125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"a0840b2c4726b080","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352003358619917","endTimeUnixNano":"1779352003416186750","durationMs":57.566833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"df255443316f2898","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352008418157917","endTimeUnixNano":"1779352008476955250","durationMs":58.797333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"2b5bdb7b3edc19e4","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352013478831125","endTimeUnixNano":"1779352013514728667","durationMs":35.897542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"c3b6766d59fe7d27","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352018516005000","endTimeUnixNano":"1779352018573472667","durationMs":57.467667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeClaudeEnvironment","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"60e8fe0cb81135ad","parentSpanId":"d663ad2b82886b4e","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020228266959","endTimeUnixNano":"1779352020228296834","durationMs":0.029875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runClaudeCommand","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"d663ad2b82886b4e","parentSpanId":"8ed0cb60e06b8185","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020228228334","endTimeUnixNano":"1779352020231316334","durationMs":3.088,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"PlatformError: NotFound: ChildProcess.spawn (claude --version)\n at Module.systemError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/PlatformError.js:59:39)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/internal/utils.js:28:24\n at toPlatformError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:25:54)\n at ChildProcess. (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:230:26)\n at ChildProcess.emit (node:events:509:28)\n at ChildProcess._handle.onexit (node:internal/child_process:293:12)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n at runClaudeCommand (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:27894:30)\n at runClaudeCommand (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:27870:33)\n at checkClaudeProviderStatus (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30400:25)\n at checkClaudeProviderStatus (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:27878:42)\n at applySnapshot (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30277:83)\n at applySnapshot (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30257:35)\n at refreshSnapshot (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30282:102)\n at refreshSnapshot (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30278:33)\n at makeManagedServerProvider (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30401:27)\n at makeManagedServerProvider (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30222:42) {\n [cause]: Error: spawn claude ENOENT\n at ChildProcess._handle.onexit (node:internal/child_process:287:19)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n}"}} -{"type":"effect-span","name":"checkClaudeProviderStatus","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"8ed0cb60e06b8185","parentSpanId":"9fc401beb2583709","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020228140334","endTimeUnixNano":"1779352020231704834","durationMs":3.5645,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"e8f04a54db4081e81cea85f3a410173d","spanId":"8512a77df6fda04c","parentSpanId":"5f44491235f036d3","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020231917667","endTimeUnixNano":"1779352020231937292","durationMs":0.019625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"e8f04a54db4081e81cea85f3a410173d","spanId":"40001fc44857114b","parentSpanId":"5f44491235f036d3","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020232077750","endTimeUnixNano":"1779352020232102917","durationMs":0.025167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"28818cbab2f9ee25","parentSpanId":"9fc401beb2583709","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020232265750","endTimeUnixNano":"1779352020232338459","durationMs":0.072709,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"9fc401beb2583709","parentSpanId":"8883eedea17fe5ca","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020228101542","endTimeUnixNano":"1779352020232350625","durationMs":4.249083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"8883eedea17fe5ca","parentSpanId":"d8882d30663dbbb0","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020228049000","endTimeUnixNano":"1779352020232365792","durationMs":4.316792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeCodexAppServerPatchedProtocol","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"d7d9fa663ebf215e","parentSpanId":"29a60967aa49f79f","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020233767250","endTimeUnixNano":"1779352020233902709","durationMs":0.135459,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"effect-codex-app-server/CodexAppServerClient.make","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"29a60967aa49f79f","parentSpanId":"2eb05c82955b998c","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020233709917","endTimeUnixNano":"1779352020233937792","durationMs":0.227875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"666b58c52d665341","parentSpanId":"28818cbab2f9ee25","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020235112667","endTimeUnixNano":"1779352020235161250","durationMs":0.048583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"08b5f66e6835c2e5","parentSpanId":"28818cbab2f9ee25","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020235195417","endTimeUnixNano":"1779352020235271875","durationMs":0.076458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"checkCursorProviderStatus","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"c76de60f97471f9d","parentSpanId":"616da621fc827067","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020235661084","endTimeUnixNano":"1779352020235730667","durationMs":0.069583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"dea41e6abb425141b2808d0504d6f376","spanId":"587d9a31cf1661c1","parentSpanId":"d650e2fdbfb562d7","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020235855584","endTimeUnixNano":"1779352020235870667","durationMs":0.015083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"dea41e6abb425141b2808d0504d6f376","spanId":"dcb3c76912476eed","parentSpanId":"d650e2fdbfb562d7","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020235969334","endTimeUnixNano":"1779352020236037292","durationMs":0.067958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"b157aa2f144299e9","parentSpanId":"616da621fc827067","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020236149875","endTimeUnixNano":"1779352020236216042","durationMs":0.066167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"616da621fc827067","parentSpanId":"9b8aa5eccbc9eecd","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020235637459","endTimeUnixNano":"1779352020236226792","durationMs":0.589333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"9b8aa5eccbc9eecd","parentSpanId":"f4270506fde844da","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020235601792","endTimeUnixNano":"1779352020236247834","durationMs":0.646042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"56899a111055d2f9","parentSpanId":"b157aa2f144299e9","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020238714875","endTimeUnixNano":"1779352020238746084","durationMs":0.031209,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"5beab7c9c3e591f9","parentSpanId":"b157aa2f144299e9","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020238791959","endTimeUnixNano":"1779352020238844542","durationMs":0.052583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"dea41e6abb425141b2808d0504d6f376","spanId":"d650e2fdbfb562d7","parentSpanId":"6f6112066e9d9fa9","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020235808125","endTimeUnixNano":"1779352020240360459","durationMs":4.552334,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"dea41e6abb425141b2808d0504d6f376","spanId":"6f6112066e9d9fa9","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020235784917","endTimeUnixNano":"1779352020240386500","durationMs":4.601583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"9196e0f6cf32f5711409681822681407","spanId":"ed9211ac165134f1","parentSpanId":"43724bad925f5002","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020240497292","endTimeUnixNano":"1779352020240513292","durationMs":0.016,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"9196e0f6cf32f5711409681822681407","spanId":"26444590cac40b5b","parentSpanId":"43724bad925f5002","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020240600000","endTimeUnixNano":"1779352020240616542","durationMs":0.016542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"e8f04a54db4081e81cea85f3a410173d","spanId":"5f44491235f036d3","parentSpanId":"63c49dc745061e61","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020231861709","endTimeUnixNano":"1779352020240707792","durationMs":8.846083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"e8f04a54db4081e81cea85f3a410173d","spanId":"63c49dc745061e61","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020231825584","endTimeUnixNano":"1779352020240720042","durationMs":8.894458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"becf08d7ca93b01da755ad092f23b9cb","spanId":"122c3b8a4299ec22","parentSpanId":"53cb57b5f111ecbf","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020240777917","endTimeUnixNano":"1779352020240789542","durationMs":0.011625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"becf08d7ca93b01da755ad092f23b9cb","spanId":"07e8c1bc10b9658b","parentSpanId":"53cb57b5f111ecbf","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020240840667","endTimeUnixNano":"1779352020240853459","durationMs":0.012792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"9196e0f6cf32f5711409681822681407","spanId":"43724bad925f5002","parentSpanId":"70ef8c5328532db5","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020240469959","endTimeUnixNano":"1779352020242159792","durationMs":1.689833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"9196e0f6cf32f5711409681822681407","spanId":"70ef8c5328532db5","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020240444000","endTimeUnixNano":"1779352020242177834","durationMs":1.733834,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"becf08d7ca93b01da755ad092f23b9cb","spanId":"53cb57b5f111ecbf","parentSpanId":"82b21c7b2594a256","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020240760209","endTimeUnixNano":"1779352020242217875","durationMs":1.457666,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"becf08d7ca93b01da755ad092f23b9cb","spanId":"82b21c7b2594a256","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020240743250","endTimeUnixNano":"1779352020242227709","durationMs":1.484459,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"requestAllCodexModels","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"848e17ebe2dcef51","parentSpanId":"2eb05c82955b998c","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020274355042","endTimeUnixNano":"1779352020275896917","durationMs":1.541875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"probeCodexAppServerProvider","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"2eb05c82955b998c","parentSpanId":"e60e41babf14e21a","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020227277709","endTimeUnixNano":"1779352020311013500","durationMs":83.735791,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"checkCodexProviderStatus","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"e60e41babf14e21a","parentSpanId":"ebd26b885a14b557","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020226992209","endTimeUnixNano":"1779352020312394459","durationMs":85.40225,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"38d2488e60198e19ed0e781cad81b74b","spanId":"9c6d8b45802af002","parentSpanId":"68968d30db6a6d07","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020312475125","endTimeUnixNano":"1779352020312481625","durationMs":0.0065,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"38d2488e60198e19ed0e781cad81b74b","spanId":"d2d704582cf8834e","parentSpanId":"68968d30db6a6d07","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020312589125","endTimeUnixNano":"1779352020312599834","durationMs":0.010709,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"eefdc53610e7b623","parentSpanId":"ebd26b885a14b557","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020312682792","endTimeUnixNano":"1779352020312706000","durationMs":0.023208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"ebd26b885a14b557","parentSpanId":"807eac14b0103a83","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020226930834","endTimeUnixNano":"1779352020312710084","durationMs":85.77925,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"807eac14b0103a83","parentSpanId":"5bc4cdb3beb605ab","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020226785292","endTimeUnixNano":"1779352020312714584","durationMs":85.929292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveLatestProviderVersion","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"2fd728a31b991c2d","parentSpanId":"fb9f1025fa3dd7a1","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020312739792","endTimeUnixNano":"1779352020312751417","durationMs":0.011625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"fb9f1025fa3dd7a1","parentSpanId":"eefdc53610e7b623","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020312728917","endTimeUnixNano":"1779352020312779375","durationMs":0.050458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"381a077e97225483","parentSpanId":"eefdc53610e7b623","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020312785542","endTimeUnixNano":"1779352020312804625","durationMs":0.019083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"38d2488e60198e19ed0e781cad81b74b","spanId":"68968d30db6a6d07","parentSpanId":"86eae8be399231c3","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020312462125","endTimeUnixNano":"1779352020313258334","durationMs":0.796209,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"38d2488e60198e19ed0e781cad81b74b","spanId":"86eae8be399231c3","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020312446750","endTimeUnixNano":"1779352020313262042","durationMs":0.815292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"d92355ee7d106cc54d35626b22dbba56","spanId":"7774915297429b01","parentSpanId":"827e9e7689d75120","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020313294750","endTimeUnixNano":"1779352020313303875","durationMs":0.009125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"d92355ee7d106cc54d35626b22dbba56","spanId":"4cd7376813fb00f4","parentSpanId":"827e9e7689d75120","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020313328000","endTimeUnixNano":"1779352020313332459","durationMs":0.004459,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"d92355ee7d106cc54d35626b22dbba56","spanId":"827e9e7689d75120","parentSpanId":"769bd227dc33d0f1","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020313285459","endTimeUnixNano":"1779352020313747625","durationMs":0.462166,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"d92355ee7d106cc54d35626b22dbba56","spanId":"769bd227dc33d0f1","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020313278792","endTimeUnixNano":"1779352020313753959","durationMs":0.475167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"opencode.app.agents","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"53ba4445fcdb20b0","parentSpanId":"be1b09187cf151a1","sampled":true,"kind":"internal","startTimeUnixNano":"1779352021037643125","endTimeUnixNano":"1779352021248954625","durationMs":211.3115,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"opencode.provider.list","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"ee5d8fdbbdcb3a17","parentSpanId":"be1b09187cf151a1","sampled":true,"kind":"internal","startTimeUnixNano":"1779352021037571500","endTimeUnixNano":"1779352021364568542","durationMs":326.997042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"checkOpenCodeProviderStatus","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"be1b09187cf151a1","parentSpanId":"141ba69bc8240f1b","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020236325292","endTimeUnixNano":"1779352022368421792","durationMs":2132.0965,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"3ea5ded8bf8fc8cb3ee006672963f1b9","spanId":"0987d8ad2299f132","parentSpanId":"f51347bbbc7ddd60","sampled":true,"kind":"internal","startTimeUnixNano":"1779352022368884917","endTimeUnixNano":"1779352022368926625","durationMs":0.041708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"3ea5ded8bf8fc8cb3ee006672963f1b9","spanId":"67bd3673ad9a15f2","parentSpanId":"f51347bbbc7ddd60","sampled":true,"kind":"internal","startTimeUnixNano":"1779352022370939625","endTimeUnixNano":"1779352022370974084","durationMs":0.034459,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"ff316b831845ec9e","parentSpanId":"141ba69bc8240f1b","sampled":true,"kind":"internal","startTimeUnixNano":"1779352022371641542","endTimeUnixNano":"1779352022371751042","durationMs":0.1095,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"141ba69bc8240f1b","parentSpanId":"1cf557d2aaa10894","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020236303000","endTimeUnixNano":"1779352022371771917","durationMs":2135.468917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"1cf557d2aaa10894","parentSpanId":"2f989ef1cbf60c79","sampled":true,"kind":"internal","startTimeUnixNano":"1779352020236279084","endTimeUnixNano":"1779352022371807417","durationMs":2135.528333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveLatestProviderVersion","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"80344b3bedb8e239","parentSpanId":"839ecd4069acd7c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352022371901834","endTimeUnixNano":"1779352022371944959","durationMs":0.043125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"839ecd4069acd7c4","parentSpanId":"ff316b831845ec9e","sampled":true,"kind":"internal","startTimeUnixNano":"1779352022371867000","endTimeUnixNano":"1779352022372038709","durationMs":0.171709,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"d68bfc34102b0b13","parentSpanId":"ff316b831845ec9e","sampled":true,"kind":"internal","startTimeUnixNano":"1779352022372064417","endTimeUnixNano":"1779352022372153834","durationMs":0.089417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"3ea5ded8bf8fc8cb3ee006672963f1b9","spanId":"f51347bbbc7ddd60","parentSpanId":"3680c195c7903109","sampled":true,"kind":"internal","startTimeUnixNano":"1779352022368794959","endTimeUnixNano":"1779352022374029917","durationMs":5.234958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"3ea5ded8bf8fc8cb3ee006672963f1b9","spanId":"3680c195c7903109","sampled":true,"kind":"internal","startTimeUnixNano":"1779352022368708042","endTimeUnixNano":"1779352022374055334","durationMs":5.347292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"e2ddcef1a72726d7eab68e49223895bf","spanId":"f3db124af5e6cf4d","parentSpanId":"cca680a278bd0cfd","sampled":true,"kind":"internal","startTimeUnixNano":"1779352022374198834","endTimeUnixNano":"1779352022374219709","durationMs":0.020875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"e2ddcef1a72726d7eab68e49223895bf","spanId":"d23407b50ed069f8","parentSpanId":"cca680a278bd0cfd","sampled":true,"kind":"internal","startTimeUnixNano":"1779352022374366000","endTimeUnixNano":"1779352022374389792","durationMs":0.023792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"e2ddcef1a72726d7eab68e49223895bf","spanId":"cca680a278bd0cfd","parentSpanId":"ead8c88d4face0da","sampled":true,"kind":"internal","startTimeUnixNano":"1779352022374151042","endTimeUnixNano":"1779352022376022334","durationMs":1.871292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"e2ddcef1a72726d7eab68e49223895bf","spanId":"ead8c88d4face0da","sampled":true,"kind":"internal","startTimeUnixNano":"1779352022374121834","endTimeUnixNano":"1779352022376042084","durationMs":1.92025,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"685939c304acf6e4","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352023573960792","endTimeUnixNano":"1779352023632279917","durationMs":58.319125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"9c222a79013464bbed30efe9f66a4107","spanId":"ecfa836823767c98","parentSpanId":"bdaa4ceb2b2577ba","sampled":true,"kind":"client","startTimeUnixNano":"1779352024774541792","endTimeUnixNano":"1779352024774841125","durationMs":0.299333,"attributes":{"server.mode":"desktop","server.port":14124,"server.host":"127.0.0.1","startup.phase":"reactors.start","db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n thread_id AS \"threadId\",\n provider_name AS \"providerName\",\n provider_instance_id AS \"providerInstanceId\",\n adapter_key AS \"adapterKey\",\n runtime_mode AS \"runtimeMode\",\n status,\n last_seen_at AS \"lastSeenAt\",\n resume_cursor_json AS \"resumeCursor\",\n runtime_payload_json AS \"runtimePayload\"\n FROM provider_session_runtime\n ORDER BY last_seen_at ASC, thread_id ASC\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"e79470b7a4c4a3ea","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352028633002000","endTimeUnixNano":"1779352028691194750","durationMs":58.19275,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"b6e459154178c4d1","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352033693479334","endTimeUnixNano":"1779352033751585500","durationMs":58.106166,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"4c04b3dc575c816b","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352038751819500","endTimeUnixNano":"1779352038808470250","durationMs":56.65075,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"c068f054ee938c65","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352043809244375","endTimeUnixNano":"1779352043866739250","durationMs":57.494875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"018f49808a95d4e8","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352048868408459","endTimeUnixNano":"1779352048928518292","durationMs":60.109833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"7188bf5204469b62","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352053929997542","endTimeUnixNano":"1779352053989360084","durationMs":59.362542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"f1f0bcdc548e04c5","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352058991258167","endTimeUnixNano":"1779352059050673292","durationMs":59.415125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"7a8bfccd362addc6","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352064051863375","endTimeUnixNano":"1779352064112549834","durationMs":60.686459,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"9f2a7d6133a8c3e1","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352069113262459","endTimeUnixNano":"1779352069170145500","durationMs":56.883041,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"d74cefd8763422c2","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352074172543417","endTimeUnixNano":"1779352074229131959","durationMs":56.588542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"fada52472063a12c","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352079231279750","endTimeUnixNano":"1779352079291137209","durationMs":59.857459,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"76f4abd7d556e1c5","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352084293376834","endTimeUnixNano":"1779352084352875417","durationMs":59.498583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"d85925a32f21a670","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352089353833542","endTimeUnixNano":"1779352089413948375","durationMs":60.114833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"885a10952b9814c1","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352094415564709","endTimeUnixNano":"1779352094473909042","durationMs":58.344333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"068ddbda7c2f69eb","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352099475291750","endTimeUnixNano":"1779352099533923834","durationMs":58.632084,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"1f86c10811fc7b3f","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352104534538125","endTimeUnixNano":"1779352104591382792","durationMs":56.844667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"7df1cc00118bbffe","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352109593695125","endTimeUnixNano":"1779352109655516209","durationMs":61.821084,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"cbd10165d81ef852","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352114656822375","endTimeUnixNano":"1779352114716025584","durationMs":59.203209,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"b0315d211550753d","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352119718747917","endTimeUnixNano":"1779352119778033000","durationMs":59.285083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"1ebbdb39a235c9b2","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352124780262709","endTimeUnixNano":"1779352124839130709","durationMs":58.868,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"c376d12b7b2fcdb0","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352129840438834","endTimeUnixNano":"1779352129898673667","durationMs":58.234833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"805f37596b5967e5","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352134899964709","endTimeUnixNano":"1779352134957478084","durationMs":57.513375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"a5522107c48050e4","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352139958908375","endTimeUnixNano":"1779352140014163250","durationMs":55.254875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"3007e2872592c549","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352145016743500","endTimeUnixNano":"1779352145077092084","durationMs":60.348584,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"cbf7624bee6d6bfb","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352150079593834","endTimeUnixNano":"1779352150137959209","durationMs":58.365375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"0e31e683f7cab193","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352155140379250","endTimeUnixNano":"1779352155199245334","durationMs":58.866084,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"0bfd2ad6f955b36c","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352160200201917","endTimeUnixNano":"1779352160225886042","durationMs":25.684125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"5349f6f8be2df0c9","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352165227055625","endTimeUnixNano":"1779352165285605000","durationMs":58.549375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"d94c529ac93a0bee","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352170287131625","endTimeUnixNano":"1779352170347751792","durationMs":60.620167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"88d93b00774afcb1","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352175350351042","endTimeUnixNano":"1779352175407258834","durationMs":56.907792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"ae14b184cfea1c05","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352180409102334","endTimeUnixNano":"1779352180467097000","durationMs":57.994666,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"8b6fc078eb47d6bb","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352185469326667","endTimeUnixNano":"1779352185502625750","durationMs":33.299083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"7188bb4e2107c5f1","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352190504632250","endTimeUnixNano":"1779352190565791084","durationMs":61.158834,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"785fe6ae1313aeaa","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352195566461584","endTimeUnixNano":"1779352195627662042","durationMs":61.200458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"07d478d1b33d3808","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352200628424459","endTimeUnixNano":"1779352200687380334","durationMs":58.955875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"7865500cc913900b","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352205689391167","endTimeUnixNano":"1779352205746504750","durationMs":57.113583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"bd64e351b1c195c5","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352210747946667","endTimeUnixNano":"1779352210806668584","durationMs":58.721917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"952c6460cdeed6d2","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352215809709250","endTimeUnixNano":"1779352215869409042","durationMs":59.699792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"81a0451e55cd7f68","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352220872160000","endTimeUnixNano":"1779352220928804875","durationMs":56.644875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"0c140d1752c0a994","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352225929778042","endTimeUnixNano":"1779352225987217125","durationMs":57.439083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"5bcda57cba338d40","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352230990654917","endTimeUnixNano":"1779352231047097125","durationMs":56.442208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"c3f0904bf1678547","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352236049859875","endTimeUnixNano":"1779352236107097250","durationMs":57.237375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"b04905304ffd736c","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352241108737834","endTimeUnixNano":"1779352241166426709","durationMs":57.688875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"ffe4a433aa56b273","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352246167915709","endTimeUnixNano":"1779352246222721667","durationMs":54.805958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"04be54e1b2209bad","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352251224659959","endTimeUnixNano":"1779352251285911125","durationMs":61.251166,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"94963c46a97d10e1","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352256288955792","endTimeUnixNano":"1779352256343356917","durationMs":54.401125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"403bf826e5cd5f8a","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352261344527875","endTimeUnixNano":"1779352261402652584","durationMs":58.124709,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"d3efa07cb36b80ca","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352266404997917","endTimeUnixNano":"1779352266462155125","durationMs":57.157208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"dbe1cf0de9a269bb","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352271465620917","endTimeUnixNano":"1779352271522632209","durationMs":57.011292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"93d4909051483bff","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352276525552625","endTimeUnixNano":"1779352276581885584","durationMs":56.332959,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"e955a25c88d441a1","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352281584214792","endTimeUnixNano":"1779352281642599584","durationMs":58.384792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"fb6a522a9bcbaaa7","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352286645698792","endTimeUnixNano":"1779352286704522417","durationMs":58.823625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"7ee92e1b7c34e23e","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352291707041000","endTimeUnixNano":"1779352291764658625","durationMs":57.617625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"79d013c5763c757a","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352296766666125","endTimeUnixNano":"1779352296824355542","durationMs":57.689417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"3c4bf641e8e761e0","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352301826401250","endTimeUnixNano":"1779352301886341584","durationMs":59.940334,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"284210930ad26893","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352306888939667","endTimeUnixNano":"1779352306946235167","durationMs":57.2955,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"17a7e0446e4d8429","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352311947657625","endTimeUnixNano":"1779352312004688334","durationMs":57.030709,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"b75cecfbc73ccdfb","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352317007656459","endTimeUnixNano":"1779352317063712042","durationMs":56.055583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeClaudeEnvironment","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"bd62ec970b5ccc85","parentSpanId":"e4521adafe1ddf79","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320236975917","endTimeUnixNano":"1779352320236985042","durationMs":0.009125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runClaudeCommand","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"e4521adafe1ddf79","parentSpanId":"08c659820368ebba","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320236963792","endTimeUnixNano":"1779352320238524667","durationMs":1.560875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"PlatformError: NotFound: ChildProcess.spawn (claude --version)\n at Module.systemError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/PlatformError.js:59:39)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/internal/utils.js:28:24\n at toPlatformError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:25:54)\n at ChildProcess. (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:230:26)\n at ChildProcess.emit (node:events:509:28)\n at ChildProcess._handle.onexit (node:internal/child_process:293:12)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n at runClaudeCommand (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:27894:30)\n at runClaudeCommand (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:27870:33)\n at checkClaudeProviderStatus (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30400:25)\n at checkClaudeProviderStatus (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:27878:42)\n at applySnapshot (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30277:83)\n at applySnapshot (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30257:35)\n at refreshSnapshot (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30282:102)\n at refreshSnapshot (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30278:33)\n at makeManagedServerProvider (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30401:27)\n at makeManagedServerProvider (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30222:42) {\n [cause]: Error: spawn claude ENOENT\n at ChildProcess._handle.onexit (node:internal/child_process:287:19)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n}"}} -{"type":"effect-span","name":"checkClaudeProviderStatus","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"08c659820368ebba","parentSpanId":"8e86dbfbc26a4c1a","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320236878250","endTimeUnixNano":"1779352320238726334","durationMs":1.848084,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"442d63ebc7786bba9b33ab104dbc017b","spanId":"37db8600070e6e7d","parentSpanId":"7de06370b9f916ff","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320238803542","endTimeUnixNano":"1779352320238812042","durationMs":0.0085,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"442d63ebc7786bba9b33ab104dbc017b","spanId":"de18102e1df031b8","parentSpanId":"7de06370b9f916ff","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320239003000","endTimeUnixNano":"1779352320239013084","durationMs":0.010084,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"2a83240bebfd2bc2","parentSpanId":"8e86dbfbc26a4c1a","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320239074542","endTimeUnixNano":"1779352320239102375","durationMs":0.027833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"8e86dbfbc26a4c1a","parentSpanId":"9ea2db034ebd649c","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320236860959","endTimeUnixNano":"1779352320239107167","durationMs":2.246208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"9ea2db034ebd649c","parentSpanId":"d8882d30663dbbb0","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320236806667","endTimeUnixNano":"1779352320239112084","durationMs":2.305417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"60baf1b87247c3ce","parentSpanId":"2a83240bebfd2bc2","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320239191459","endTimeUnixNano":"1779352320239203084","durationMs":0.011625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"37c7f46090238ed0","parentSpanId":"2a83240bebfd2bc2","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320239211250","endTimeUnixNano":"1779352320239235084","durationMs":0.023834,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"checkCursorProviderStatus","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"b6b091148b74a8cc","parentSpanId":"844ae2031ccfe277","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320239471375","endTimeUnixNano":"1779352320239492125","durationMs":0.02075,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"1e6c7ecb3fc6208c81ce36fa3cc5b02e","spanId":"70d3dbe9b98d9e8e","parentSpanId":"74cc88e51e292ff5","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320239549250","endTimeUnixNano":"1779352320239555584","durationMs":0.006334,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"1e6c7ecb3fc6208c81ce36fa3cc5b02e","spanId":"91825762cebdeb10","parentSpanId":"74cc88e51e292ff5","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320239596417","endTimeUnixNano":"1779352320239603167","durationMs":0.00675,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"a0ff8a2fed42b718","parentSpanId":"844ae2031ccfe277","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320239647500","endTimeUnixNano":"1779352320239676917","durationMs":0.029417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"844ae2031ccfe277","parentSpanId":"e681d2679de44470","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320239461125","endTimeUnixNano":"1779352320239682667","durationMs":0.221542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"e681d2679de44470","parentSpanId":"f4270506fde844da","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320239442084","endTimeUnixNano":"1779352320239686959","durationMs":0.244875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"6d5d8db267040427","parentSpanId":"a0ff8a2fed42b718","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320239916417","endTimeUnixNano":"1779352320239924667","durationMs":0.00825,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"113a535c77fb6a21","parentSpanId":"a0ff8a2fed42b718","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320239938459","endTimeUnixNano":"1779352320239958417","durationMs":0.019958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"442d63ebc7786bba9b33ab104dbc017b","spanId":"7de06370b9f916ff","parentSpanId":"67f64f0a7d5d04eb","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320238784292","endTimeUnixNano":"1779352320240402750","durationMs":1.618458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"442d63ebc7786bba9b33ab104dbc017b","spanId":"67f64f0a7d5d04eb","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320238768250","endTimeUnixNano":"1779352320240408250","durationMs":1.64,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"733c844cda8bb867919c51bc100a1657","spanId":"959d6f211554e47c","parentSpanId":"ae099c00ec7ea0a3","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320240442625","endTimeUnixNano":"1779352320240448167","durationMs":0.005542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"733c844cda8bb867919c51bc100a1657","spanId":"ef4773f66044cca3","parentSpanId":"ae099c00ec7ea0a3","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320240481667","endTimeUnixNano":"1779352320240487125","durationMs":0.005458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"1e6c7ecb3fc6208c81ce36fa3cc5b02e","spanId":"74cc88e51e292ff5","parentSpanId":"0b6926e9669bf735","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320239536292","endTimeUnixNano":"1779352320240530334","durationMs":0.994042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"1e6c7ecb3fc6208c81ce36fa3cc5b02e","spanId":"0b6926e9669bf735","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320239524875","endTimeUnixNano":"1779352320240534042","durationMs":1.009167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"29db6a049f550a06038f37f4d0a1c891","spanId":"7b65fae54dc77f5e","parentSpanId":"e93d6f8b04328047","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320240559042","endTimeUnixNano":"1779352320240563625","durationMs":0.004583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"29db6a049f550a06038f37f4d0a1c891","spanId":"bbf9c6ad170adc06","parentSpanId":"e93d6f8b04328047","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320240585167","endTimeUnixNano":"1779352320240589959","durationMs":0.004792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"29db6a049f550a06038f37f4d0a1c891","spanId":"e93d6f8b04328047","parentSpanId":"5ea239032c058efc","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320240551125","endTimeUnixNano":"1779352320241099625","durationMs":0.5485,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"29db6a049f550a06038f37f4d0a1c891","spanId":"5ea239032c058efc","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320240543709","endTimeUnixNano":"1779352320241104167","durationMs":0.560458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"733c844cda8bb867919c51bc100a1657","spanId":"ae099c00ec7ea0a3","parentSpanId":"413de5929d759c62","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320240432334","endTimeUnixNano":"1779352320241117292","durationMs":0.684958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"733c844cda8bb867919c51bc100a1657","spanId":"413de5929d759c62","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320240423875","endTimeUnixNano":"1779352320241120500","durationMs":0.696625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeCodexAppServerPatchedProtocol","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"3f6cee8d358dd7be","parentSpanId":"a6b868fbd32b8116","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320317419792","endTimeUnixNano":"1779352320317636792","durationMs":0.217,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"effect-codex-app-server/CodexAppServerClient.make","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"a6b868fbd32b8116","parentSpanId":"d581b6076b05015c","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320317350875","endTimeUnixNano":"1779352320317739334","durationMs":0.388459,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"requestAllCodexModels","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"89ded603b924862b","parentSpanId":"d581b6076b05015c","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320375779834","endTimeUnixNano":"1779352320378447209","durationMs":2.667375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"probeCodexAppServerProvider","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"d581b6076b05015c","parentSpanId":"96a054d9072454eb","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320315565750","endTimeUnixNano":"1779352320421141667","durationMs":105.575917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"checkCodexProviderStatus","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"96a054d9072454eb","parentSpanId":"39aef4e57735b82c","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320315353042","endTimeUnixNano":"1779352320422625459","durationMs":107.272417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"84d9454d8f62954655fb33a0b3460b9c","spanId":"2556b995a242a2bb","parentSpanId":"60f32d42205e212a","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320422704334","endTimeUnixNano":"1779352320422710209","durationMs":0.005875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"84d9454d8f62954655fb33a0b3460b9c","spanId":"5f16c064009f06e7","parentSpanId":"60f32d42205e212a","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320422811750","endTimeUnixNano":"1779352320422819959","durationMs":0.008209,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"d7ad4f1690572574","parentSpanId":"39aef4e57735b82c","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320422899834","endTimeUnixNano":"1779352320422924250","durationMs":0.024416,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"39aef4e57735b82c","parentSpanId":"ae96b37c5be94e71","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320315328375","endTimeUnixNano":"1779352320422928459","durationMs":107.600084,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"ae96b37c5be94e71","parentSpanId":"5bc4cdb3beb605ab","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320315264834","endTimeUnixNano":"1779352320422932667","durationMs":107.667833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveLatestProviderVersion","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"33c8382691582222","parentSpanId":"944bfe472dd5f3f8","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320422968542","endTimeUnixNano":"1779352320422983167","durationMs":0.014625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"944bfe472dd5f3f8","parentSpanId":"d7ad4f1690572574","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320422959834","endTimeUnixNano":"1779352320423006750","durationMs":0.046916,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"f78449b1157b0f48","parentSpanId":"d7ad4f1690572574","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320423015875","endTimeUnixNano":"1779352320423039000","durationMs":0.023125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"84d9454d8f62954655fb33a0b3460b9c","spanId":"60f32d42205e212a","parentSpanId":"117b59b2b264c837","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320422692417","endTimeUnixNano":"1779352320423519709","durationMs":0.827292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"84d9454d8f62954655fb33a0b3460b9c","spanId":"117b59b2b264c837","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320422677292","endTimeUnixNano":"1779352320423523125","durationMs":0.845833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"3a8f2d5f5ce88e3872eedda1e3d05237","spanId":"cace13e1eadd2b1d","parentSpanId":"30c498a5a1ab67bc","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320423550625","endTimeUnixNano":"1779352320423556042","durationMs":0.005417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"3a8f2d5f5ce88e3872eedda1e3d05237","spanId":"8a0dae0a1e7b5d37","parentSpanId":"30c498a5a1ab67bc","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320423586167","endTimeUnixNano":"1779352320423590667","durationMs":0.0045,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"3a8f2d5f5ce88e3872eedda1e3d05237","spanId":"30c498a5a1ab67bc","parentSpanId":"c9d66d6dec3c6243","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320423542792","endTimeUnixNano":"1779352320424154625","durationMs":0.611833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"3a8f2d5f5ce88e3872eedda1e3d05237","spanId":"c9d66d6dec3c6243","sampled":true,"kind":"internal","startTimeUnixNano":"1779352320423535125","endTimeUnixNano":"1779352320424157709","durationMs":0.622584,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"7d44a6adbc582adc","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352322065330292","endTimeUnixNano":"1779352322123315750","durationMs":57.985458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"opencode.app.agents","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"e3fad2e2ac3ef2a0","parentSpanId":"0a8e00f0072674ba","sampled":true,"kind":"internal","startTimeUnixNano":"1779352323077978959","endTimeUnixNano":"1779352323285301042","durationMs":207.322083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"opencode.provider.list","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"c759cab6fbd72930","parentSpanId":"0a8e00f0072674ba","sampled":true,"kind":"internal","startTimeUnixNano":"1779352323077902959","endTimeUnixNano":"1779352323408943167","durationMs":331.040208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"checkOpenCodeProviderStatus","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"0a8e00f0072674ba","parentSpanId":"560001db9065a78b","sampled":true,"kind":"internal","startTimeUnixNano":"1779352322374325834","endTimeUnixNano":"1779352324412609334","durationMs":2038.2835,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"7146034d4e882cacf9f021229053d4aa","spanId":"6f333c534d7def6f","parentSpanId":"5874348ca83b4fec","sampled":true,"kind":"internal","startTimeUnixNano":"1779352324413019917","endTimeUnixNano":"1779352324413054792","durationMs":0.034875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"7146034d4e882cacf9f021229053d4aa","spanId":"704be7af0cf185b9","parentSpanId":"5874348ca83b4fec","sampled":true,"kind":"internal","startTimeUnixNano":"1779352324414663125","endTimeUnixNano":"1779352324414693667","durationMs":0.030542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"f28f8e6a331b0638","parentSpanId":"560001db9065a78b","sampled":true,"kind":"internal","startTimeUnixNano":"1779352324415323042","endTimeUnixNano":"1779352324415423459","durationMs":0.100417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"560001db9065a78b","parentSpanId":"ab61fd0b7d3107ac","sampled":true,"kind":"internal","startTimeUnixNano":"1779352322374268959","endTimeUnixNano":"1779352324415435375","durationMs":2041.166416,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"ab61fd0b7d3107ac","parentSpanId":"2f989ef1cbf60c79","sampled":true,"kind":"internal","startTimeUnixNano":"1779352322374151125","endTimeUnixNano":"1779352324415457667","durationMs":2041.306542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveLatestProviderVersion","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"d5498a1aa6c2ac5c","parentSpanId":"b07b059712b95075","sampled":true,"kind":"internal","startTimeUnixNano":"1779352324415537209","endTimeUnixNano":"1779352324415578167","durationMs":0.040958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"b07b059712b95075","parentSpanId":"f28f8e6a331b0638","sampled":true,"kind":"internal","startTimeUnixNano":"1779352324415511792","endTimeUnixNano":"1779352324415654167","durationMs":0.142375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"4b6cfe3c4021297b","parentSpanId":"f28f8e6a331b0638","sampled":true,"kind":"internal","startTimeUnixNano":"1779352324415670667","endTimeUnixNano":"1779352324415739000","durationMs":0.068333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"7146034d4e882cacf9f021229053d4aa","spanId":"5874348ca83b4fec","parentSpanId":"3eab97b6d7509d65","sampled":true,"kind":"internal","startTimeUnixNano":"1779352324412929375","endTimeUnixNano":"1779352324417578417","durationMs":4.649042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"7146034d4e882cacf9f021229053d4aa","spanId":"3eab97b6d7509d65","sampled":true,"kind":"internal","startTimeUnixNano":"1779352324412850667","endTimeUnixNano":"1779352324417603209","durationMs":4.752542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"7fd94e7b74e96ffc83042e81809a80a3","spanId":"34024f0baa7b317b","parentSpanId":"f9f72abefb94e411","sampled":true,"kind":"internal","startTimeUnixNano":"1779352324417727792","endTimeUnixNano":"1779352324417743459","durationMs":0.015667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"7fd94e7b74e96ffc83042e81809a80a3","spanId":"f3164217b857f4f2","parentSpanId":"f9f72abefb94e411","sampled":true,"kind":"internal","startTimeUnixNano":"1779352324417888084","endTimeUnixNano":"1779352324417905000","durationMs":0.016916,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"7fd94e7b74e96ffc83042e81809a80a3","spanId":"f9f72abefb94e411","parentSpanId":"0abc3e44b272f0a4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352324417698375","endTimeUnixNano":"1779352324420280084","durationMs":2.581709,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"7fd94e7b74e96ffc83042e81809a80a3","spanId":"0abc3e44b272f0a4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352324417670917","endTimeUnixNano":"1779352324420304209","durationMs":2.633292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"9c222a79013464bbed30efe9f66a4107","spanId":"a391886dae4282a0","parentSpanId":"bdaa4ceb2b2577ba","sampled":true,"kind":"client","startTimeUnixNano":"1779352324776902750","endTimeUnixNano":"1779352324777474250","durationMs":0.5715,"attributes":{"server.mode":"desktop","server.port":14124,"server.host":"127.0.0.1","startup.phase":"reactors.start","db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n thread_id AS \"threadId\",\n provider_name AS \"providerName\",\n provider_instance_id AS \"providerInstanceId\",\n adapter_key AS \"adapterKey\",\n runtime_mode AS \"runtimeMode\",\n status,\n last_seen_at AS \"lastSeenAt\",\n resume_cursor_json AS \"resumeCursor\",\n runtime_payload_json AS \"runtimePayload\"\n FROM provider_session_runtime\n ORDER BY last_seen_at ASC, thread_id ASC\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"eb6f87ed4d2d012e","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352327125087084","endTimeUnixNano":"1779352327183979084","durationMs":58.892,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"89b2f4485687e8af","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352332187624834","endTimeUnixNano":"1779352332248864167","durationMs":61.239333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"a5f1b6df623a55f2","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352337250052542","endTimeUnixNano":"1779352337310306000","durationMs":60.253458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"f42f9925af320de6","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352342313262625","endTimeUnixNano":"1779352342363147542","durationMs":49.884917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"71bc4e594409d6a5","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352347364518000","endTimeUnixNano":"1779352347426002125","durationMs":61.484125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"0bbfdacc4903779c","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352352429313084","endTimeUnixNano":"1779352352487825459","durationMs":58.512375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"a06b72412ee01200","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352357488699334","endTimeUnixNano":"1779352357544955167","durationMs":56.255833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"5bee1b195defaada","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352362546209584","endTimeUnixNano":"1779352362604149334","durationMs":57.93975,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"82283acd7b7cd1a9","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352367605958084","endTimeUnixNano":"1779352367663350542","durationMs":57.392458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"27c0b8419feb198f","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352372666537125","endTimeUnixNano":"1779352372714650875","durationMs":48.11375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"6a3eee1292723d3b","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352377716645000","endTimeUnixNano":"1779352377775830500","durationMs":59.1855,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"665bd5a5f8297782","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352382777761375","endTimeUnixNano":"1779352382834617459","durationMs":56.856084,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"45e399db83cb9be7","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352387835642584","endTimeUnixNano":"1779352387894680875","durationMs":59.038291,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"b1f720fe0fc5a2e8","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352392896038750","endTimeUnixNano":"1779352392953058334","durationMs":57.019584,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"0c1e2d4a460f3a64","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352397954858625","endTimeUnixNano":"1779352398015127834","durationMs":60.269209,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"8278dbcb969af43e","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352403016271417","endTimeUnixNano":"1779352403044987125","durationMs":28.715708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"f3dc75c8fae8115d","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352408048207875","endTimeUnixNano":"1779352408107715417","durationMs":59.507542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"4982475ffa7ff467","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352413111653917","endTimeUnixNano":"1779352413168382084","durationMs":56.728167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"805a81ae670a90b2","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352418170027167","endTimeUnixNano":"1779352418229014084","durationMs":58.986917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"e8550f85c17f1451","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352423231858875","endTimeUnixNano":"1779352423289588709","durationMs":57.729834,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"1ce010425e963940","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352428291170000","endTimeUnixNano":"1779352428350090959","durationMs":58.920959,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"b2701ec5c284ccfd","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352433351302042","endTimeUnixNano":"1779352433409133417","durationMs":57.831375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"b5758df17533c220","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352438412428250","endTimeUnixNano":"1779352438470551375","durationMs":58.123125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"b45d3d70f881370b","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352443473333209","endTimeUnixNano":"1779352443534340000","durationMs":61.006791,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"24af9c3461cbb843","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352448536745542","endTimeUnixNano":"1779352448594045667","durationMs":57.300125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"e7f6efd00e3babb9","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352453595846459","endTimeUnixNano":"1779352453655879417","durationMs":60.032958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"f5c68c44c461c7c5","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352458656603834","endTimeUnixNano":"1779352458718269250","durationMs":61.665416,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"dab303abd5dd5be4","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352463721083417","endTimeUnixNano":"1779352463779012084","durationMs":57.928667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"a81e01e45ba11b04","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352468781526875","endTimeUnixNano":"1779352468843253709","durationMs":61.726834,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"22e786a5324af9fb","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352473846372709","endTimeUnixNano":"1779352473905660000","durationMs":59.287291,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"85b893a0d717b103","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352478907997542","endTimeUnixNano":"1779352478967002209","durationMs":59.004667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"938f7db464a02de4","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352483969997667","endTimeUnixNano":"1779352484028966917","durationMs":58.96925,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"6e88459feec84b52","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352489031079042","endTimeUnixNano":"1779352489089602625","durationMs":58.523583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"d001e62b8a9bc3fd","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352494091611875","endTimeUnixNano":"1779352494149263917","durationMs":57.652042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"528f065d4bb2155a","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352499151292584","endTimeUnixNano":"1779352499208271959","durationMs":56.979375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"dd4ec0eca45b410f","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352504211701292","endTimeUnixNano":"1779352504267334250","durationMs":55.632958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"436e89d202c60ef4","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352509270616000","endTimeUnixNano":"1779352509325702917","durationMs":55.086917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"0aa70c629c772ab5","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352514328878375","endTimeUnixNano":"1779352514383902042","durationMs":55.023667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"590bfa36ef1e24f2","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352519384395834","endTimeUnixNano":"1779352519443462084","durationMs":59.06625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"3511729f871ffbef","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352524446103625","endTimeUnixNano":"1779352524503630959","durationMs":57.527334,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"37d365e7fa43a8da","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352529506592417","endTimeUnixNano":"1779352529563777125","durationMs":57.184708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"5dad8b354145748b","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352534564973792","endTimeUnixNano":"1779352534623940792","durationMs":58.967,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"b36befbaf7b7a826","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352539625014917","endTimeUnixNano":"1779352539682962709","durationMs":57.947792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"d96e539c2010bae1","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352544685013375","endTimeUnixNano":"1779352544744132917","durationMs":59.119542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"7542406c68d31606","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352549747096292","endTimeUnixNano":"1779352549803963000","durationMs":56.866708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"e420de4a64e4ff69","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352554805117125","endTimeUnixNano":"1779352554861312625","durationMs":56.1955,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"4cb7e50f8f9a7045","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352559862243792","endTimeUnixNano":"1779352559904734417","durationMs":42.490625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"31c981ed7a07b13b","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352564905968875","endTimeUnixNano":"1779352564963072042","durationMs":57.103167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"786ae2f52ce01041","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352569965167292","endTimeUnixNano":"1779352570010369584","durationMs":45.202292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"http.server GET","traceId":"84642a4c0cea74cccea7058a3ff63fbc","spanId":"2413ce31e858cc0c","sampled":true,"kind":"server","startTimeUnixNano":"1779352570571116750","endTimeUnixNano":"1779352570571518542","durationMs":0.401792,"attributes":{"http.route":"/.well-known/t3/environment","http.request.method":"GET","url.full":"http://127.0.0.1:14124/.well-known/t3/environment","url.path":"/.well-known/t3/environment","url.scheme":"http","user_agent.original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"close","http.request.header.sec-ch-ua-platform":"\"macOS\"","http.request.header.user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.sec-ch-ua":"\"Not-A.Brand\";v=\"24\", \"Chromium\";v=\"146\"","http.request.header.sec-ch-ua-mobile":"?0","http.request.header.accept":"*/*","http.request.header.sec-fetch-site":"same-origin","http.request.header.sec-fetch-mode":"cors","http.request.header.sec-fetch-dest":"empty","http.request.header.referer":"http://127.0.0.1:6084/","http.request.header.accept-encoding":"gzip, deflate, br, zstd","http.request.header.accept-language":"en-GB","http.request.header.cookie":"","http.response.status_code":200,"http.response.header.access-control-allow-origin":"*","http.response.header.access-control-allow-methods":"GET, POST, OPTIONS","http.response.header.access-control-allow-headers":"authorization, b3, traceparent, content-type","http.response.header.content-type":"application/json","http.response.header.content-length":"198"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"ebecf5b1ebcfa3a8ae193a37533f6f07","spanId":"19b175da3b0426e1","parentSpanId":"0f269119e81a0c8a","sampled":true,"kind":"client","startTimeUnixNano":"1779352570572225417","endTimeUnixNano":"1779352570572337084","durationMs":0.111667,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n session_id AS \"sessionId\",\n subject AS \"subject\",\n role AS \"role\",\n method AS \"method\",\n client_label AS \"clientLabel\",\n client_ip_address AS \"clientIpAddress\",\n client_user_agent AS \"clientUserAgent\",\n client_device_type AS \"clientDeviceType\",\n client_os AS \"clientOs\",\n client_browser AS \"clientBrowser\",\n issued_at AS \"issuedAt\",\n expires_at AS \"expiresAt\",\n last_connected_at AS \"lastConnectedAt\",\n revoked_at AS \"revokedAt\"\n FROM auth_sessions\n WHERE session_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"http.server GET","traceId":"ebecf5b1ebcfa3a8ae193a37533f6f07","spanId":"0f269119e81a0c8a","sampled":true,"kind":"server","startTimeUnixNano":"1779352570571934542","endTimeUnixNano":"1779352570572499875","durationMs":0.565333,"attributes":{"http.route":"/api/auth/session","http.request.method":"GET","url.full":"http://127.0.0.1:14124/api/auth/session","url.path":"/api/auth/session","url.scheme":"http","user_agent.original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"close","http.request.header.sec-ch-ua-platform":"\"macOS\"","http.request.header.user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.sec-ch-ua":"\"Not-A.Brand\";v=\"24\", \"Chromium\";v=\"146\"","http.request.header.sec-ch-ua-mobile":"?0","http.request.header.accept":"*/*","http.request.header.sec-fetch-site":"same-origin","http.request.header.sec-fetch-mode":"cors","http.request.header.sec-fetch-dest":"empty","http.request.header.referer":"http://127.0.0.1:6084/","http.request.header.accept-encoding":"gzip, deflate, br, zstd","http.request.header.accept-language":"en-GB","http.request.header.cookie":"","http.response.status_code":200,"http.response.header.access-control-allow-origin":"*","http.response.header.access-control-allow-methods":"GET, POST, OPTIONS","http.response.header.access-control-allow-headers":"authorization, b3, traceparent, content-type","http.response.header.content-type":"application/json","http.response.header.content-length":"306"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"a1dc76d2d0d36c16","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"client","startTimeUnixNano":"1779352570658023250","endTimeUnixNano":"1779352570658555167","durationMs":0.531917,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n session_id AS \"sessionId\",\n subject AS \"subject\",\n role AS \"role\",\n method AS \"method\",\n client_label AS \"clientLabel\",\n client_ip_address AS \"clientIpAddress\",\n client_user_agent AS \"clientUserAgent\",\n client_device_type AS \"clientDeviceType\",\n client_os AS \"clientOs\",\n client_browser AS \"clientBrowser\",\n issued_at AS \"issuedAt\",\n expires_at AS \"expiresAt\",\n last_connected_at AS \"lastConnectedAt\",\n revoked_at AS \"revokedAt\"\n FROM auth_sessions\n WHERE session_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeProviderMaintenanceCommandCoordinator","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"e9f08e35d1c3f40e","parentSpanId":"87d759d1657d2f57","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570659232834","endTimeUnixNano":"1779352570659271875","durationMs":0.039041,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProviderMaintenanceRunner.make","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"87d759d1657d2f57","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570659194500","endTimeUnixNano":"1779352570659283125","durationMs":0.088625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"0d73dcab6b4eec2a","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"client","startTimeUnixNano":"1779352570659975167","endTimeUnixNano":"1779352570660141584","durationMs":0.166417,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n UPDATE auth_sessions\n SET last_connected_at = ?\n WHERE session_id = ?\n AND revoked_at IS NULL\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"2b248131f80eb736","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"client","startTimeUnixNano":"1779352570660196917","endTimeUnixNano":"1779352570660219584","durationMs":0.022667,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n session_id AS \"sessionId\",\n subject AS \"subject\",\n role AS \"role\",\n method AS \"method\",\n client_label AS \"clientLabel\",\n client_ip_address AS \"clientIpAddress\",\n client_user_agent AS \"clientUserAgent\",\n client_device_type AS \"clientDeviceType\",\n client_os AS \"clientOs\",\n client_browser AS \"clientBrowser\",\n issued_at AS \"issuedAt\",\n expires_at AS \"expiresAt\",\n last_connected_at AS \"lastConnectedAt\",\n revoked_at AS \"revokedAt\"\n FROM auth_sessions\n WHERE session_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"4a6026927be7a941","parentSpanId":"7eee6a96e2d17ec4","sampled":true,"kind":"client","startTimeUnixNano":"1779352570662466917","endTimeUnixNano":"1779352570662540750","durationMs":0.073833,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n project_id AS \"projectId\",\n title,\n workspace_root AS \"workspaceRoot\",\n default_model_selection_json AS \"defaultModelSelection\",\n scripts_json AS \"scripts\",\n created_at AS \"createdAt\",\n updated_at AS \"updatedAt\",\n deleted_at AS \"deletedAt\"\n FROM projection_projects\n ORDER BY created_at ASC, project_id ASC\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"98e0d7317cb7f2fa","parentSpanId":"7eee6a96e2d17ec4","sampled":true,"kind":"client","startTimeUnixNano":"1779352570662642042","endTimeUnixNano":"1779352570662700459","durationMs":0.058417,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n thread_id AS \"threadId\",\n project_id AS \"projectId\",\n title,\n model_selection_json AS \"modelSelection\",\n runtime_mode AS \"runtimeMode\",\n interaction_mode AS \"interactionMode\",\n branch,\n worktree_path AS \"worktreePath\",\n latest_turn_id AS \"latestTurnId\",\n created_at AS \"createdAt\",\n updated_at AS \"updatedAt\",\n archived_at AS \"archivedAt\",\n latest_user_message_at AS \"latestUserMessageAt\",\n pending_approval_count AS \"pendingApprovalCount\",\n pending_user_input_count AS \"pendingUserInputCount\",\n has_actionable_proposed_plan AS \"hasActionableProposedPlan\",\n deleted_at AS \"deletedAt\"\n FROM projection_threads\n WHERE deleted_at IS NULL\n AND archived_at IS NULL\n ORDER BY project_id ASC, created_at ASC, thread_id ASC\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"9c3b53fb1096264a","parentSpanId":"7eee6a96e2d17ec4","sampled":true,"kind":"client","startTimeUnixNano":"1779352570662715500","endTimeUnixNano":"1779352570662756292","durationMs":0.040792,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n sessions.thread_id AS \"threadId\",\n sessions.status,\n sessions.provider_name AS \"providerName\",\n sessions.provider_instance_id AS \"providerInstanceId\",\n sessions.provider_session_id AS \"providerSessionId\",\n sessions.provider_thread_id AS \"providerThreadId\",\n sessions.runtime_mode AS \"runtimeMode\",\n sessions.active_turn_id AS \"activeTurnId\",\n sessions.last_error AS \"lastError\",\n sessions.updated_at AS \"updatedAt\"\n FROM projection_thread_sessions sessions\n INNER JOIN projection_threads threads\n ON threads.thread_id = sessions.thread_id\n WHERE threads.deleted_at IS NULL\n AND threads.archived_at IS NULL\n ORDER BY sessions.thread_id ASC\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"b11080dfcc9180ad","parentSpanId":"7eee6a96e2d17ec4","sampled":true,"kind":"client","startTimeUnixNano":"1779352570662768917","endTimeUnixNano":"1779352570662811000","durationMs":0.042083,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n turns.thread_id AS \"threadId\",\n turns.turn_id AS \"turnId\",\n turns.state,\n turns.requested_at AS \"requestedAt\",\n turns.started_at AS \"startedAt\",\n turns.completed_at AS \"completedAt\",\n turns.assistant_message_id AS \"assistantMessageId\",\n turns.source_proposed_plan_thread_id AS \"sourceProposedPlanThreadId\",\n turns.source_proposed_plan_id AS \"sourceProposedPlanId\"\n FROM projection_threads threads\n JOIN projection_turns turns\n ON turns.thread_id = threads.thread_id\n AND turns.turn_id = threads.latest_turn_id\n WHERE threads.deleted_at IS NULL\n AND threads.archived_at IS NULL\n AND threads.latest_turn_id IS NOT NULL\n ORDER BY turns.thread_id ASC\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"9e81faf33ba9bb67","parentSpanId":"7eee6a96e2d17ec4","sampled":true,"kind":"client","startTimeUnixNano":"1779352570662821084","endTimeUnixNano":"1779352570662853084","durationMs":0.032,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n projector,\n last_applied_sequence AS \"lastAppliedSequence\",\n updated_at AS \"updatedAt\"\n FROM projection_state\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.transaction","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"7eee6a96e2d17ec4","parentSpanId":"2ea2cdc31ee0588a","sampled":true,"kind":"client","startTimeUnixNano":"1779352570662384625","endTimeUnixNano":"1779352570662898125","durationMs":0.5135,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite"},"events":[{"name":"db.transaction.commit","timeUnixNano":"1779352570662875000","attributes":{}}],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.server.getConfig","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"4c853a5b8d4cd798","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570668700959","endTimeUnixNano":"1779352570674344917","durationMs":5.643958,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"server.getConfig","rpc.aggregate":"server"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.server.getConfig","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"8b6aee64a4bead00","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570689962250","endTimeUnixNano":"1779352570693597459","durationMs":3.635209,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"server.getConfig","rpc.aggregate":"server"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeClaudeEnvironment","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"88a53efd40829583","parentSpanId":"bc07c70b805440b8","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570701216292","endTimeUnixNano":"1779352570701223792","durationMs":0.0075,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"checkCursorProviderStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"cf632fa2301ee28d","parentSpanId":"e590b8e11d2f132a","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570708244542","endTimeUnixNano":"1779352570708319667","durationMs":0.075125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"bb960772554489e1734d1c427f69cf97","spanId":"15e1012cf70ec44d","parentSpanId":"e25ae112e0eac1b0","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570708502542","endTimeUnixNano":"1779352570708518500","durationMs":0.015958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"bb960772554489e1734d1c427f69cf97","spanId":"ffe2c2e4cad6225c","parentSpanId":"e25ae112e0eac1b0","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570708953417","endTimeUnixNano":"1779352570708968542","durationMs":0.015125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"132823721c78dcee","parentSpanId":"e590b8e11d2f132a","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570709058042","endTimeUnixNano":"1779352570709104917","durationMs":0.046875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"e590b8e11d2f132a","parentSpanId":"ba06dde56bdc68c9","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570708217125","endTimeUnixNano":"1779352570709110125","durationMs":0.893,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"ba06dde56bdc68c9","parentSpanId":"ff4ec2810ea2cf69","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570708174667","endTimeUnixNano":"1779352570709116000","durationMs":0.941333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"98fb8df02b5a76ec","parentSpanId":"f96de5bb73f9c7c6","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570709203292","endTimeUnixNano":"1779352570709484917","durationMs":0.281625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"f96de5bb73f9c7c6","parentSpanId":"0c8dd9624282b9a7","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570709191500","endTimeUnixNano":"1779352570709566542","durationMs":0.375042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"0c8dd9624282b9a7","parentSpanId":"ff4ec2810ea2cf69","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570709183042","endTimeUnixNano":"1779352570709569542","durationMs":0.3865,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshOneSource","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"ff4ec2810ea2cf69","parentSpanId":"014607b7d9ca3659","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570708134750","endTimeUnixNano":"1779352570709572000","durationMs":1.43725,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runClaudeCommand","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"bc07c70b805440b8","parentSpanId":"9ea6734a25c2acf9","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570701207584","endTimeUnixNano":"1779352570713673792","durationMs":12.466208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"PlatformError: NotFound: ChildProcess.spawn (claude --version)\n at Module.systemError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/PlatformError.js:59:39)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/internal/utils.js:28:24\n at toPlatformError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:25:54)\n at ChildProcess. (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:230:26)\n at ChildProcess.emit (node:events:509:28)\n at ChildProcess._handle.onexit (node:internal/child_process:293:12)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n at runClaudeCommand (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:27894:30)\n at runClaudeCommand (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:27870:33)\n at checkClaudeProviderStatus (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30400:25)\n at checkClaudeProviderStatus (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:27878:42)\n at applySnapshot (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30277:83)\n at applySnapshot (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30257:35)\n at refreshSnapshot (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30287:12)\n at refreshSnapshot (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30278:33)\n at refreshOneSource (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:60480:53)\n at refreshOneSource (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:60475:34) {\n [cause]: Error: spawn claude ENOENT\n at ChildProcess._handle.onexit (node:internal/child_process:287:19)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n}"}} -{"type":"effect-span","name":"checkClaudeProviderStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"9ea6734a25c2acf9","parentSpanId":"dd1f9edca2c4b687","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570701181500","endTimeUnixNano":"1779352570714107667","durationMs":12.926167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"f06554e73dd55cfc014e53bf6c16c138","spanId":"178011ac4dc7ca9e","parentSpanId":"d74cf5bf580d86a8","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570714249042","endTimeUnixNano":"1779352570714264209","durationMs":0.015167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"f06554e73dd55cfc014e53bf6c16c138","spanId":"5f9965dc66bd6112","parentSpanId":"d74cf5bf580d86a8","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570714393917","endTimeUnixNano":"1779352570714416625","durationMs":0.022708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"e0e5b5a0431ac919","parentSpanId":"dd1f9edca2c4b687","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570714543584","endTimeUnixNano":"1779352570714603917","durationMs":0.060333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"dd1f9edca2c4b687","parentSpanId":"6930a5ffbda7901d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570701172250","endTimeUnixNano":"1779352570714818709","durationMs":13.646459,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"6930a5ffbda7901d","parentSpanId":"bd183a0598f4209d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570701160250","endTimeUnixNano":"1779352570714847959","durationMs":13.687709,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"b6e7f9f9c6081c7b","parentSpanId":"be23962aabaca3ff","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570714894292","endTimeUnixNano":"1779352570714900875","durationMs":0.006583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"be23962aabaca3ff","parentSpanId":"2e136c0ca1cae02a","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570714881750","endTimeUnixNano":"1779352570714934167","durationMs":0.052417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"2e136c0ca1cae02a","parentSpanId":"bd183a0598f4209d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570714870584","endTimeUnixNano":"1779352570714937084","durationMs":0.0665,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshOneSource","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"bd183a0598f4209d","parentSpanId":"014607b7d9ca3659","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570701150000","endTimeUnixNano":"1779352570714939959","durationMs":13.789959,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"dd58cc3e9277443a","parentSpanId":"21638c8cd2c3a39a","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570667930584","endTimeUnixNano":"1779352570715272917","durationMs":47.342333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeCodexAppServerPatchedProtocol","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"24aca792cc0fb070","parentSpanId":"7c93523f235704d0","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570715932792","endTimeUnixNano":"1779352570715981334","durationMs":0.048542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"effect-codex-app-server/CodexAppServerClient.make","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"7c93523f235704d0","parentSpanId":"a74b233e6a4123e5","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570715913875","endTimeUnixNano":"1779352570715996667","durationMs":0.082792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"adfc4aee30100cac","parentSpanId":"132823721c78dcee","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570716354709","endTimeUnixNano":"1779352570716368375","durationMs":0.013666,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"a01fd902ff5193d1","parentSpanId":"132823721c78dcee","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570716385667","endTimeUnixNano":"1779352570716413334","durationMs":0.027667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"279abee82d829820","parentSpanId":"e0e5b5a0431ac919","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570716425750","endTimeUnixNano":"1779352570716431750","durationMs":0.006,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"4e5161f1132c80e2","parentSpanId":"e0e5b5a0431ac919","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570716439459","endTimeUnixNano":"1779352570716454375","durationMs":0.014916,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"b0a20d5fc5f87de6","parentSpanId":"21638c8cd2c3a39a","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570668143959","endTimeUnixNano":"1779352570716982250","durationMs":48.838291,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"21638c8cd2c3a39a","parentSpanId":"3468011a7fb96010","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570663446125","endTimeUnixNano":"1779352570717018417","durationMs":53.572292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveRepositoryIdentityCacheKey","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"3468011a7fb96010","parentSpanId":"63c9650bbcfc93b2","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570663035292","endTimeUnixNano":"1779352570717248042","durationMs":54.21275,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"bb960772554489e1734d1c427f69cf97","spanId":"e25ae112e0eac1b0","parentSpanId":"b04b599187aa2614","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570708467417","endTimeUnixNano":"1779352570720678250","durationMs":12.210833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"bb960772554489e1734d1c427f69cf97","spanId":"b04b599187aa2614","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570708435459","endTimeUnixNano":"1779352570720704959","durationMs":12.2695,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"66e62e5c365b9006ec4d40476671fe40","spanId":"df49c9bbeaf58cf2","parentSpanId":"ed77efabde157adc","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570720819084","endTimeUnixNano":"1779352570720834042","durationMs":0.014958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"66e62e5c365b9006ec4d40476671fe40","spanId":"19f6e266cce3c4d1","parentSpanId":"ed77efabde157adc","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570720939584","endTimeUnixNano":"1779352570720961000","durationMs":0.021416,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"f06554e73dd55cfc014e53bf6c16c138","spanId":"d74cf5bf580d86a8","parentSpanId":"8f262b8889eaa4c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570714220000","endTimeUnixNano":"1779352570721119750","durationMs":6.89975,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"f06554e73dd55cfc014e53bf6c16c138","spanId":"8f262b8889eaa4c4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570714190709","endTimeUnixNano":"1779352570721130209","durationMs":6.9395,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"5ce1b1af70033770f8c07e468b8ff620","spanId":"4c76137cde39080d","parentSpanId":"b7755ed7a51d73af","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570721254417","endTimeUnixNano":"1779352570721268167","durationMs":0.01375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"5ce1b1af70033770f8c07e468b8ff620","spanId":"c2ad029914a5c2f7","parentSpanId":"b7755ed7a51d73af","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570721341000","endTimeUnixNano":"1779352570721354459","durationMs":0.013459,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"5ce1b1af70033770f8c07e468b8ff620","spanId":"b7755ed7a51d73af","parentSpanId":"7642560de2ce6379","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570721204542","endTimeUnixNano":"1779352570722979042","durationMs":1.7745,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"5ce1b1af70033770f8c07e468b8ff620","spanId":"7642560de2ce6379","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570721167167","endTimeUnixNano":"1779352570722994084","durationMs":1.826917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"66e62e5c365b9006ec4d40476671fe40","spanId":"ed77efabde157adc","parentSpanId":"2b0959c19a88c29d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570720790459","endTimeUnixNano":"1779352570723016209","durationMs":2.22575,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"66e62e5c365b9006ec4d40476671fe40","spanId":"2b0959c19a88c29d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570720762250","endTimeUnixNano":"1779352570723021000","durationMs":2.25875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"27c5afaac01f7bb8","parentSpanId":"60b803c5d66c77da","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570718236709","endTimeUnixNano":"1779352570725849542","durationMs":7.612833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"607ae0da8e079093","parentSpanId":"60b803c5d66c77da","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570718195292","endTimeUnixNano":"1779352570725985750","durationMs":7.790458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"60b803c5d66c77da","parentSpanId":"6a9e2f6e65b41ca8","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570717314042","endTimeUnixNano":"1779352570726036917","durationMs":8.722875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveRepositoryIdentityFromCacheKey","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"6a9e2f6e65b41ca8","parentSpanId":"63c9650bbcfc93b2","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570717282875","endTimeUnixNano":"1779352570726169667","durationMs":8.886792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"RepositoryIdentityResolver.resolve","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"63c9650bbcfc93b2","parentSpanId":"11e3099e1e0375d1","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570663022167","endTimeUnixNano":"1779352570726598250","durationMs":63.576083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectionSnapshotQuery.resolveRepositoryIdentitiesForProjects","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"11e3099e1e0375d1","parentSpanId":"2ea2cdc31ee0588a","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570662990667","endTimeUnixNano":"1779352570726637167","durationMs":63.6465,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"requestAllCodexModels","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"1a632b0766cefeb9","parentSpanId":"a74b233e6a4123e5","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570759713959","endTimeUnixNano":"1779352570761264667","durationMs":1.550708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"probeCodexAppServerProvider","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"a74b233e6a4123e5","parentSpanId":"8b3f7e51d27a3d86","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570700907459","endTimeUnixNano":"1779352570812527750","durationMs":111.620291,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"checkCodexProviderStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"8b3f7e51d27a3d86","parentSpanId":"47c75f920ddaf251","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570700793334","endTimeUnixNano":"1779352570816258084","durationMs":115.46475,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"95608bde3cc44c7e8e34dcc9e0f932fb","spanId":"3636239f46e6187b","parentSpanId":"781098b7697732ef","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570816437500","endTimeUnixNano":"1779352570816450500","durationMs":0.013,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"95608bde3cc44c7e8e34dcc9e0f932fb","spanId":"36610efbcdf219b6","parentSpanId":"781098b7697732ef","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570816623209","endTimeUnixNano":"1779352570816639459","durationMs":0.01625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"8e7dfda08aa260a8","parentSpanId":"47c75f920ddaf251","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570816755917","endTimeUnixNano":"1779352570816797625","durationMs":0.041708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"47c75f920ddaf251","parentSpanId":"32d96dcbd0bf39eb","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570700776917","endTimeUnixNano":"1779352570816803375","durationMs":116.026458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"32d96dcbd0bf39eb","parentSpanId":"0a94c9d3e4b22247","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570700723917","endTimeUnixNano":"1779352570816809750","durationMs":116.085833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"d8024bec39842d84","parentSpanId":"1dd570334e37bc60","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570816843125","endTimeUnixNano":"1779352570816848834","durationMs":0.005709,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"1dd570334e37bc60","parentSpanId":"5020dd9091c1a61f","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570816831625","endTimeUnixNano":"1779352570816877167","durationMs":0.045542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"5020dd9091c1a61f","parentSpanId":"0a94c9d3e4b22247","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570816822584","endTimeUnixNano":"1779352570816879959","durationMs":0.057375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshOneSource","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"0a94c9d3e4b22247","parentSpanId":"014607b7d9ca3659","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570700697584","endTimeUnixNano":"1779352570816883000","durationMs":116.185416,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveLatestProviderVersion","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"67d58e24db4c339d","parentSpanId":"e757fcc2a0a25c2d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570816944084","endTimeUnixNano":"1779352570816954709","durationMs":0.010625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"e757fcc2a0a25c2d","parentSpanId":"8e7dfda08aa260a8","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570816933000","endTimeUnixNano":"1779352570816978292","durationMs":0.045292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"623db49e8cd8dccf","parentSpanId":"8e7dfda08aa260a8","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570816985375","endTimeUnixNano":"1779352570817003167","durationMs":0.017792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"95608bde3cc44c7e8e34dcc9e0f932fb","spanId":"781098b7697732ef","parentSpanId":"2ff1ef8db01b8510","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570816408625","endTimeUnixNano":"1779352570817591834","durationMs":1.183209,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"95608bde3cc44c7e8e34dcc9e0f932fb","spanId":"2ff1ef8db01b8510","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570816371917","endTimeUnixNano":"1779352570817595917","durationMs":1.224,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"b9bedee53e9172e46b4a85b895800417","spanId":"249f11e3908ebd09","parentSpanId":"8bfb28a88f7bae9a","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570817622500","endTimeUnixNano":"1779352570817626917","durationMs":0.004417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"b9bedee53e9172e46b4a85b895800417","spanId":"f14d427af796c39d","parentSpanId":"8bfb28a88f7bae9a","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570817648792","endTimeUnixNano":"1779352570817653209","durationMs":0.004417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"b9bedee53e9172e46b4a85b895800417","spanId":"8bfb28a88f7bae9a","parentSpanId":"cb9d6b3db02fb499","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570817614584","endTimeUnixNano":"1779352570818103500","durationMs":0.488916,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"b9bedee53e9172e46b4a85b895800417","spanId":"cb9d6b3db02fb499","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570817607542","endTimeUnixNano":"1779352570818110000","durationMs":0.502458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"48425abb64cc80ee052d339fc8d4551a","spanId":"adb9efc23e74e146","parentSpanId":"d63cf7162e7f4179","sampled":true,"kind":"client","startTimeUnixNano":"1779352570825367542","endTimeUnixNano":"1779352570825424542","durationMs":0.057,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n session_id AS \"sessionId\",\n subject AS \"subject\",\n role AS \"role\",\n method AS \"method\",\n client_label AS \"clientLabel\",\n client_ip_address AS \"clientIpAddress\",\n client_user_agent AS \"clientUserAgent\",\n client_device_type AS \"clientDeviceType\",\n client_os AS \"clientOs\",\n client_browser AS \"clientBrowser\",\n issued_at AS \"issuedAt\",\n expires_at AS \"expiresAt\",\n last_connected_at AS \"lastConnectedAt\",\n revoked_at AS \"revokedAt\"\n FROM auth_sessions\n WHERE session_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"48425abb64cc80ee052d339fc8d4551a","spanId":"ac1d948b410833b0","parentSpanId":"4dbaccdd187a7e06","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570825557042","endTimeUnixNano":"1779352570825637750","durationMs":0.080708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"48425abb64cc80ee052d339fc8d4551a","spanId":"f62b734ee9aa869a","parentSpanId":"4dbaccdd187a7e06","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570825650709","endTimeUnixNano":"1779352570825677542","durationMs":0.026833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"48425abb64cc80ee052d339fc8d4551a","spanId":"bef25f269ac53d9a","parentSpanId":"4dbaccdd187a7e06","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570825685750","endTimeUnixNano":"1779352570825707375","durationMs":0.021625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"48425abb64cc80ee052d339fc8d4551a","spanId":"f6c7a4e373112372","parentSpanId":"4dbaccdd187a7e06","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570825715459","endTimeUnixNano":"1779352570825740084","durationMs":0.024625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"48425abb64cc80ee052d339fc8d4551a","spanId":"0b09dfad3f794c4a","parentSpanId":"4dbaccdd187a7e06","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570825746917","endTimeUnixNano":"1779352570825767959","durationMs":0.021042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"48425abb64cc80ee052d339fc8d4551a","spanId":"68828f60391a057f","parentSpanId":"4dbaccdd187a7e06","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570825774625","endTimeUnixNano":"1779352570825793292","durationMs":0.018667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"48425abb64cc80ee052d339fc8d4551a","spanId":"e609abba7d82c957","parentSpanId":"4dbaccdd187a7e06","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570825799625","endTimeUnixNano":"1779352570825818084","durationMs":0.018459,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"48425abb64cc80ee052d339fc8d4551a","spanId":"c2285ab4dc949cb4","parentSpanId":"4dbaccdd187a7e06","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570825824625","endTimeUnixNano":"1779352570825849250","durationMs":0.024625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"48425abb64cc80ee052d339fc8d4551a","spanId":"3caa2b83904a0d4e","parentSpanId":"4dbaccdd187a7e06","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570825855875","endTimeUnixNano":"1779352570825903584","durationMs":0.047709,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"48425abb64cc80ee052d339fc8d4551a","spanId":"d77d32214ea7a178","parentSpanId":"4dbaccdd187a7e06","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570825910375","endTimeUnixNano":"1779352570825961542","durationMs":0.051167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"48425abb64cc80ee052d339fc8d4551a","spanId":"19f6cf890e4b399d","parentSpanId":"4dbaccdd187a7e06","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570825979709","endTimeUnixNano":"1779352570826012084","durationMs":0.032375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"48425abb64cc80ee052d339fc8d4551a","spanId":"3c7ebf1b87a3fca2","parentSpanId":"4dbaccdd187a7e06","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570826150000","endTimeUnixNano":"1779352570826174459","durationMs":0.024459,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"48425abb64cc80ee052d339fc8d4551a","spanId":"eb94101899268f34","parentSpanId":"4dbaccdd187a7e06","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570826182667","endTimeUnixNano":"1779352570826459625","durationMs":0.276958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"48425abb64cc80ee052d339fc8d4551a","spanId":"fc2c647512818006","parentSpanId":"4dbaccdd187a7e06","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570826467959","endTimeUnixNano":"1779352570826488375","durationMs":0.020416,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"48425abb64cc80ee052d339fc8d4551a","spanId":"2eb567ffb6cc6beb","parentSpanId":"4dbaccdd187a7e06","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570826495500","endTimeUnixNano":"1779352570826512709","durationMs":0.017209,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"48425abb64cc80ee052d339fc8d4551a","spanId":"1486ed27c8adf0bc","parentSpanId":"4dbaccdd187a7e06","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570826519584","endTimeUnixNano":"1779352570826536209","durationMs":0.016625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"48425abb64cc80ee052d339fc8d4551a","spanId":"f7036f655d065e69","parentSpanId":"4dbaccdd187a7e06","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570826542959","endTimeUnixNano":"1779352570826559709","durationMs":0.01675,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"48425abb64cc80ee052d339fc8d4551a","spanId":"77aa3674d91f5b2e","parentSpanId":"4dbaccdd187a7e06","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570826566125","endTimeUnixNano":"1779352570826582000","durationMs":0.015875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"48425abb64cc80ee052d339fc8d4551a","spanId":"ccaa8041d0394dd8","parentSpanId":"4dbaccdd187a7e06","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570826588334","endTimeUnixNano":"1779352570826604084","durationMs":0.01575,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"48425abb64cc80ee052d339fc8d4551a","spanId":"79782ce2bcc154a8","parentSpanId":"4dbaccdd187a7e06","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570826610334","endTimeUnixNano":"1779352570826629500","durationMs":0.019166,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"48425abb64cc80ee052d339fc8d4551a","spanId":"1c90ec585f2c303e","parentSpanId":"4dbaccdd187a7e06","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570826637375","endTimeUnixNano":"1779352570826676000","durationMs":0.038625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.resolvePath","traceId":"48425abb64cc80ee052d339fc8d4551a","spanId":"4dbaccdd187a7e06","parentSpanId":"d63cf7162e7f4179","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570825535125","endTimeUnixNano":"1779352570826855209","durationMs":1.320084,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"http.server GET","traceId":"48425abb64cc80ee052d339fc8d4551a","spanId":"d63cf7162e7f4179","sampled":true,"kind":"server","startTimeUnixNano":"1779352570825228542","endTimeUnixNano":"1779352570826988042","durationMs":1.7595,"attributes":{"http.route":"/api/project-favicon","http.request.method":"GET","url.full":"http://127.0.0.1:14124/api/project-favicon?cwd=%2FUsers%2Fharrydawson","url.path":"/api/project-favicon","url.query":"cwd=%2FUsers%2Fharrydawson","url.scheme":"http","user_agent.original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"keep-alive","http.request.header.sec-ch-ua-platform":"\"macOS\"","http.request.header.user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.sec-ch-ua":"\"Not-A.Brand\";v=\"24\", \"Chromium\";v=\"146\"","http.request.header.sec-ch-ua-mobile":"?0","http.request.header.accept":"image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8","http.request.header.sec-fetch-site":"same-site","http.request.header.sec-fetch-mode":"no-cors","http.request.header.sec-fetch-dest":"image","http.request.header.referer":"http://127.0.0.1:6084/","http.request.header.accept-encoding":"gzip, deflate, br, zstd","http.request.header.accept-language":"en-GB","http.request.header.cookie":"","client.address":"127.0.0.1","http.response.status_code":200,"http.response.header.cache-control":"public, max-age=3600","http.response.header.content-type":"image/svg+xml","http.response.header.content-length":"306"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"opencode.app.agents","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"3d607af00d44563f","parentSpanId":"11609a320ee76f69","sampled":true,"kind":"internal","startTimeUnixNano":"1779352571488627334","endTimeUnixNano":"1779352571732448084","durationMs":243.82075,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"opencode.provider.list","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"4365a26e931b41e9","parentSpanId":"11609a320ee76f69","sampled":true,"kind":"internal","startTimeUnixNano":"1779352571488530417","endTimeUnixNano":"1779352571850210709","durationMs":361.680292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"checkOpenCodeProviderStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"11609a320ee76f69","parentSpanId":"05172eca49acbb9c","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570709611709","endTimeUnixNano":"1779352572852376709","durationMs":2142.765,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"6ffb75a32a0d09307a608bb5f781fb24","spanId":"651beda7dce98151","parentSpanId":"818c1f58b5aff5c1","sampled":true,"kind":"internal","startTimeUnixNano":"1779352572852709709","endTimeUnixNano":"1779352572852735209","durationMs":0.0255,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"6ffb75a32a0d09307a608bb5f781fb24","spanId":"116df8cdec4600d4","parentSpanId":"818c1f58b5aff5c1","sampled":true,"kind":"internal","startTimeUnixNano":"1779352572854000209","endTimeUnixNano":"1779352572854036500","durationMs":0.036291,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"86586aa696c2f512","parentSpanId":"05172eca49acbb9c","sampled":true,"kind":"internal","startTimeUnixNano":"1779352572854668042","endTimeUnixNano":"1779352572854782167","durationMs":0.114125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"05172eca49acbb9c","parentSpanId":"9a48b18da1fb78cf","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570709602167","endTimeUnixNano":"1779352572854796459","durationMs":2145.194292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"9a48b18da1fb78cf","parentSpanId":"941b44183ff28403","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570709589042","endTimeUnixNano":"1779352572854815875","durationMs":2145.226833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"457a4bf7282a44bf","parentSpanId":"1e3ca8405973a375","sampled":true,"kind":"internal","startTimeUnixNano":"1779352572854905084","endTimeUnixNano":"1779352572854920959","durationMs":0.015875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"1e3ca8405973a375","parentSpanId":"3b0638c6048c6114","sampled":true,"kind":"internal","startTimeUnixNano":"1779352572854871209","endTimeUnixNano":"1779352572855064625","durationMs":0.193416,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"3b0638c6048c6114","parentSpanId":"941b44183ff28403","sampled":true,"kind":"internal","startTimeUnixNano":"1779352572854844500","endTimeUnixNano":"1779352572855074209","durationMs":0.229709,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshOneSource","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"941b44183ff28403","parentSpanId":"014607b7d9ca3659","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570709581709","endTimeUnixNano":"1779352572855085209","durationMs":2145.5035,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshAll","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"014607b7d9ca3659","parentSpanId":"ef91fa9a85f06795","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570700561625","endTimeUnixNano":"1779352572855117125","durationMs":2154.5555,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refresh","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"ef91fa9a85f06795","parentSpanId":"e37a73ca0ab12f2b","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570700481750","endTimeUnixNano":"1779352572855136084","durationMs":2154.654334,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveLatestProviderVersion","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"4da0db14af171760","parentSpanId":"469718f8e1537095","sampled":true,"kind":"internal","startTimeUnixNano":"1779352572855246250","endTimeUnixNano":"1779352572855280334","durationMs":0.034084,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"469718f8e1537095","parentSpanId":"86586aa696c2f512","sampled":true,"kind":"internal","startTimeUnixNano":"1779352572855213959","endTimeUnixNano":"1779352572855344625","durationMs":0.130666,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"82ee0997b3de1e49","parentSpanId":"86586aa696c2f512","sampled":true,"kind":"internal","startTimeUnixNano":"1779352572855368459","endTimeUnixNano":"1779352572855425667","durationMs":0.057208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"6ffb75a32a0d09307a608bb5f781fb24","spanId":"818c1f58b5aff5c1","parentSpanId":"74eb2987b0f5d051","sampled":true,"kind":"internal","startTimeUnixNano":"1779352572852633667","endTimeUnixNano":"1779352572857723834","durationMs":5.090167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"6ffb75a32a0d09307a608bb5f781fb24","spanId":"74eb2987b0f5d051","sampled":true,"kind":"internal","startTimeUnixNano":"1779352572852576542","endTimeUnixNano":"1779352572857745334","durationMs":5.168792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"5eed7d413ebbe1a518f4b325a2e25472","spanId":"a34c64a75aaac55d","parentSpanId":"3a47f68bcaa4eedb","sampled":true,"kind":"internal","startTimeUnixNano":"1779352572857842917","endTimeUnixNano":"1779352572857856875","durationMs":0.013958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"5eed7d413ebbe1a518f4b325a2e25472","spanId":"6ce8a75cc28892db","parentSpanId":"3a47f68bcaa4eedb","sampled":true,"kind":"internal","startTimeUnixNano":"1779352572857958875","endTimeUnixNano":"1779352572857974042","durationMs":0.015167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"5eed7d413ebbe1a518f4b325a2e25472","spanId":"3a47f68bcaa4eedb","parentSpanId":"74554fb4642f9ed9","sampled":true,"kind":"internal","startTimeUnixNano":"1779352572857816792","endTimeUnixNano":"1779352572859805334","durationMs":1.988542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"5eed7d413ebbe1a518f4b325a2e25472","spanId":"74554fb4642f9ed9","sampled":true,"kind":"internal","startTimeUnixNano":"1779352572857792750","endTimeUnixNano":"1779352572859826459","durationMs":2.033709,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"06206abdd01b19d3","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352575011897584","endTimeUnixNano":"1779352575069398792","durationMs":57.501208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"44dfab83399eb4d9","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352580071362417","endTimeUnixNano":"1779352580131572584","durationMs":60.210167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"8baf6f0e898dbbe6","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352585133543209","endTimeUnixNano":"1779352585189791750","durationMs":56.248541,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"e9d5bc02430a014e","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352590191293875","endTimeUnixNano":"1779352590233081709","durationMs":41.787834,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.server.updateSettings","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"8eaed89644c5b613","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"internal","startTimeUnixNano":"1779352590579310375","endTimeUnixNano":"1779352590583153625","durationMs":3.84325,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"server.updateSettings","rpc.aggregate":"server"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"1af96f90186939834425b9bfb7fdc818","spanId":"38dddd4b454cb288","parentSpanId":"575b57d73eed16fc","sampled":true,"kind":"client","startTimeUnixNano":"1779352590765404209","endTimeUnixNano":"1779352590765461834","durationMs":0.057625,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n session_id AS \"sessionId\",\n subject AS \"subject\",\n role AS \"role\",\n method AS \"method\",\n client_label AS \"clientLabel\",\n client_ip_address AS \"clientIpAddress\",\n client_user_agent AS \"clientUserAgent\",\n client_device_type AS \"clientDeviceType\",\n client_os AS \"clientOs\",\n client_browser AS \"clientBrowser\",\n issued_at AS \"issuedAt\",\n expires_at AS \"expiresAt\",\n last_connected_at AS \"lastConnectedAt\",\n revoked_at AS \"revokedAt\"\n FROM auth_sessions\n WHERE session_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"otlp-span","name":"RpcClient.server.updateSettings","traceId":"45011faa1c4c0fcda76dd89638f72012","spanId":"fe729432d88c82de","sampled":true,"kind":"internal","startTimeUnixNano":"1779352590676700000","endTimeUnixNano":"1779352590714700000","durationMs":38,"attributes":{},"resourceAttributes":{"service.runtime":"t3-web","service.mode":"electron","service.name":"t3-web","service.version":"0.0.24"},"scope":{"name":"t3-web","attributes":{}},"events":[],"links":[],"status":{"code":"1"}} -{"type":"effect-span","name":"http.server POST","traceId":"1af96f90186939834425b9bfb7fdc818","spanId":"575b57d73eed16fc","sampled":true,"kind":"server","startTimeUnixNano":"1779352590765258709","endTimeUnixNano":"1779352590766005417","durationMs":0.746708,"attributes":{"http.route":"/api/observability/v1/traces","http.request.method":"POST","url.full":"http://127.0.0.1:14124/api/observability/v1/traces","url.path":"/api/observability/v1/traces","url.scheme":"http","user_agent.original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"close","http.request.header.content-length":"699","http.request.header.sec-ch-ua-platform":"\"macOS\"","http.request.header.user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.sec-ch-ua":"\"Not-A.Brand\";v=\"24\", \"Chromium\";v=\"146\"","http.request.header.content-type":"application/json","http.request.header.sec-ch-ua-mobile":"?0","http.request.header.accept":"*/*","http.request.header.origin":"http://127.0.0.1:6084","http.request.header.sec-fetch-site":"same-origin","http.request.header.sec-fetch-mode":"cors","http.request.header.sec-fetch-dest":"empty","http.request.header.referer":"http://127.0.0.1:6084/","http.request.header.accept-encoding":"gzip, deflate, br, zstd","http.request.header.accept-language":"en-GB","http.request.header.cookie":"","http.response.status_code":204},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.server.updateSettings","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"165625f2d48d2473","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"internal","startTimeUnixNano":"1779352592241795375","endTimeUnixNano":"1779352592246618625","durationMs":4.82325,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"server.updateSettings","rpc.aggregate":"server"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.server.updateSettings","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"b86cf0fe06918a82","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"internal","startTimeUnixNano":"1779352592726607000","endTimeUnixNano":"1779352592730073334","durationMs":3.466334,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"server.updateSettings","rpc.aggregate":"server"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"e13a7a4c3f099f8f3ba2884e5e8f5229","spanId":"af4375bdc88abd89","parentSpanId":"7ef2a70ec417826a","sampled":true,"kind":"client","startTimeUnixNano":"1779352592769549709","endTimeUnixNano":"1779352592769608417","durationMs":0.058708,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n session_id AS \"sessionId\",\n subject AS \"subject\",\n role AS \"role\",\n method AS \"method\",\n client_label AS \"clientLabel\",\n client_ip_address AS \"clientIpAddress\",\n client_user_agent AS \"clientUserAgent\",\n client_device_type AS \"clientDeviceType\",\n client_os AS \"clientOs\",\n client_browser AS \"clientBrowser\",\n issued_at AS \"issuedAt\",\n expires_at AS \"expiresAt\",\n last_connected_at AS \"lastConnectedAt\",\n revoked_at AS \"revokedAt\"\n FROM auth_sessions\n WHERE session_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"otlp-span","name":"RpcClient.server.updateSettings","traceId":"a23cccf497f3b30add59d9508fd79874","spanId":"3c2c9cb420706c2b","sampled":true,"kind":"internal","startTimeUnixNano":"1779352592339900000","endTimeUnixNano":"1779352592355600000","durationMs":15.7,"attributes":{},"resourceAttributes":{"service.runtime":"t3-web","service.mode":"electron","service.name":"t3-web","service.version":"0.0.24"},"scope":{"name":"t3-web","attributes":{}},"events":[],"links":[],"status":{"code":"1"}} -{"type":"otlp-span","name":"RpcClient.server.updateSettings","traceId":"0e2eeef759125a6b58eb1f9f57cf21d6","spanId":"d2aa9739f3eedffc","sampled":true,"kind":"internal","startTimeUnixNano":"1779352592825300000","endTimeUnixNano":"1779352592844400000","durationMs":19.1,"attributes":{},"resourceAttributes":{"service.runtime":"t3-web","service.mode":"electron","service.name":"t3-web","service.version":"0.0.24"},"scope":{"name":"t3-web","attributes":{}},"events":[],"links":[],"status":{"code":"1"}} -{"type":"effect-span","name":"http.server POST","traceId":"e13a7a4c3f099f8f3ba2884e5e8f5229","spanId":"7ef2a70ec417826a","sampled":true,"kind":"server","startTimeUnixNano":"1779352592769412709","endTimeUnixNano":"1779352592769844959","durationMs":0.43225,"attributes":{"http.route":"/api/observability/v1/traces","http.request.method":"POST","url.full":"http://127.0.0.1:14124/api/observability/v1/traces","url.path":"/api/observability/v1/traces","url.scheme":"http","user_agent.original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"close","http.request.header.content-length":"1037","http.request.header.sec-ch-ua-platform":"\"macOS\"","http.request.header.user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.sec-ch-ua":"\"Not-A.Brand\";v=\"24\", \"Chromium\";v=\"146\"","http.request.header.content-type":"application/json","http.request.header.sec-ch-ua-mobile":"?0","http.request.header.accept":"*/*","http.request.header.origin":"http://127.0.0.1:6084","http.request.header.sec-fetch-site":"same-origin","http.request.header.sec-fetch-mode":"cors","http.request.header.sec-fetch-dest":"empty","http.request.header.referer":"http://127.0.0.1:6084/","http.request.header.accept-encoding":"gzip, deflate, br, zstd","http.request.header.accept-language":"en-GB","http.request.header.cookie":"","http.response.status_code":204},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"cd6ae443ce902504","parentSpanId":"52ae721a0e7fe74c","sampled":true,"kind":"internal","startTimeUnixNano":"1779352594495973292","endTimeUnixNano":"1779352594497657209","durationMs":1.683917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"ProcessSpawnError: \n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14166:38\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/effect.js:1309:96\n at ~effect/Utils/internal (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Utils.js:69:12)\n at processRunner.runProcessCore (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14219:44)\n at processRunner.runProcessCore (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14155:31)\n at VcsProcess.run (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:24401:18)\n at VcsProcess.run (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19834:21)\n at ws.rpc.server.discoverSourceControl (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:17831:111) {\n [cause]: PlatformError: NotFound: ChildProcess.spawn (jj --version)\n at Module.systemError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/PlatformError.js:59:39)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/internal/utils.js:28:24\n at toPlatformError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:25:54)\n at ChildProcess. (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:230:26)\n at ChildProcess.emit (node:events:509:28)\n at ChildProcess._handle.onexit (node:internal/child_process:293:12)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {\n [cause]: Error: spawn jj ENOENT\n at ChildProcess._handle.onexit (node:internal/child_process:287:19)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n }\n}"}} -{"type":"effect-span","name":"VcsProcess.run","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"52ae721a0e7fe74c","parentSpanId":"c9bd1160ed07b6db","sampled":true,"kind":"internal","startTimeUnixNano":"1779352594495953417","endTimeUnixNano":"1779352594497961250","durationMs":2.007833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"VcsProcessSpawnError: VCS process failed to spawn in source-control.discovery.probe: jj --version (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69)\n at VcsProcessSpawnError.fromProcessSpawnError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:3950:10)\n at Object.ProcessSpawnError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19854:55)\n at Object.evaluate (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:170:101)\n at i (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:236:37)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:281:20\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:133:10\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Function.js:97:18\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/effect.js:1309:96\n at ~effect/Utils/internal (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Utils.js:69:12)\n at VcsProcess.run (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:24401:18)\n at VcsProcess.run (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19834:21)\n at ws.rpc.server.discoverSourceControl (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:17831:111) {\n [cause]: PlatformError: NotFound: ChildProcess.spawn (jj --version)\n at Module.systemError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/PlatformError.js:59:39)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/internal/utils.js:28:24\n at toPlatformError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:25:54)\n at ChildProcess. (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:230:26)\n at ChildProcess.emit (node:events:509:28)\n at ChildProcess._handle.onexit (node:internal/child_process:293:12)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {\n [cause]: Error: spawn jj ENOENT\n at ChildProcess._handle.onexit (node:internal/child_process:287:19)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n }\n}"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"8acd457f459801b4","parentSpanId":"79c02664a32d08db","sampled":true,"kind":"internal","startTimeUnixNano":"1779352594496592750","endTimeUnixNano":"1779352594500852125","durationMs":4.259375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"d3e7537a8a2cfaa4","parentSpanId":"79c02664a32d08db","sampled":true,"kind":"internal","startTimeUnixNano":"1779352594496562750","endTimeUnixNano":"1779352594500896667","durationMs":4.333917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"79c02664a32d08db","parentSpanId":"7615e74e72cfd0ae","sampled":true,"kind":"internal","startTimeUnixNano":"1779352594495908542","endTimeUnixNano":"1779352594500924417","durationMs":5.015875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProcess.run","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"7615e74e72cfd0ae","parentSpanId":"c9bd1160ed07b6db","sampled":true,"kind":"internal","startTimeUnixNano":"1779352594495861292","endTimeUnixNano":"1779352594500977875","durationMs":5.116583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"2eaadc40ada59487","parentSpanId":"234dc3c3cc2e389a","sampled":true,"kind":"internal","startTimeUnixNano":"1779352594501168917","endTimeUnixNano":"1779352594503909042","durationMs":2.740125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"ProcessSpawnError: \n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14166:38\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/effect.js:1309:96\n at ~effect/Utils/internal (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Utils.js:69:12)\n at processRunner.runProcessCore (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14219:44)\n at processRunner.runProcessCore (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14155:31)\n at VcsProcess.run (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:20703:23)\n at VcsProcess.run (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19834:21)\n at ws.rpc.server.discoverSourceControl (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:17831:111) {\n [cause]: PlatformError: NotFound: ChildProcess.spawn (glab --version)\n at Module.systemError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/PlatformError.js:59:39)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/internal/utils.js:28:24\n at toPlatformError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:25:54)\n at ChildProcess. (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:230:26)\n at ChildProcess.emit (node:events:509:28)\n at ChildProcess._handle.onexit (node:internal/child_process:293:12)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {\n [cause]: Error: spawn glab ENOENT\n at ChildProcess._handle.onexit (node:internal/child_process:287:19)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n }\n}"}} -{"type":"effect-span","name":"VcsProcess.run","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"234dc3c3cc2e389a","parentSpanId":"c9bd1160ed07b6db","sampled":true,"kind":"internal","startTimeUnixNano":"1779352594501151625","endTimeUnixNano":"1779352594504053167","durationMs":2.901542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"VcsProcessSpawnError: VCS process failed to spawn in source-control.discovery.probe: glab --version (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69)\n at VcsProcessSpawnError.fromProcessSpawnError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:3950:10)\n at Object.ProcessSpawnError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19854:55)\n at Object.evaluate (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:170:101)\n at i (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:236:37)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:281:20\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:133:10\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Function.js:97:18\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/effect.js:1309:96\n at ~effect/Utils/internal (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Utils.js:69:12)\n at VcsProcess.run (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:20703:23)\n at VcsProcess.run (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19834:21)\n at ws.rpc.server.discoverSourceControl (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:17831:111) {\n [cause]: PlatformError: NotFound: ChildProcess.spawn (glab --version)\n at Module.systemError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/PlatformError.js:59:39)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/internal/utils.js:28:24\n at toPlatformError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:25:54)\n at ChildProcess. (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:230:26)\n at ChildProcess.emit (node:events:509:28)\n at ChildProcess._handle.onexit (node:internal/child_process:293:12)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {\n [cause]: Error: spawn glab ENOENT\n at ChildProcess._handle.onexit (node:internal/child_process:287:19)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n }\n}"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"d305fb631d6ab259","parentSpanId":"bf73bd0707c5129e","sampled":true,"kind":"internal","startTimeUnixNano":"1779352594501197459","endTimeUnixNano":"1779352594506166667","durationMs":4.969208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"ProcessSpawnError: \n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14166:38\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/effect.js:1309:96\n at ~effect/Utils/internal (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Utils.js:69:12)\n at processRunner.runProcessCore (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14219:44)\n at processRunner.runProcessCore (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14155:31)\n at VcsProcess.run (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:20703:23)\n at VcsProcess.run (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19834:21)\n at ws.rpc.server.discoverSourceControl (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:17831:111) {\n [cause]: PlatformError: NotFound: ChildProcess.spawn (az --version)\n at Module.systemError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/PlatformError.js:59:39)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/internal/utils.js:28:24\n at toPlatformError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:25:54)\n at ChildProcess. (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:230:26)\n at ChildProcess.emit (node:events:509:28)\n at ChildProcess._handle.onexit (node:internal/child_process:293:12)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {\n [cause]: Error: spawn az ENOENT\n at ChildProcess._handle.onexit (node:internal/child_process:287:19)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n }\n}"}} -{"type":"effect-span","name":"VcsProcess.run","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"bf73bd0707c5129e","parentSpanId":"c9bd1160ed07b6db","sampled":true,"kind":"internal","startTimeUnixNano":"1779352594501182334","endTimeUnixNano":"1779352594506371917","durationMs":5.189583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"VcsProcessSpawnError: VCS process failed to spawn in source-control.discovery.probe: az --version (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69)\n at VcsProcessSpawnError.fromProcessSpawnError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:3950:10)\n at Object.ProcessSpawnError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19854:55)\n at Object.evaluate (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:170:101)\n at i (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:236:37)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:281:20\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:133:10\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Function.js:97:18\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/effect.js:1309:96\n at ~effect/Utils/internal (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Utils.js:69:12)\n at VcsProcess.run (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:20703:23)\n at VcsProcess.run (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19834:21)\n at ws.rpc.server.discoverSourceControl (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:17831:111) {\n [cause]: PlatformError: NotFound: ChildProcess.spawn (az --version)\n at Module.systemError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/PlatformError.js:59:39)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/internal/utils.js:28:24\n at toPlatformError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:25:54)\n at ChildProcess. (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:230:26)\n at ChildProcess.emit (node:events:509:28)\n at ChildProcess._handle.onexit (node:internal/child_process:293:12)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {\n [cause]: Error: spawn az ENOENT\n at ChildProcess._handle.onexit (node:internal/child_process:287:19)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n }\n}"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"92be84aa50541b46","parentSpanId":"a7de47eba4f16df9","sampled":true,"kind":"internal","startTimeUnixNano":"1779352594503081917","endTimeUnixNano":"1779352594523999542","durationMs":20.917625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"9eadf420998cb3f4","parentSpanId":"a7de47eba4f16df9","sampled":true,"kind":"internal","startTimeUnixNano":"1779352594503055584","endTimeUnixNano":"1779352594524056917","durationMs":21.001333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"a7de47eba4f16df9","parentSpanId":"59508ad1eea94b0b","sampled":true,"kind":"internal","startTimeUnixNano":"1779352594501119000","endTimeUnixNano":"1779352594524091084","durationMs":22.972084,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProcess.run","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"59508ad1eea94b0b","parentSpanId":"c9bd1160ed07b6db","sampled":true,"kind":"internal","startTimeUnixNano":"1779352594501079375","endTimeUnixNano":"1779352594524142250","durationMs":23.062875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"http.client GET","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"c35c0edaa583c59f","parentSpanId":"c9bd1160ed07b6db","sampled":true,"kind":"client","startTimeUnixNano":"1779352594501365084","endTimeUnixNano":"1779352594821299875","durationMs":319.934791,"attributes":{"http.request.method":"GET","server.address":"https://api.bitbucket.org","url.full":"https://api.bitbucket.org/2.0/user","url.path":"/2.0/user","url.scheme":"https","http.request.header.accept":"application/json","http.response.status_code":401,"http.response.header.age":"0","http.response.header.atl-request-id":"232a1e70-999d-4f22-b18f-1dc269966338","http.response.header.atl-traceid":"232a1e70999d4f22b18f1dc269966338","http.response.header.content-length":"0","http.response.header.content-type":"text/html; charset=utf-8","http.response.header.date":"Thu, 21 May 2026 08:36:34 GMT","http.response.header.nel":"{\"failure_fraction\": 0.01, \"include_subdomains\": true, \"max_age\": 600, \"report_to\": \"endpoint-1\"}","http.response.header.report-to":"{\"endpoints\": [{\"url\": \"https://dz8aopenkvv6s.cloudfront.net\"}], \"group\": \"endpoint-1\", \"include_subdomains\": true, \"max_age\": 600}","http.response.header.server":"AtlassianEdge","http.response.header.server-timing":"atl-edge;dur=274,atl-edge-internal;dur=7,atl-edge-upstream;dur=268,atl-edge-pop;desc=\"aws-ap-southeast-2\"","http.response.header.strict-transport-security":"max-age=63072000; includeSubDomains; preload","http.response.header.vary":"Authorization, origin","http.response.header.www-authenticate":"BitbucketCustom realm=Bitbucket.org HTTP","http.response.header.x-accepted-oauth-scopes":"account","http.response.header.x-asap-succeeded":"True","http.response.header.x-b3-spanid":"9269c668df094492","http.response.header.x-b3-traceid":"232a1e70999d4f22b18f1dc269966338","http.response.header.x-cache":"MISS","http.response.header.x-content-type-options":"nosniff","http.response.header.x-credential-type":"unauthenticated_identity","http.response.header.x-dc-location":"Micros-3","http.response.header.x-envoy-attempt-count":"1","http.response.header.x-frame-options":"SAMEORIGIN","http.response.header.x-ratelimit-limit":"60, 60;w=3600","http.response.header.x-ratelimit-remaining":"57","http.response.header.x-ratelimit-reset":"1406","http.response.header.x-render-time":"0.02318286895751953","http.response.header.x-request-count":"2171","http.response.header.x-served-by":"2560bed39b85","http.response.header.x-static-version":"51d05f3ab3e8","http.response.header.x-usage-input-ops":"0","http.response.header.x-usage-output-ops":"0","http.response.header.x-usage-system-time":"0.003688","http.response.header.x-usage-user-time":"0.029977","http.response.header.x-used-mesh":"False","http.response.header.x-version":"51d05f3ab3e8","http.response.header.x-view-name":"bitbucket.apps.bb.api.v20.handlers.CurrentUserHandler","http.response.header.x-xss-protection":"1; mode=block"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"e4e52f9759fc4ddc","parentSpanId":"580aeb0df33d4058","sampled":true,"kind":"internal","startTimeUnixNano":"1779352594524962209","endTimeUnixNano":"1779352594952643875","durationMs":427.681666,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"7a734667301241c8","parentSpanId":"580aeb0df33d4058","sampled":true,"kind":"internal","startTimeUnixNano":"1779352594524935167","endTimeUnixNano":"1779352594952727834","durationMs":427.792667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"580aeb0df33d4058","parentSpanId":"fe8962fe375c24cb","sampled":true,"kind":"internal","startTimeUnixNano":"1779352594524262292","endTimeUnixNano":"1779352594952780709","durationMs":428.518417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProcess.run","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"fe8962fe375c24cb","parentSpanId":"c9bd1160ed07b6db","sampled":true,"kind":"internal","startTimeUnixNano":"1779352594524228000","endTimeUnixNano":"1779352594952859334","durationMs":428.631334,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.server.discoverSourceControl","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"c9bd1160ed07b6db","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"internal","startTimeUnixNano":"1779352594495784667","endTimeUnixNano":"1779352594953448250","durationMs":457.663583,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"server.discoverSourceControl","rpc.aggregate":"server"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"2a57e16f584010ce","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352595235114209","endTimeUnixNano":"1779352595287948167","durationMs":52.833958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"f151bbec4885194b54ac344605cec410","spanId":"953f9d5ebe45187a","parentSpanId":"039c56e6a1394ef7","sampled":true,"kind":"client","startTimeUnixNano":"1779352595780690500","endTimeUnixNano":"1779352595780913084","durationMs":0.222584,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n session_id AS \"sessionId\",\n subject AS \"subject\",\n role AS \"role\",\n method AS \"method\",\n client_label AS \"clientLabel\",\n client_ip_address AS \"clientIpAddress\",\n client_user_agent AS \"clientUserAgent\",\n client_device_type AS \"clientDeviceType\",\n client_os AS \"clientOs\",\n client_browser AS \"clientBrowser\",\n issued_at AS \"issuedAt\",\n expires_at AS \"expiresAt\",\n last_connected_at AS \"lastConnectedAt\",\n revoked_at AS \"revokedAt\"\n FROM auth_sessions\n WHERE session_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"otlp-span","name":"RpcClient.server.discoverSourceControl","traceId":"f5bb312ea7f3e67c69360c22edd3e8e8","spanId":"27adf64ffe0bfc83","sampled":true,"kind":"internal","startTimeUnixNano":"1779352594594600000","endTimeUnixNano":"1779352595054400000","durationMs":459.8,"attributes":{},"resourceAttributes":{"service.runtime":"t3-web","service.mode":"electron","service.name":"t3-web","service.version":"0.0.24"},"scope":{"name":"t3-web","attributes":{}},"events":[],"links":[],"status":{"code":"1"}} -{"type":"effect-span","name":"http.server POST","traceId":"f151bbec4885194b54ac344605cec410","spanId":"039c56e6a1394ef7","sampled":true,"kind":"server","startTimeUnixNano":"1779352595780202417","endTimeUnixNano":"1779352595781791500","durationMs":1.589083,"attributes":{"http.route":"/api/observability/v1/traces","http.request.method":"POST","url.full":"http://127.0.0.1:14124/api/observability/v1/traces","url.path":"/api/observability/v1/traces","url.scheme":"http","user_agent.original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"close","http.request.header.content-length":"706","http.request.header.sec-ch-ua-platform":"\"macOS\"","http.request.header.user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.sec-ch-ua":"\"Not-A.Brand\";v=\"24\", \"Chromium\";v=\"146\"","http.request.header.content-type":"application/json","http.request.header.sec-ch-ua-mobile":"?0","http.request.header.accept":"*/*","http.request.header.origin":"http://127.0.0.1:6084","http.request.header.sec-fetch-site":"same-origin","http.request.header.sec-fetch-mode":"cors","http.request.header.sec-fetch-dest":"empty","http.request.header.referer":"http://127.0.0.1:6084/","http.request.header.accept-encoding":"gzip, deflate, br, zstd","http.request.header.accept-language":"en-GB","http.request.header.cookie":"","http.response.status_code":204},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"WorkspaceEntries.browse","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"2625d10e18b26780","parentSpanId":"e615bcb4d6f603a1","sampled":true,"kind":"internal","startTimeUnixNano":"1779352595857055959","endTimeUnixNano":"1779352595857509709","durationMs":0.45375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.filesystem.browse","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"e615bcb4d6f603a1","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"internal","startTimeUnixNano":"1779352595857020042","endTimeUnixNano":"1779352595857569834","durationMs":0.549792,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"filesystem.browse","rpc.aggregate":"workspace"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"WorkspaceEntries.browse","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"0fd3a67b27e172aa","parentSpanId":"2190f24f34a653b1","sampled":true,"kind":"internal","startTimeUnixNano":"1779352596221267917","endTimeUnixNano":"1779352596221548042","durationMs":0.280125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.filesystem.browse","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"2190f24f34a653b1","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"internal","startTimeUnixNano":"1779352596221228917","endTimeUnixNano":"1779352596221616584","durationMs":0.387667,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"filesystem.browse","rpc.aggregate":"workspace"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"WorkspaceEntries.browse","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"4ae7970dd9dcd866","parentSpanId":"6afb329c4587c402","sampled":true,"kind":"internal","startTimeUnixNano":"1779352596383921375","endTimeUnixNano":"1779352596384149875","durationMs":0.2285,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.filesystem.browse","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"6afb329c4587c402","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"internal","startTimeUnixNano":"1779352596383881834","endTimeUnixNano":"1779352596384207500","durationMs":0.325666,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"filesystem.browse","rpc.aggregate":"workspace"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"278fc072115a0d077134f9f1d55b9a34","spanId":"e63a541e693f45d0","parentSpanId":"0cbcdc4b194fc27d","sampled":true,"kind":"client","startTimeUnixNano":"1779352596790714042","endTimeUnixNano":"1779352596790922667","durationMs":0.208625,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n session_id AS \"sessionId\",\n subject AS \"subject\",\n role AS \"role\",\n method AS \"method\",\n client_label AS \"clientLabel\",\n client_ip_address AS \"clientIpAddress\",\n client_user_agent AS \"clientUserAgent\",\n client_device_type AS \"clientDeviceType\",\n client_os AS \"clientOs\",\n client_browser AS \"clientBrowser\",\n issued_at AS \"issuedAt\",\n expires_at AS \"expiresAt\",\n last_connected_at AS \"lastConnectedAt\",\n revoked_at AS \"revokedAt\"\n FROM auth_sessions\n WHERE session_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"otlp-span","name":"RpcClient.filesystem.browse","traceId":"18c2b4224e94bd66c6cfdfd5dd049d3d","spanId":"44dfe24e63eed359","sampled":true,"kind":"internal","startTimeUnixNano":"1779352595955800000","endTimeUnixNano":"1779352595970100000","durationMs":14.3,"attributes":{},"resourceAttributes":{"service.runtime":"t3-web","service.mode":"electron","service.name":"t3-web","service.version":"0.0.24"},"scope":{"name":"t3-web","attributes":{}},"events":[],"links":[],"status":{"code":"1"}} -{"type":"otlp-span","name":"RpcClient.filesystem.browse","traceId":"e50068804beed5ab98b2c034dbfd363d","spanId":"6be3b3bb1fe961ed","sampled":true,"kind":"internal","startTimeUnixNano":"1779352596320300000","endTimeUnixNano":"1779352596322300000","durationMs":2,"attributes":{},"resourceAttributes":{"service.runtime":"t3-web","service.mode":"electron","service.name":"t3-web","service.version":"0.0.24"},"scope":{"name":"t3-web","attributes":{}},"events":[],"links":[],"status":{"code":"1"}} -{"type":"otlp-span","name":"RpcClient.filesystem.browse","traceId":"4f988004e2ce53d2ac593a489e5e14ac","spanId":"b8dd4db41588cafa","sampled":true,"kind":"internal","startTimeUnixNano":"1779352596483000000","endTimeUnixNano":"1779352596485900000","durationMs":2.9,"attributes":{},"resourceAttributes":{"service.runtime":"t3-web","service.mode":"electron","service.name":"t3-web","service.version":"0.0.24"},"scope":{"name":"t3-web","attributes":{}},"events":[],"links":[],"status":{"code":"1"}} -{"type":"effect-span","name":"http.server POST","traceId":"278fc072115a0d077134f9f1d55b9a34","spanId":"0cbcdc4b194fc27d","sampled":true,"kind":"server","startTimeUnixNano":"1779352596790252709","endTimeUnixNano":"1779352596791777500","durationMs":1.524791,"attributes":{"http.route":"/api/observability/v1/traces","http.request.method":"POST","url.full":"http://127.0.0.1:14124/api/observability/v1/traces","url.path":"/api/observability/v1/traces","url.scheme":"http","user_agent.original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"close","http.request.header.content-length":"1363","http.request.header.sec-ch-ua-platform":"\"macOS\"","http.request.header.user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.sec-ch-ua":"\"Not-A.Brand\";v=\"24\", \"Chromium\";v=\"146\"","http.request.header.content-type":"application/json","http.request.header.sec-ch-ua-mobile":"?0","http.request.header.accept":"*/*","http.request.header.origin":"http://127.0.0.1:6084","http.request.header.sec-fetch-site":"same-origin","http.request.header.sec-fetch-mode":"cors","http.request.header.sec-fetch-dest":"empty","http.request.header.referer":"http://127.0.0.1:6084/","http.request.header.accept-encoding":"gzip, deflate, br, zstd","http.request.header.accept-language":"en-GB","http.request.header.cookie":"","http.response.status_code":204},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"WorkspaceEntries.browse","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"35b0927681b5447c","parentSpanId":"98eebeb8f755ae00","sampled":true,"kind":"internal","startTimeUnixNano":"1779352597354265459","endTimeUnixNano":"1779352597354477542","durationMs":0.212083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.filesystem.browse","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"98eebeb8f755ae00","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"internal","startTimeUnixNano":"1779352597354222209","endTimeUnixNano":"1779352597354554750","durationMs":0.332541,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"filesystem.browse","rpc.aggregate":"workspace"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"878eae30343adc0fa5499a5a8bd96a68","spanId":"cc1145115163bf94","parentSpanId":"4fd592a28d77a865","sampled":true,"kind":"client","startTimeUnixNano":"1779352597800319125","endTimeUnixNano":"1779352597800510417","durationMs":0.191292,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n session_id AS \"sessionId\",\n subject AS \"subject\",\n role AS \"role\",\n method AS \"method\",\n client_label AS \"clientLabel\",\n client_ip_address AS \"clientIpAddress\",\n client_user_agent AS \"clientUserAgent\",\n client_device_type AS \"clientDeviceType\",\n client_os AS \"clientOs\",\n client_browser AS \"clientBrowser\",\n issued_at AS \"issuedAt\",\n expires_at AS \"expiresAt\",\n last_connected_at AS \"lastConnectedAt\",\n revoked_at AS \"revokedAt\"\n FROM auth_sessions\n WHERE session_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"otlp-span","name":"RpcClient.filesystem.browse","traceId":"f3d5030e17902aeea6d86b922736f8e4","spanId":"de2e81bfa55c17ff","sampled":true,"kind":"internal","startTimeUnixNano":"1779352597453200000","endTimeUnixNano":"1779352597454800000","durationMs":1.6,"attributes":{},"resourceAttributes":{"service.runtime":"t3-web","service.mode":"electron","service.name":"t3-web","service.version":"0.0.24"},"scope":{"name":"t3-web","attributes":{}},"events":[],"links":[],"status":{"code":"1"}} -{"type":"effect-span","name":"http.server POST","traceId":"878eae30343adc0fa5499a5a8bd96a68","spanId":"4fd592a28d77a865","sampled":true,"kind":"server","startTimeUnixNano":"1779352597799867250","endTimeUnixNano":"1779352597801221667","durationMs":1.354417,"attributes":{"http.route":"/api/observability/v1/traces","http.request.method":"POST","url.full":"http://127.0.0.1:14124/api/observability/v1/traces","url.path":"/api/observability/v1/traces","url.scheme":"http","user_agent.original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"close","http.request.header.content-length":"695","http.request.header.sec-ch-ua-platform":"\"macOS\"","http.request.header.user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.sec-ch-ua":"\"Not-A.Brand\";v=\"24\", \"Chromium\";v=\"146\"","http.request.header.content-type":"application/json","http.request.header.sec-ch-ua-mobile":"?0","http.request.header.accept":"*/*","http.request.header.origin":"http://127.0.0.1:6084","http.request.header.sec-fetch-site":"same-origin","http.request.header.sec-fetch-mode":"cors","http.request.header.sec-fetch-dest":"empty","http.request.header.referer":"http://127.0.0.1:6084/","http.request.header.accept-encoding":"gzip, deflate, br, zstd","http.request.header.accept-language":"en-GB","http.request.header.cookie":"","http.response.status_code":204},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"f34d8fcc1e37bb66","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600289129750","endTimeUnixNano":"1779352600347419792","durationMs":58.290042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"WorkspacePaths.normalizeWorkspaceRoot","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"81bd565a30cc276b","parentSpanId":"d045f4d30c8ff39d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600716113667","endTimeUnixNano":"1779352600717346917","durationMs":1.23325,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"0c05b7d02fc30c28","parentSpanId":"c8153f095f61e84a","sampled":true,"kind":"client","startTimeUnixNano":"1779352600718315334","endTimeUnixNano":"1779352600718616125","durationMs":0.300791,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n command_id AS \"commandId\",\n aggregate_kind AS \"aggregateKind\",\n aggregate_id AS \"aggregateId\",\n accepted_at AS \"acceptedAt\",\n result_sequence AS \"resultSequence\",\n status,\n error\n FROM orchestration_command_receipts\n WHERE command_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"decideOrchestrationCommand","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"23a6e8b1ce677d95","parentSpanId":"c8153f095f61e84a","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600718684625","endTimeUnixNano":"1779352600718949875","durationMs":0.26525,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"befca34322ba7ce8","parentSpanId":"28a890bb3742e47c","sampled":true,"kind":"client","startTimeUnixNano":"1779352600719486042","endTimeUnixNano":"1779352600719894584","durationMs":0.408542,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n INSERT INTO orchestration_events (\n event_id,\n aggregate_kind,\n stream_id,\n stream_version,\n event_type,\n occurred_at,\n command_id,\n causation_event_id,\n correlation_id,\n actor_kind,\n payload_json,\n metadata_json\n )\n VALUES (\n ?,\n ?,\n ?,\n COALESCE(\n (\n SELECT stream_version + 1\n FROM orchestration_events\n WHERE aggregate_kind = ?\n AND stream_id = ?\n ORDER BY stream_version DESC\n LIMIT 1\n ),\n 0\n ),\n ?,\n ?,\n ?,\n ?,\n ?,\n ?,\n ?,\n ?\n )\n RETURNING\n sequence,\n event_id AS \"eventId\",\n event_type AS \"type\",\n aggregate_kind AS \"aggregateKind\",\n stream_id AS \"aggregateId\",\n occurred_at AS \"occurredAt\",\n command_id AS \"commandId\",\n causation_event_id AS \"causationEventId\",\n correlation_id AS \"correlationId\",\n payload_json AS \"payload\",\n metadata_json AS \"metadata\"\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"eb1f7930747306f5","parentSpanId":"e99e3725e1d95fed","sampled":true,"kind":"client","startTimeUnixNano":"1779352600721049375","endTimeUnixNano":"1779352600721215084","durationMs":0.165709,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n INSERT INTO projection_projects (\n project_id,\n title,\n workspace_root,\n default_model_selection_json,\n scripts_json,\n created_at,\n updated_at,\n deleted_at\n )\n VALUES (\n ?,\n ?,\n ?,\n ?,\n ?,\n ?,\n ?,\n ?\n )\n ON CONFLICT (project_id)\n DO UPDATE SET\n title = excluded.title,\n workspace_root = excluded.workspace_root,\n default_model_selection_json = excluded.default_model_selection_json,\n scripts_json = excluded.scripts_json,\n created_at = excluded.created_at,\n updated_at = excluded.updated_at,\n deleted_at = excluded.deleted_at\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProjectsProjection","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"e99e3725e1d95fed","parentSpanId":"4e609f5881f57954","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600720854500","endTimeUnixNano":"1779352600721249667","durationMs":0.395167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"64fc822c212c7a74","parentSpanId":"4e609f5881f57954","sampled":true,"kind":"client","startTimeUnixNano":"1779352600721303709","endTimeUnixNano":"1779352600721418375","durationMs":0.114666,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n INSERT INTO projection_state (\n projector,\n last_applied_sequence,\n updated_at\n )\n VALUES (\n ?,\n ?,\n ?\n )\n ON CONFLICT (projector)\n DO UPDATE SET\n last_applied_sequence = excluded.last_applied_sequence,\n updated_at = excluded.updated_at\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.transaction","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"4e609f5881f57954","parentSpanId":"96eada97f68400c9","sampled":true,"kind":"client","startTimeUnixNano":"1779352600720792000","endTimeUnixNano":"1779352600721446000","durationMs":0.654,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite"},"events":[{"name":"db.transaction.savepoint","timeUnixNano":"1779352600721440625","attributes":{}}],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runAttachmentSideEffects","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"bd97c39655b61b5a","parentSpanId":"96eada97f68400c9","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600721490125","endTimeUnixNano":"1779352600721649209","durationMs":0.159084,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProjectorForEvent","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"96eada97f68400c9","parentSpanId":"28a890bb3742e47c","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600720762542","endTimeUnixNano":"1779352600721667042","durationMs":0.9045,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyThreadMessagesProjection","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"1ff4da8b4d254c71","parentSpanId":"6f6ebcfce5ebd5a8","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600721775500","endTimeUnixNano":"1779352600721790959","durationMs":0.015459,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"916b5b360db14515","parentSpanId":"6f6ebcfce5ebd5a8","sampled":true,"kind":"client","startTimeUnixNano":"1779352600721885084","endTimeUnixNano":"1779352600721938959","durationMs":0.053875,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n INSERT INTO projection_state (\n projector,\n last_applied_sequence,\n updated_at\n )\n VALUES (\n ?,\n ?,\n ?\n )\n ON CONFLICT (projector)\n DO UPDATE SET\n last_applied_sequence = excluded.last_applied_sequence,\n updated_at = excluded.updated_at\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.transaction","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"6f6ebcfce5ebd5a8","parentSpanId":"d68764632f1f362b","sampled":true,"kind":"client","startTimeUnixNano":"1779352600721717375","endTimeUnixNano":"1779352600721958084","durationMs":0.240709,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite"},"events":[{"name":"db.transaction.savepoint","timeUnixNano":"1779352600721955209","attributes":{}}],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runAttachmentSideEffects","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"c0614cdb05ede464","parentSpanId":"d68764632f1f362b","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600721982584","endTimeUnixNano":"1779352600722029709","durationMs":0.047125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProjectorForEvent","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"d68764632f1f362b","parentSpanId":"28a890bb3742e47c","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600721695959","endTimeUnixNano":"1779352600722038167","durationMs":0.342208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyThreadProposedPlansProjection","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"0ed0220f56453dc1","parentSpanId":"95b7c8c5600ed514","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600722106209","endTimeUnixNano":"1779352600722118750","durationMs":0.012541,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"cea8b720ccc2984a","parentSpanId":"95b7c8c5600ed514","sampled":true,"kind":"client","startTimeUnixNano":"1779352600722134250","endTimeUnixNano":"1779352600722166500","durationMs":0.03225,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n INSERT INTO projection_state (\n projector,\n last_applied_sequence,\n updated_at\n )\n VALUES (\n ?,\n ?,\n ?\n )\n ON CONFLICT (projector)\n DO UPDATE SET\n last_applied_sequence = excluded.last_applied_sequence,\n updated_at = excluded.updated_at\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.transaction","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"95b7c8c5600ed514","parentSpanId":"400613d3ae488e38","sampled":true,"kind":"client","startTimeUnixNano":"1779352600722067292","endTimeUnixNano":"1779352600722179000","durationMs":0.111708,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite"},"events":[{"name":"db.transaction.savepoint","timeUnixNano":"1779352600722177250","attributes":{}}],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runAttachmentSideEffects","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"106ce6443f116e88","parentSpanId":"400613d3ae488e38","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600722197667","endTimeUnixNano":"1779352600722227875","durationMs":0.030208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProjectorForEvent","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"400613d3ae488e38","parentSpanId":"28a890bb3742e47c","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600722053250","endTimeUnixNano":"1779352600722234917","durationMs":0.181667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyThreadActivitiesProjection","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"55126ec43720fc6b","parentSpanId":"3e2070e70f1c2f16","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600722293459","endTimeUnixNano":"1779352600722304375","durationMs":0.010916,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"aa89cc3387fbbe97","parentSpanId":"3e2070e70f1c2f16","sampled":true,"kind":"client","startTimeUnixNano":"1779352600722318417","endTimeUnixNano":"1779352600722433542","durationMs":0.115125,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n INSERT INTO projection_state (\n projector,\n last_applied_sequence,\n updated_at\n )\n VALUES (\n ?,\n ?,\n ?\n )\n ON CONFLICT (projector)\n DO UPDATE SET\n last_applied_sequence = excluded.last_applied_sequence,\n updated_at = excluded.updated_at\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.transaction","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"3e2070e70f1c2f16","parentSpanId":"5a78158ffecaabbf","sampled":true,"kind":"client","startTimeUnixNano":"1779352600722260709","endTimeUnixNano":"1779352600722478542","durationMs":0.217833,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite"},"events":[{"name":"db.transaction.savepoint","timeUnixNano":"1779352600722474042","attributes":{}}],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runAttachmentSideEffects","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"60fe6810d03ad2cc","parentSpanId":"5a78158ffecaabbf","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600722556209","endTimeUnixNano":"1779352600722638000","durationMs":0.081791,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProjectorForEvent","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"5a78158ffecaabbf","parentSpanId":"28a890bb3742e47c","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600722248584","endTimeUnixNano":"1779352600722655375","durationMs":0.406791,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyThreadSessionsProjection","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"76de7ded05e25e17","parentSpanId":"758f88207540d1a5","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600722761209","endTimeUnixNano":"1779352600722787750","durationMs":0.026541,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"21562861a1a75ada","parentSpanId":"758f88207540d1a5","sampled":true,"kind":"client","startTimeUnixNano":"1779352600722828000","endTimeUnixNano":"1779352600722901375","durationMs":0.073375,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n INSERT INTO projection_state (\n projector,\n last_applied_sequence,\n updated_at\n )\n VALUES (\n ?,\n ?,\n ?\n )\n ON CONFLICT (projector)\n DO UPDATE SET\n last_applied_sequence = excluded.last_applied_sequence,\n updated_at = excluded.updated_at\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.transaction","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"758f88207540d1a5","parentSpanId":"b7fc245bd12262fd","sampled":true,"kind":"client","startTimeUnixNano":"1779352600722704750","endTimeUnixNano":"1779352600722922000","durationMs":0.21725,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite"},"events":[{"name":"db.transaction.savepoint","timeUnixNano":"1779352600722919709","attributes":{}}],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runAttachmentSideEffects","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"f7f1be19d3207809","parentSpanId":"b7fc245bd12262fd","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600722949250","endTimeUnixNano":"1779352600723003334","durationMs":0.054084,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProjectorForEvent","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"b7fc245bd12262fd","parentSpanId":"28a890bb3742e47c","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600722683417","endTimeUnixNano":"1779352600723009792","durationMs":0.326375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyThreadTurnsProjection","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"d0180980af4abacd","parentSpanId":"7e75ca6d9b33d6a8","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600723091834","endTimeUnixNano":"1779352600723108042","durationMs":0.016208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"ed0e2cca791e41cf","parentSpanId":"7e75ca6d9b33d6a8","sampled":true,"kind":"client","startTimeUnixNano":"1779352600723131000","endTimeUnixNano":"1779352600723200584","durationMs":0.069584,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n INSERT INTO projection_state (\n projector,\n last_applied_sequence,\n updated_at\n )\n VALUES (\n ?,\n ?,\n ?\n )\n ON CONFLICT (projector)\n DO UPDATE SET\n last_applied_sequence = excluded.last_applied_sequence,\n updated_at = excluded.updated_at\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.transaction","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"7e75ca6d9b33d6a8","parentSpanId":"659a572ef365b128","sampled":true,"kind":"client","startTimeUnixNano":"1779352600723048167","endTimeUnixNano":"1779352600723677209","durationMs":0.629042,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite"},"events":[{"name":"db.transaction.savepoint","timeUnixNano":"1779352600723673792","attributes":{}}],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runAttachmentSideEffects","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"ee3aa12064f76888","parentSpanId":"659a572ef365b128","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600723701834","endTimeUnixNano":"1779352600723737709","durationMs":0.035875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProjectorForEvent","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"659a572ef365b128","parentSpanId":"28a890bb3742e47c","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600723024084","endTimeUnixNano":"1779352600723743875","durationMs":0.719791,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"117058c5464e1732","parentSpanId":"499bee32d32a23e4","sampled":true,"kind":"client","startTimeUnixNano":"1779352600724366542","endTimeUnixNano":"1779352600724426917","durationMs":0.060375,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n INSERT INTO projection_state (\n projector,\n last_applied_sequence,\n updated_at\n )\n VALUES (\n ?,\n ?,\n ?\n )\n ON CONFLICT (projector)\n DO UPDATE SET\n last_applied_sequence = excluded.last_applied_sequence,\n updated_at = excluded.updated_at\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.transaction","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"499bee32d32a23e4","parentSpanId":"3a51c7630a87523d","sampled":true,"kind":"client","startTimeUnixNano":"1779352600723809959","endTimeUnixNano":"1779352600724447959","durationMs":0.638,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite"},"events":[{"name":"db.transaction.savepoint","timeUnixNano":"1779352600724445209","attributes":{}}],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runAttachmentSideEffects","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"c4e14d4101abd501","parentSpanId":"3a51c7630a87523d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600724482917","endTimeUnixNano":"1779352600724535250","durationMs":0.052333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProjectorForEvent","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"3a51c7630a87523d","parentSpanId":"28a890bb3742e47c","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600723757000","endTimeUnixNano":"1779352600724544792","durationMs":0.787792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyPendingApprovalsProjection","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"e5db063adfc55ace","parentSpanId":"8a9d56ba421ebdfd","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600724627459","endTimeUnixNano":"1779352600724643750","durationMs":0.016291,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"b272e7caf4eba999","parentSpanId":"8a9d56ba421ebdfd","sampled":true,"kind":"client","startTimeUnixNano":"1779352600724664584","endTimeUnixNano":"1779352600724704417","durationMs":0.039833,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n INSERT INTO projection_state (\n projector,\n last_applied_sequence,\n updated_at\n )\n VALUES (\n ?,\n ?,\n ?\n )\n ON CONFLICT (projector)\n DO UPDATE SET\n last_applied_sequence = excluded.last_applied_sequence,\n updated_at = excluded.updated_at\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.transaction","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"8a9d56ba421ebdfd","parentSpanId":"812fc9dfe0ebd763","sampled":true,"kind":"client","startTimeUnixNano":"1779352600724581250","endTimeUnixNano":"1779352600724718292","durationMs":0.137042,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite"},"events":[{"name":"db.transaction.savepoint","timeUnixNano":"1779352600724716292","attributes":{}}],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runAttachmentSideEffects","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"758a2953a7598d17","parentSpanId":"812fc9dfe0ebd763","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600724741042","endTimeUnixNano":"1779352600724778084","durationMs":0.037042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProjectorForEvent","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"812fc9dfe0ebd763","parentSpanId":"28a890bb3742e47c","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600724563834","endTimeUnixNano":"1779352600724784667","durationMs":0.220833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyThreadsProjection","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"c79dd5502987ba4f","parentSpanId":"5837913f6d9b1c7c","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600724849209","endTimeUnixNano":"1779352600724861959","durationMs":0.01275,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"e7b5cf2489d13c6a","parentSpanId":"5837913f6d9b1c7c","sampled":true,"kind":"client","startTimeUnixNano":"1779352600724877709","endTimeUnixNano":"1779352600724906709","durationMs":0.029,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n INSERT INTO projection_state (\n projector,\n last_applied_sequence,\n updated_at\n )\n VALUES (\n ?,\n ?,\n ?\n )\n ON CONFLICT (projector)\n DO UPDATE SET\n last_applied_sequence = excluded.last_applied_sequence,\n updated_at = excluded.updated_at\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.transaction","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"5837913f6d9b1c7c","parentSpanId":"3aa9e83beb821405","sampled":true,"kind":"client","startTimeUnixNano":"1779352600724812542","endTimeUnixNano":"1779352600724918459","durationMs":0.105917,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite"},"events":[{"name":"db.transaction.savepoint","timeUnixNano":"1779352600724917000","attributes":{}}],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runAttachmentSideEffects","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"44dc08d95b3a2683","parentSpanId":"3aa9e83beb821405","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600724936667","endTimeUnixNano":"1779352600724968625","durationMs":0.031958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProjectorForEvent","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"3aa9e83beb821405","parentSpanId":"28a890bb3742e47c","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600724798875","endTimeUnixNano":"1779352600724974542","durationMs":0.175667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"31f449bdb183759f","parentSpanId":"28a890bb3742e47c","sampled":true,"kind":"client","startTimeUnixNano":"1779352600725148167","endTimeUnixNano":"1779352600725861875","durationMs":0.713708,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n INSERT INTO orchestration_command_receipts (\n command_id,\n aggregate_kind,\n aggregate_id,\n accepted_at,\n result_sequence,\n status,\n error\n )\n VALUES (\n ?,\n ?,\n ?,\n ?,\n ?,\n ?,\n ?\n )\n ON CONFLICT (command_id)\n DO UPDATE SET\n aggregate_kind = excluded.aggregate_kind,\n aggregate_id = excluded.aggregate_id,\n accepted_at = excluded.accepted_at,\n result_sequence = excluded.result_sequence,\n status = excluded.status,\n error = excluded.error\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.transaction","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"28a890bb3742e47c","parentSpanId":"c8153f095f61e84a","sampled":true,"kind":"client","startTimeUnixNano":"1779352600718986792","endTimeUnixNano":"1779352600726607875","durationMs":7.621083,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite"},"events":[{"name":"db.transaction.commit","timeUnixNano":"1779352600725891792","attributes":{}}],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processEvent","traceId":"9c222a79013464bbed30efe9f66a4107","spanId":"13f9012956980097","parentSpanId":"02bc1709635397f9","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600726741750","endTimeUnixNano":"1779352600726759167","durationMs":0.017417,"attributes":{"server.mode":"desktop","server.port":14124,"server.host":"127.0.0.1","startup.phase":"reactors.start"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"70a0e8d00309b277","parentSpanId":"2ea2cdc31ee0588a","sampled":true,"kind":"client","startTimeUnixNano":"1779352600726991750","endTimeUnixNano":"1779352600727132667","durationMs":0.140917,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n project_id AS \"projectId\",\n title,\n workspace_root AS \"workspaceRoot\",\n default_model_selection_json AS \"defaultModelSelection\",\n scripts_json AS \"scripts\",\n created_at AS \"createdAt\",\n updated_at AS \"updatedAt\",\n deleted_at AS \"deletedAt\"\n FROM projection_projects\n WHERE project_id = ?\n AND deleted_at IS NULL\n LIMIT 1\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"orchestration.command.project.create","traceId":"1670d9e493f91f5097d22444a90fd893","spanId":"c8153f095f61e84a","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600717910125","endTimeUnixNano":"1779352600728615042","durationMs":10.704917,"attributes":{"orchestration.command_id":"5b44080e-028b-43f4-8fca-f8a78cdfb560","orchestration.command_type":"project.create","orchestration.aggregate_kind":"project","orchestration.aggregate_id":"22674271-0f5b-45a1-a927-f71d276117a9"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.orchestration.dispatchCommand","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"d045f4d30c8ff39d","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600715576625","endTimeUnixNano":"1779352600729178084","durationMs":13.601459,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"orchestration.dispatchCommand","rpc.aggregate":"orchestration"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"e9d9cff95d671804","parentSpanId":"3c00c7d6d407ac8d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600729984584","endTimeUnixNano":"1779352600738135792","durationMs":8.151208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"f41e095cb5a0417b","parentSpanId":"3c00c7d6d407ac8d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600729805834","endTimeUnixNano":"1779352600738212792","durationMs":8.406958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"3c00c7d6d407ac8d","parentSpanId":"97baeed494e76a32","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600727386167","endTimeUnixNano":"1779352600738253584","durationMs":10.867417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveRepositoryIdentityCacheKey","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"97baeed494e76a32","parentSpanId":"628c78aab4f2654e","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600727301042","endTimeUnixNano":"1779352600738393250","durationMs":11.092208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"73a7a2bf69adeae9","parentSpanId":"9d2e232e752cbd62","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600739212417","endTimeUnixNano":"1779352600744147709","durationMs":4.935292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"eb5b284c2b011ada","parentSpanId":"9d2e232e752cbd62","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600739160500","endTimeUnixNano":"1779352600744204542","durationMs":5.044042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"9d2e232e752cbd62","parentSpanId":"e7c6febb868a240e","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600738496542","endTimeUnixNano":"1779352600744231709","durationMs":5.735167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveRepositoryIdentityFromCacheKey","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"e7c6febb868a240e","parentSpanId":"628c78aab4f2654e","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600738447542","endTimeUnixNano":"1779352600744330167","durationMs":5.882625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"RepositoryIdentityResolver.resolve","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"628c78aab4f2654e","parentSpanId":"2ea2cdc31ee0588a","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600727266709","endTimeUnixNano":"1779352600744340584","durationMs":17.073875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"cce3727a5069440bc996ff5313365f3f","spanId":"ad524e6f738ebb1b","parentSpanId":"dfcab10d9c9273bc","sampled":true,"kind":"client","startTimeUnixNano":"1779352600810257042","endTimeUnixNano":"1779352600810318334","durationMs":0.061292,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n session_id AS \"sessionId\",\n subject AS \"subject\",\n role AS \"role\",\n method AS \"method\",\n client_label AS \"clientLabel\",\n client_ip_address AS \"clientIpAddress\",\n client_user_agent AS \"clientUserAgent\",\n client_device_type AS \"clientDeviceType\",\n client_os AS \"clientOs\",\n client_browser AS \"clientBrowser\",\n issued_at AS \"issuedAt\",\n expires_at AS \"expiresAt\",\n last_connected_at AS \"lastConnectedAt\",\n revoked_at AS \"revokedAt\"\n FROM auth_sessions\n WHERE session_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"otlp-span","name":"RpcClient.orchestration.dispatchCommand","traceId":"427c158a6c81364d571b1dba61ef1673","spanId":"3bdc8334e1ee5b06","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600810800000","endTimeUnixNano":"1779352600830100000","durationMs":19.3,"attributes":{},"resourceAttributes":{"service.runtime":"t3-web","service.mode":"electron","service.name":"t3-web","service.version":"0.0.24"},"scope":{"name":"t3-web","attributes":{}},"events":[],"links":[],"status":{"code":"1"}} -{"type":"effect-span","name":"http.server POST","traceId":"cce3727a5069440bc996ff5313365f3f","spanId":"dfcab10d9c9273bc","sampled":true,"kind":"server","startTimeUnixNano":"1779352600810064375","endTimeUnixNano":"1779352600810540459","durationMs":0.476084,"attributes":{"http.route":"/api/observability/v1/traces","http.request.method":"POST","url.full":"http://127.0.0.1:14124/api/observability/v1/traces","url.path":"/api/observability/v1/traces","url.scheme":"http","user_agent.original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"close","http.request.header.content-length":"707","http.request.header.sec-ch-ua-platform":"\"macOS\"","http.request.header.user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.sec-ch-ua":"\"Not-A.Brand\";v=\"24\", \"Chromium\";v=\"146\"","http.request.header.content-type":"application/json","http.request.header.sec-ch-ua-mobile":"?0","http.request.header.accept":"*/*","http.request.header.origin":"http://127.0.0.1:6084","http.request.header.sec-fetch-site":"same-origin","http.request.header.sec-fetch-mode":"cors","http.request.header.sec-fetch-dest":"empty","http.request.header.referer":"http://127.0.0.1:6084/","http.request.header.accept-encoding":"gzip, deflate, br, zstd","http.request.header.accept-language":"en-GB","http.request.header.cookie":"","http.response.status_code":204},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"e4aa6ecf75d62357","parentSpanId":"711e2081a96f9881","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600867212542","endTimeUnixNano":"1779352600869026542","durationMs":1.814,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"ProcessSpawnError: \n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14166:38\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/effect.js:1309:96\n at ~effect/Utils/internal (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Utils.js:69:12)\n at processRunner.runProcessCore (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14219:44)\n at processRunner.runProcessCore (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14155:31)\n at VcsProcess.run (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:24401:18)\n at VcsProcess.run (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19834:21)\n at ws.rpc.server.discoverSourceControl (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:17831:111) {\n [cause]: PlatformError: NotFound: ChildProcess.spawn (jj --version)\n at Module.systemError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/PlatformError.js:59:39)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/internal/utils.js:28:24\n at toPlatformError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:25:54)\n at ChildProcess. (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:230:26)\n at ChildProcess.emit (node:events:509:28)\n at ChildProcess._handle.onexit (node:internal/child_process:293:12)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {\n [cause]: Error: spawn jj ENOENT\n at ChildProcess._handle.onexit (node:internal/child_process:287:19)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n }\n}"}} -{"type":"effect-span","name":"VcsProcess.run","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"711e2081a96f9881","parentSpanId":"6e5cb775e0b82976","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600867196584","endTimeUnixNano":"1779352600869178750","durationMs":1.982166,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"VcsProcessSpawnError: VCS process failed to spawn in source-control.discovery.probe: jj --version (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69)\n at VcsProcessSpawnError.fromProcessSpawnError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:3950:10)\n at Object.ProcessSpawnError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19854:55)\n at Object.evaluate (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:170:101)\n at i (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:236:37)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:281:20\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:133:10\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Function.js:97:18\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/effect.js:1309:96\n at ~effect/Utils/internal (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Utils.js:69:12)\n at VcsProcess.run (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:24401:18)\n at VcsProcess.run (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19834:21)\n at ws.rpc.server.discoverSourceControl (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:17831:111) {\n [cause]: PlatformError: NotFound: ChildProcess.spawn (jj --version)\n at Module.systemError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/PlatformError.js:59:39)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/internal/utils.js:28:24\n at toPlatformError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:25:54)\n at ChildProcess. (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:230:26)\n at ChildProcess.emit (node:events:509:28)\n at ChildProcess._handle.onexit (node:internal/child_process:293:12)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {\n [cause]: Error: spawn jj ENOENT\n at ChildProcess._handle.onexit (node:internal/child_process:287:19)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n }\n}"}} -{"type":"effect-span","name":"sql.execute","traceId":"6b225ed648bdd1d8e27f16f54766d83c","spanId":"9836879d477d1c66","parentSpanId":"e6f2f87c54e8fb6b","sampled":true,"kind":"client","startTimeUnixNano":"1779352600869935000","endTimeUnixNano":"1779352600869983125","durationMs":0.048125,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n session_id AS \"sessionId\",\n subject AS \"subject\",\n role AS \"role\",\n method AS \"method\",\n client_label AS \"clientLabel\",\n client_ip_address AS \"clientIpAddress\",\n client_user_agent AS \"clientUserAgent\",\n client_device_type AS \"clientDeviceType\",\n client_os AS \"clientOs\",\n client_browser AS \"clientBrowser\",\n issued_at AS \"issuedAt\",\n expires_at AS \"expiresAt\",\n last_connected_at AS \"lastConnectedAt\",\n revoked_at AS \"revokedAt\"\n FROM auth_sessions\n WHERE session_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"6b225ed648bdd1d8e27f16f54766d83c","spanId":"f942f30693bea466","parentSpanId":"2b15e540cfbd20f3","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600870062584","endTimeUnixNano":"1779352600870191917","durationMs":0.129333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"6b225ed648bdd1d8e27f16f54766d83c","spanId":"4427e6c75ece6078","parentSpanId":"2b15e540cfbd20f3","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600870476875","endTimeUnixNano":"1779352600870547875","durationMs":0.071,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.getCachedStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"47d1230ddc1bef16","parentSpanId":"bab6668a21c249a4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600870619584","endTimeUnixNano":"1779352600870637625","durationMs":0.018041,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"6b225ed648bdd1d8e27f16f54766d83c","spanId":"0465dcde55215d46","parentSpanId":"2b15e540cfbd20f3","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600870563292","endTimeUnixNano":"1779352600870704917","durationMs":0.141625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProjectConfig.findConfigPath","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"fa7f0e1623717903","parentSpanId":"0d7d144a27776f81","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600869727667","endTimeUnixNano":"1779352600870729000","durationMs":1.001333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProjectConfig.resolveKind","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"0d7d144a27776f81","parentSpanId":"4883a0a85448d6ba","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600869720167","endTimeUnixNano":"1779352600870732917","durationMs":1.01275,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"6b225ed648bdd1d8e27f16f54766d83c","spanId":"77b99bacbb34beb2","parentSpanId":"2b15e540cfbd20f3","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600870712209","endTimeUnixNano":"1779352600870911834","durationMs":0.199625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"6b225ed648bdd1d8e27f16f54766d83c","spanId":"d9697034620e618b","parentSpanId":"2b15e540cfbd20f3","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600870919459","endTimeUnixNano":"1779352600871422834","durationMs":0.503375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"6b225ed648bdd1d8e27f16f54766d83c","spanId":"b28528ca2107c7e3","parentSpanId":"2b15e540cfbd20f3","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600871431084","endTimeUnixNano":"1779352600871502792","durationMs":0.071708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProjectConfig.findConfigPath","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"5766812869fb18f2","parentSpanId":"7c41290cd3fe268c","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600870687875","endTimeUnixNano":"1779352600871526292","durationMs":0.838417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProjectConfig.resolveKind","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"7c41290cd3fe268c","parentSpanId":"d7946f520cbd143a","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600870681334","endTimeUnixNano":"1779352600871529875","durationMs":0.848541,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"6b225ed648bdd1d8e27f16f54766d83c","spanId":"d7867bf140053b40","parentSpanId":"2b15e540cfbd20f3","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600871509875","endTimeUnixNano":"1779352600871544084","durationMs":0.034209,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"6b225ed648bdd1d8e27f16f54766d83c","spanId":"f983ae13f4952597","parentSpanId":"2b15e540cfbd20f3","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600871551000","endTimeUnixNano":"1779352600871573084","durationMs":0.022084,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"6b225ed648bdd1d8e27f16f54766d83c","spanId":"f3711903e11f3448","parentSpanId":"2b15e540cfbd20f3","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600871579292","endTimeUnixNano":"1779352600871598375","durationMs":0.019083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"6b225ed648bdd1d8e27f16f54766d83c","spanId":"5994bb063b5fcbce","parentSpanId":"2b15e540cfbd20f3","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600871606834","endTimeUnixNano":"1779352600871795625","durationMs":0.188791,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"1d433489b399f90f","parentSpanId":"eff8d54b159db154","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600868143709","endTimeUnixNano":"1779352600871846250","durationMs":3.702541,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"941824ba6427186c","parentSpanId":"eff8d54b159db154","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600868072625","endTimeUnixNano":"1779352600871875459","durationMs":3.802834,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"eff8d54b159db154","parentSpanId":"9bb5b8bf89bf8019","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600867149667","endTimeUnixNano":"1779352600871892750","durationMs":4.743083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProcess.run","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"9bb5b8bf89bf8019","parentSpanId":"6e5cb775e0b82976","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600867116334","endTimeUnixNano":"1779352600871920542","durationMs":4.804208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"6b225ed648bdd1d8e27f16f54766d83c","spanId":"54dc8577b9904e50","parentSpanId":"2b15e540cfbd20f3","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600871802542","endTimeUnixNano":"1779352600872307875","durationMs":0.505333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"0f48c1544591f0bd","parentSpanId":"485b71b6c594f5cf","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600871984042","endTimeUnixNano":"1779352600874637125","durationMs":2.653083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"ProcessSpawnError: \n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14166:38\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/effect.js:1309:96\n at ~effect/Utils/internal (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Utils.js:69:12)\n at processRunner.runProcessCore (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14219:44)\n at processRunner.runProcessCore (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14155:31)\n at VcsProcess.run (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:20703:23)\n at VcsProcess.run (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19834:21)\n at ws.rpc.server.discoverSourceControl (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:17831:111) {\n [cause]: PlatformError: NotFound: ChildProcess.spawn (glab --version)\n at Module.systemError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/PlatformError.js:59:39)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/internal/utils.js:28:24\n at toPlatformError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:25:54)\n at ChildProcess. (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:230:26)\n at ChildProcess.emit (node:events:509:28)\n at ChildProcess._handle.onexit (node:internal/child_process:293:12)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {\n [cause]: Error: spawn glab ENOENT\n at ChildProcess._handle.onexit (node:internal/child_process:287:19)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n }\n}"}} -{"type":"effect-span","name":"VcsProcess.run","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"485b71b6c594f5cf","parentSpanId":"6e5cb775e0b82976","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600871971625","endTimeUnixNano":"1779352600874810709","durationMs":2.839084,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"VcsProcessSpawnError: VCS process failed to spawn in source-control.discovery.probe: glab --version (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69)\n at VcsProcessSpawnError.fromProcessSpawnError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:3950:10)\n at Object.ProcessSpawnError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19854:55)\n at Object.evaluate (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:170:101)\n at i (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:236:37)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:281:20\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:133:10\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Function.js:97:18\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/effect.js:1309:96\n at ~effect/Utils/internal (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Utils.js:69:12)\n at VcsProcess.run (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:20703:23)\n at VcsProcess.run (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19834:21)\n at ws.rpc.server.discoverSourceControl (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:17831:111) {\n [cause]: PlatformError: NotFound: ChildProcess.spawn (glab --version)\n at Module.systemError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/PlatformError.js:59:39)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/internal/utils.js:28:24\n at toPlatformError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:25:54)\n at ChildProcess. (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:230:26)\n at ChildProcess.emit (node:events:509:28)\n at ChildProcess._handle.onexit (node:internal/child_process:293:12)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {\n [cause]: Error: spawn glab ENOENT\n at ChildProcess._handle.onexit (node:internal/child_process:287:19)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n }\n}"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"f690611be53d2892","parentSpanId":"495c05aa6ed7bc70","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600872007084","endTimeUnixNano":"1779352600875599375","durationMs":3.592291,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"ProcessSpawnError: \n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14166:38\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/effect.js:1309:96\n at ~effect/Utils/internal (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Utils.js:69:12)\n at processRunner.runProcessCore (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14219:44)\n at processRunner.runProcessCore (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:14155:31)\n at VcsProcess.run (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:20703:23)\n at VcsProcess.run (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19834:21)\n at ws.rpc.server.discoverSourceControl (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:17831:111) {\n [cause]: PlatformError: NotFound: ChildProcess.spawn (az --version)\n at Module.systemError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/PlatformError.js:59:39)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/internal/utils.js:28:24\n at toPlatformError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:25:54)\n at ChildProcess. (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:230:26)\n at ChildProcess.emit (node:events:509:28)\n at ChildProcess._handle.onexit (node:internal/child_process:293:12)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {\n [cause]: Error: spawn az ENOENT\n at ChildProcess._handle.onexit (node:internal/child_process:287:19)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n }\n}"}} -{"type":"effect-span","name":"VcsProcess.run","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"495c05aa6ed7bc70","parentSpanId":"6e5cb775e0b82976","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600871995375","endTimeUnixNano":"1779352600875672334","durationMs":3.676959,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"VcsProcessSpawnError: VCS process failed to spawn in source-control.discovery.probe: az --version (/Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69)\n at VcsProcessSpawnError.fromProcessSpawnError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:3950:10)\n at Object.ProcessSpawnError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19854:55)\n at Object.evaluate (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:170:101)\n at i (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:236:37)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:281:20\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/matcher.js:133:10\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Function.js:97:18\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/internal/effect.js:1309:96\n at ~effect/Utils/internal (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/Utils.js:69:12)\n at VcsProcess.run (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:20703:23)\n at VcsProcess.run (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:19834:21)\n at ws.rpc.server.discoverSourceControl (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:17831:111) {\n [cause]: PlatformError: NotFound: ChildProcess.spawn (az --version)\n at Module.systemError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/PlatformError.js:59:39)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/internal/utils.js:28:24\n at toPlatformError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:25:54)\n at ChildProcess. (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:230:26)\n at ChildProcess.emit (node:events:509:28)\n at ChildProcess._handle.onexit (node:internal/child_process:293:12)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {\n [cause]: Error: spawn az ENOENT\n at ChildProcess._handle.onexit (node:internal/child_process:287:19)\n at onErrorNT (node:internal/child_process:508:16)\n at process.processTicksAndRejections (node:internal/process/task_queues:90:21)\n }\n}"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"6b225ed648bdd1d8e27f16f54766d83c","spanId":"6b82db1bc0fc0d30","parentSpanId":"2b15e540cfbd20f3","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600872317084","endTimeUnixNano":"1779352600875730792","durationMs":3.413708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"6a2f09ba0ad26005","parentSpanId":"3177ce5974619a7e","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600871357292","endTimeUnixNano":"1779352600876021292","durationMs":4.664,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"3773b606d1585f4a","parentSpanId":"3177ce5974619a7e","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600871381250","endTimeUnixNano":"1779352600876276667","durationMs":4.895417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"3177ce5974619a7e","parentSpanId":"594a4cc259c14eb3","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600870871917","endTimeUnixNano":"1779352600876284209","durationMs":5.412292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProcess.run","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"594a4cc259c14eb3","parentSpanId":"065b44912a339fa6","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600870844959","endTimeUnixNano":"1779352600876354000","durationMs":5.509041,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"detectRepository","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"065b44912a339fa6","parentSpanId":"370b02e55cdf0791","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600870791875","endTimeUnixNano":"1779352600876388542","durationMs":5.596667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsDriverRegistry.detectWithDriver","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"370b02e55cdf0791","parentSpanId":"d67a6d56013cb888","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600870784959","endTimeUnixNano":"1779352600876391875","durationMs":5.606916,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsDriverRegistry.detectResolvedKind","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"d67a6d56013cb888","parentSpanId":"4883a0a85448d6ba","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600870776875","endTimeUnixNano":"1779352600876394875","durationMs":5.618,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsDriverRegistry.detect","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"d7946f520cbd143a","parentSpanId":"73d3dffd8295db3e","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600870674375","endTimeUnixNano":"1779352600876399834","durationMs":5.725459,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"GitWorkflowService.detectGitRepositoryForStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"73d3dffd8295db3e","parentSpanId":"80b4e4088faf7690","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600870665792","endTimeUnixNano":"1779352600876403167","durationMs":5.737375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.updateCachedLocalStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"a6916725f298c677","parentSpanId":"80b4e4088faf7690","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600876437917","endTimeUnixNano":"1779352600876473959","durationMs":0.036042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.loadLocalStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"80b4e4088faf7690","parentSpanId":"bab6668a21c249a4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600870645750","endTimeUnixNano":"1779352600876477042","durationMs":5.831292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.getOrLoadLocalStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"bab6668a21c249a4","parentSpanId":"2dad6716c4a3cab9","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600870610625","endTimeUnixNano":"1779352600876479792","durationMs":5.869167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.getCachedStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"ec231c5d0639d833","parentSpanId":"2dad6716c4a3cab9","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600876488542","endTimeUnixNano":"1779352600876496250","durationMs":0.007708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.retainRemotePoller","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"15519d49086c4fd0","parentSpanId":"2dad6716c4a3cab9","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600876502667","endTimeUnixNano":"1779352600876605500","durationMs":0.102833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsDriverRegistry.detect","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"4883a0a85448d6ba","parentSpanId":"3ca1b268d374674e","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600869707292","endTimeUnixNano":"1779352600876756167","durationMs":7.048875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"GitWorkflowService.detectGitRepositoryForCommand","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"3ca1b268d374674e","parentSpanId":"c010419a8acaa97e","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600869696959","endTimeUnixNano":"1779352600876760417","durationMs":7.063458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.vcs.listRefs","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"c010419a8acaa97e","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600869682792","endTimeUnixNano":"1779352600876841084","durationMs":7.158292,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"vcs.listRefs","rpc.aggregate":"vcs"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"6b225ed648bdd1d8e27f16f54766d83c","spanId":"c437d8f9c166193f","parentSpanId":"2b15e540cfbd20f3","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600875753000","endTimeUnixNano":"1779352600876909250","durationMs":1.15625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"6b225ed648bdd1d8e27f16f54766d83c","spanId":"022e538861032807","parentSpanId":"2b15e540cfbd20f3","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600876936834","endTimeUnixNano":"1779352600877463834","durationMs":0.527,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"6b225ed648bdd1d8e27f16f54766d83c","spanId":"1383c52a509b6b73","parentSpanId":"2b15e540cfbd20f3","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600877473209","endTimeUnixNano":"1779352600877509125","durationMs":0.035916,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"6b225ed648bdd1d8e27f16f54766d83c","spanId":"adb72ed600e09ab2","parentSpanId":"2b15e540cfbd20f3","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600877517042","endTimeUnixNano":"1779352600877539917","durationMs":0.022875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"invalidateRemoteStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"7060584444171c49","parentSpanId":"fc21a10f4f2c97ca","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600877415709","endTimeUnixNano":"1779352600877566834","durationMs":0.151125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"6b225ed648bdd1d8e27f16f54766d83c","spanId":"84c2c2f0ac08a964","parentSpanId":"2b15e540cfbd20f3","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600877546750","endTimeUnixNano":"1779352600877626709","durationMs":0.079959,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"6b225ed648bdd1d8e27f16f54766d83c","spanId":"55e326119a41cc5d","parentSpanId":"2b15e540cfbd20f3","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600877633500","endTimeUnixNano":"1779352600877661500","durationMs":0.028,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"6b225ed648bdd1d8e27f16f54766d83c","spanId":"81d599795df85e15","parentSpanId":"2b15e540cfbd20f3","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600877667959","endTimeUnixNano":"1779352600877692875","durationMs":0.024916,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"6b225ed648bdd1d8e27f16f54766d83c","spanId":"33b2db618b87867b","parentSpanId":"2b15e540cfbd20f3","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600877699292","endTimeUnixNano":"1779352600877746084","durationMs":0.046792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProjectConfig.findConfigPath","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"9fa3dbaefb354b18","parentSpanId":"66884092f379cf14","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600877604417","endTimeUnixNano":"1779352600877813500","durationMs":0.209083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProjectConfig.resolveKind","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"66884092f379cf14","parentSpanId":"2e4bb1d56d32d407","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600877597042","endTimeUnixNano":"1779352600877847500","durationMs":0.250458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsDriverRegistry.detect","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"2e4bb1d56d32d407","parentSpanId":"3523dba17c5f0936","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600877590000","endTimeUnixNano":"1779352600877861625","durationMs":0.271625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"GitWorkflowService.detectGitRepositoryForStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"3523dba17c5f0936","parentSpanId":"fc21a10f4f2c97ca","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600877581042","endTimeUnixNano":"1779352600877865292","durationMs":0.28425,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.updateCachedRemoteStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"f93a3b573b7a76be","parentSpanId":"fc21a10f4f2c97ca","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600877885709","endTimeUnixNano":"1779352600877920625","durationMs":0.034916,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.refreshRemoteStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"fc21a10f4f2c97ca","parentSpanId":"15519d49086c4fd0","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600877405792","endTimeUnixNano":"1779352600877923959","durationMs":0.518167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.findExistingFile","traceId":"6b225ed648bdd1d8e27f16f54766d83c","spanId":"a7e2fce6e5b3237b","parentSpanId":"2b15e540cfbd20f3","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600877759709","endTimeUnixNano":"1779352600878013292","durationMs":0.253583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ProjectFaviconResolver.resolvePath","traceId":"6b225ed648bdd1d8e27f16f54766d83c","spanId":"2b15e540cfbd20f3","parentSpanId":"e6f2f87c54e8fb6b","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600870052125","endTimeUnixNano":"1779352600878374334","durationMs":8.322209,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"http.server GET","traceId":"6b225ed648bdd1d8e27f16f54766d83c","spanId":"e6f2f87c54e8fb6b","sampled":true,"kind":"server","startTimeUnixNano":"1779352600869835792","endTimeUnixNano":"1779352600878507834","durationMs":8.672042,"attributes":{"http.route":"/api/project-favicon","http.request.method":"GET","url.full":"http://127.0.0.1:14124/api/project-favicon?cwd=%2FUsers%2Fharrydawson%2FDesktop","url.path":"/api/project-favicon","url.query":"cwd=%2FUsers%2Fharrydawson%2FDesktop","url.scheme":"http","user_agent.original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"keep-alive","http.request.header.sec-ch-ua-platform":"\"macOS\"","http.request.header.user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.sec-ch-ua":"\"Not-A.Brand\";v=\"24\", \"Chromium\";v=\"146\"","http.request.header.sec-ch-ua-mobile":"?0","http.request.header.accept":"image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8","http.request.header.sec-fetch-site":"same-site","http.request.header.sec-fetch-mode":"no-cors","http.request.header.sec-fetch-dest":"image","http.request.header.referer":"http://127.0.0.1:6084/","http.request.header.accept-encoding":"gzip, deflate, br, zstd","http.request.header.accept-language":"en-GB","http.request.header.cookie":"","client.address":"127.0.0.1","http.response.status_code":200,"http.response.header.cache-control":"public, max-age=3600","http.response.header.content-type":"image/svg+xml","http.response.header.content-length":"306"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"5d54d56b875cfa5b","parentSpanId":"d6cbe48ff192c2d1","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600873020000","endTimeUnixNano":"1779352600891423792","durationMs":18.403792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"7735e92a3e9a2567","parentSpanId":"d6cbe48ff192c2d1","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600872989334","endTimeUnixNano":"1779352600891472625","durationMs":18.483291,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"d6cbe48ff192c2d1","parentSpanId":"2f011243441121af","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600871954542","endTimeUnixNano":"1779352600891496875","durationMs":19.542333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProcess.run","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"2f011243441121af","parentSpanId":"6e5cb775e0b82976","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600871939000","endTimeUnixNano":"1779352600891540459","durationMs":19.601459,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"http.client GET","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"ca6eb5dfb86a807b","parentSpanId":"6e5cb775e0b82976","sampled":true,"kind":"client","startTimeUnixNano":"1779352600872032709","endTimeUnixNano":"1779352601177577584","durationMs":305.544875,"attributes":{"http.request.method":"GET","server.address":"https://api.bitbucket.org","url.full":"https://api.bitbucket.org/2.0/user","url.path":"/2.0/user","url.scheme":"https","http.request.header.accept":"application/json","http.response.status_code":401,"http.response.header.age":"0","http.response.header.atl-request-id":"e6873cd1-d9ce-46bc-81b5-cdcd42370882","http.response.header.atl-traceid":"e6873cd1d9ce46bc81b5cdcd42370882","http.response.header.content-length":"0","http.response.header.content-type":"text/html; charset=utf-8","http.response.header.date":"Thu, 21 May 2026 08:36:41 GMT","http.response.header.nel":"{\"failure_fraction\": 0.01, \"include_subdomains\": true, \"max_age\": 600, \"report_to\": \"endpoint-1\"}","http.response.header.report-to":"{\"endpoints\": [{\"url\": \"https://dz8aopenkvv6s.cloudfront.net\"}], \"group\": \"endpoint-1\", \"include_subdomains\": true, \"max_age\": 600}","http.response.header.server":"AtlassianEdge","http.response.header.server-timing":"atl-edge;dur=269,atl-edge-internal;dur=10,atl-edge-upstream;dur=260,atl-edge-pop;desc=\"aws-ap-southeast-2\"","http.response.header.strict-transport-security":"max-age=63072000; includeSubDomains; preload","http.response.header.vary":"Authorization, origin","http.response.header.www-authenticate":"BitbucketCustom realm=Bitbucket.org HTTP","http.response.header.x-accepted-oauth-scopes":"account","http.response.header.x-asap-succeeded":"True","http.response.header.x-b3-spanid":"4e7125d236039cce","http.response.header.x-b3-traceid":"e6873cd1d9ce46bc81b5cdcd42370882","http.response.header.x-cache":"MISS","http.response.header.x-content-type-options":"nosniff","http.response.header.x-credential-type":"unauthenticated_identity","http.response.header.x-dc-location":"Micros-3","http.response.header.x-envoy-attempt-count":"1","http.response.header.x-frame-options":"SAMEORIGIN","http.response.header.x-ratelimit-limit":"60, 60;w=3600","http.response.header.x-ratelimit-remaining":"56","http.response.header.x-ratelimit-reset":"1399","http.response.header.x-render-time":"0.021687030792236328","http.response.header.x-request-count":"1830","http.response.header.x-served-by":"42e673904b22","http.response.header.x-static-version":"51d05f3ab3e8","http.response.header.x-usage-input-ops":"0","http.response.header.x-usage-output-ops":"0","http.response.header.x-usage-system-time":"0.001409","http.response.header.x-usage-user-time":"0.023628","http.response.header.x-used-mesh":"False","http.response.header.x-version":"51d05f3ab3e8","http.response.header.x-view-name":"bitbucket.apps.bb.api.v20.handlers.CurrentUserHandler","http.response.header.x-xss-protection":"1; mode=block"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"43dde1a572021276","parentSpanId":"3391a72f255e50ec","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600892296334","endTimeUnixNano":"1779352601357230042","durationMs":464.933708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"f5fdf44bd0b1e078","parentSpanId":"3391a72f255e50ec","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600892264250","endTimeUnixNano":"1779352601357364417","durationMs":465.100167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"3391a72f255e50ec","parentSpanId":"fa5f01274789132e","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600891609875","endTimeUnixNano":"1779352601357449709","durationMs":465.839834,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProcess.run","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"fa5f01274789132e","parentSpanId":"6e5cb775e0b82976","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600891578292","endTimeUnixNano":"1779352601357565417","durationMs":465.987125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.server.discoverSourceControl","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"6e5cb775e0b82976","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600867067250","endTimeUnixNano":"1779352601357922209","durationMs":490.854959,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"server.discoverSourceControl","rpc.aggregate":"server"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"45e796030f0513906a8183a47fe10470","spanId":"362ff14ef11c176c","parentSpanId":"71faa546a8887d38","sampled":true,"kind":"client","startTimeUnixNano":"1779352601906939125","endTimeUnixNano":"1779352601907052167","durationMs":0.113042,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n session_id AS \"sessionId\",\n subject AS \"subject\",\n role AS \"role\",\n method AS \"method\",\n client_label AS \"clientLabel\",\n client_ip_address AS \"clientIpAddress\",\n client_user_agent AS \"clientUserAgent\",\n client_device_type AS \"clientDeviceType\",\n client_os AS \"clientOs\",\n client_browser AS \"clientBrowser\",\n issued_at AS \"issuedAt\",\n expires_at AS \"expiresAt\",\n last_connected_at AS \"lastConnectedAt\",\n revoked_at AS \"revokedAt\"\n FROM auth_sessions\n WHERE session_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"otlp-span","name":"RpcClient.vcs.listRefs","traceId":"97f13fe618af346976d4a46ee76746c0","spanId":"f9b7ebe2c56ee36a","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600967100000","endTimeUnixNano":"1779352601014300000","durationMs":47.2,"attributes":{},"resourceAttributes":{"service.runtime":"t3-web","service.mode":"electron","service.name":"t3-web","service.version":"0.0.24"},"scope":{"name":"t3-web","attributes":{}},"events":[],"links":[],"status":{"code":"1"}} -{"type":"otlp-span","name":"RpcClient.server.discoverSourceControl","traceId":"1da3ff2c155088d0ac1da35a26488e50","spanId":"98d90e7db2e6eab4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600966200000","endTimeUnixNano":"1779352601458700000","durationMs":492.5,"attributes":{},"resourceAttributes":{"service.runtime":"t3-web","service.mode":"electron","service.name":"t3-web","service.version":"0.0.24"},"scope":{"name":"t3-web","attributes":{}},"events":[],"links":[],"status":{"code":"1"}} -{"type":"effect-span","name":"http.server POST","traceId":"45e796030f0513906a8183a47fe10470","spanId":"71faa546a8887d38","sampled":true,"kind":"server","startTimeUnixNano":"1779352601906695667","endTimeUnixNano":"1779352601907463042","durationMs":0.767375,"attributes":{"http.route":"/api/observability/v1/traces","http.request.method":"POST","url.full":"http://127.0.0.1:14124/api/observability/v1/traces","url.path":"/api/observability/v1/traces","url.scheme":"http","user_agent.original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"close","http.request.header.content-length":"1035","http.request.header.sec-ch-ua-platform":"\"macOS\"","http.request.header.user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.sec-ch-ua":"\"Not-A.Brand\";v=\"24\", \"Chromium\";v=\"146\"","http.request.header.content-type":"application/json","http.request.header.sec-ch-ua-mobile":"?0","http.request.header.accept":"*/*","http.request.header.origin":"http://127.0.0.1:6084","http.request.header.sec-fetch-site":"same-origin","http.request.header.sec-fetch-mode":"cors","http.request.header.sec-fetch-dest":"empty","http.request.header.referer":"http://127.0.0.1:6084/","http.request.header.accept-encoding":"gzip, deflate, br, zstd","http.request.header.accept-language":"en-GB","http.request.header.cookie":"","http.response.status_code":204},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"0e2b4c49d32202c6","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352605349529375","endTimeUnixNano":"1779352605387020584","durationMs":37.491209,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.server.updateSettings","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"bcc039344e3d08ec","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"internal","startTimeUnixNano":"1779352606535063000","endTimeUnixNano":"1779352606538071000","durationMs":3.008,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"server.updateSettings","rpc.aggregate":"server"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"543325acc5b7aaf38e254efc80f119af","spanId":"2e1ed1be8c951c2d","parentSpanId":"4e015ccdbc89d0f2","sampled":true,"kind":"client","startTimeUnixNano":"1779352606928407209","endTimeUnixNano":"1779352606928608667","durationMs":0.201458,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n session_id AS \"sessionId\",\n subject AS \"subject\",\n role AS \"role\",\n method AS \"method\",\n client_label AS \"clientLabel\",\n client_ip_address AS \"clientIpAddress\",\n client_user_agent AS \"clientUserAgent\",\n client_device_type AS \"clientDeviceType\",\n client_os AS \"clientOs\",\n client_browser AS \"clientBrowser\",\n issued_at AS \"issuedAt\",\n expires_at AS \"expiresAt\",\n last_connected_at AS \"lastConnectedAt\",\n revoked_at AS \"revokedAt\"\n FROM auth_sessions\n WHERE session_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"otlp-span","name":"RpcClient.server.updateSettings","traceId":"7ef576c49a494222aba90fc1a5055f67","spanId":"d2eead49bc049bbc","sampled":true,"kind":"internal","startTimeUnixNano":"1779352606633600000","endTimeUnixNano":"1779352606658600000","durationMs":25,"attributes":{},"resourceAttributes":{"service.runtime":"t3-web","service.mode":"electron","service.name":"t3-web","service.version":"0.0.24"},"scope":{"name":"t3-web","attributes":{}},"events":[],"links":[],"status":{"code":"1"}} -{"type":"effect-span","name":"http.server POST","traceId":"543325acc5b7aaf38e254efc80f119af","spanId":"4e015ccdbc89d0f2","sampled":true,"kind":"server","startTimeUnixNano":"1779352606927947292","endTimeUnixNano":"1779352606929399542","durationMs":1.45225,"attributes":{"http.route":"/api/observability/v1/traces","http.request.method":"POST","url.full":"http://127.0.0.1:14124/api/observability/v1/traces","url.path":"/api/observability/v1/traces","url.scheme":"http","user_agent.original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"close","http.request.header.content-length":"699","http.request.header.sec-ch-ua-platform":"\"macOS\"","http.request.header.user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.sec-ch-ua":"\"Not-A.Brand\";v=\"24\", \"Chromium\";v=\"146\"","http.request.header.content-type":"application/json","http.request.header.sec-ch-ua-mobile":"?0","http.request.header.accept":"*/*","http.request.header.origin":"http://127.0.0.1:6084","http.request.header.sec-fetch-site":"same-origin","http.request.header.sec-fetch-mode":"cors","http.request.header.sec-fetch-dest":"empty","http.request.header.referer":"http://127.0.0.1:6084/","http.request.header.accept-encoding":"gzip, deflate, br, zstd","http.request.header.accept-language":"en-GB","http.request.header.cookie":"","http.response.status_code":204},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.server.updateSettings","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"72af247991e98984","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"internal","startTimeUnixNano":"1779352607130334750","endTimeUnixNano":"1779352607132555667","durationMs":2.220917,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"server.updateSettings","rpc.aggregate":"server"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"c128c19a8ebea2ccd58d9d6729b42916","spanId":"e943c3e961f9e210","parentSpanId":"978397b58dbae48d","sampled":true,"kind":"client","startTimeUnixNano":"1779352607936848000","endTimeUnixNano":"1779352607937191500","durationMs":0.3435,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n session_id AS \"sessionId\",\n subject AS \"subject\",\n role AS \"role\",\n method AS \"method\",\n client_label AS \"clientLabel\",\n client_ip_address AS \"clientIpAddress\",\n client_user_agent AS \"clientUserAgent\",\n client_device_type AS \"clientDeviceType\",\n client_os AS \"clientOs\",\n client_browser AS \"clientBrowser\",\n issued_at AS \"issuedAt\",\n expires_at AS \"expiresAt\",\n last_connected_at AS \"lastConnectedAt\",\n revoked_at AS \"revokedAt\"\n FROM auth_sessions\n WHERE session_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"otlp-span","name":"RpcClient.server.updateSettings","traceId":"1dd737c89564d70b0835f279877074c8","spanId":"2c65583d54704456","sampled":true,"kind":"internal","startTimeUnixNano":"1779352607229400000","endTimeUnixNano":"1779352607259100000","durationMs":29.7,"attributes":{},"resourceAttributes":{"service.runtime":"t3-web","service.mode":"electron","service.name":"t3-web","service.version":"0.0.24"},"scope":{"name":"t3-web","attributes":{}},"events":[],"links":[],"status":{"code":"1"}} -{"type":"effect-span","name":"http.server POST","traceId":"c128c19a8ebea2ccd58d9d6729b42916","spanId":"978397b58dbae48d","sampled":true,"kind":"server","startTimeUnixNano":"1779352607936370667","endTimeUnixNano":"1779352607938291709","durationMs":1.921042,"attributes":{"http.route":"/api/observability/v1/traces","http.request.method":"POST","url.full":"http://127.0.0.1:14124/api/observability/v1/traces","url.path":"/api/observability/v1/traces","url.scheme":"http","user_agent.original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"close","http.request.header.content-length":"699","http.request.header.sec-ch-ua-platform":"\"macOS\"","http.request.header.user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.sec-ch-ua":"\"Not-A.Brand\";v=\"24\", \"Chromium\";v=\"146\"","http.request.header.content-type":"application/json","http.request.header.sec-ch-ua-mobile":"?0","http.request.header.accept":"*/*","http.request.header.origin":"http://127.0.0.1:6084","http.request.header.sec-fetch-site":"same-origin","http.request.header.sec-fetch-mode":"cors","http.request.header.sec-fetch-dest":"empty","http.request.header.referer":"http://127.0.0.1:6084/","http.request.header.accept-encoding":"gzip, deflate, br, zstd","http.request.header.accept-language":"en-GB","http.request.header.cookie":"","http.response.status_code":204},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.server.updateSettings","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"0fd81492ece295b6","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"internal","startTimeUnixNano":"1779352609879781334","endTimeUnixNano":"1779352609882059084","durationMs":2.27775,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"server.updateSettings","rpc.aggregate":"server"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"f4cece8d3522ccb957d356c2d6bd765b","spanId":"87e1f8f6568ee443","parentSpanId":"c2eb2b96df51059c","sampled":true,"kind":"client","startTimeUnixNano":"1779352609946930667","endTimeUnixNano":"1779352609946992584","durationMs":0.061917,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n session_id AS \"sessionId\",\n subject AS \"subject\",\n role AS \"role\",\n method AS \"method\",\n client_label AS \"clientLabel\",\n client_ip_address AS \"clientIpAddress\",\n client_user_agent AS \"clientUserAgent\",\n client_device_type AS \"clientDeviceType\",\n client_os AS \"clientOs\",\n client_browser AS \"clientBrowser\",\n issued_at AS \"issuedAt\",\n expires_at AS \"expiresAt\",\n last_connected_at AS \"lastConnectedAt\",\n revoked_at AS \"revokedAt\"\n FROM auth_sessions\n WHERE session_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"otlp-span","name":"RpcClient.server.updateSettings","traceId":"411eda69a62b5376fc3163fa3ddc5944","spanId":"b95904a5faa95fb6","sampled":true,"kind":"internal","startTimeUnixNano":"1779352609978900000","endTimeUnixNano":"1779352610002600000","durationMs":23.7,"attributes":{},"resourceAttributes":{"service.runtime":"t3-web","service.mode":"electron","service.name":"t3-web","service.version":"0.0.24"},"scope":{"name":"t3-web","attributes":{}},"events":[],"links":[],"status":{"code":"1"}} -{"type":"effect-span","name":"http.server POST","traceId":"f4cece8d3522ccb957d356c2d6bd765b","spanId":"c2eb2b96df51059c","sampled":true,"kind":"server","startTimeUnixNano":"1779352609946792417","endTimeUnixNano":"1779352609947235667","durationMs":0.44325,"attributes":{"http.route":"/api/observability/v1/traces","http.request.method":"POST","url.full":"http://127.0.0.1:14124/api/observability/v1/traces","url.path":"/api/observability/v1/traces","url.scheme":"http","user_agent.original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"close","http.request.header.content-length":"699","http.request.header.sec-ch-ua-platform":"\"macOS\"","http.request.header.user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.sec-ch-ua":"\"Not-A.Brand\";v=\"24\", \"Chromium\";v=\"146\"","http.request.header.content-type":"application/json","http.request.header.sec-ch-ua-mobile":"?0","http.request.header.accept":"*/*","http.request.header.origin":"http://127.0.0.1:6084","http.request.header.sec-fetch-site":"same-origin","http.request.header.sec-fetch-mode":"cors","http.request.header.sec-fetch-dest":"empty","http.request.header.referer":"http://127.0.0.1:6084/","http.request.header.accept-encoding":"gzip, deflate, br, zstd","http.request.header.accept-language":"en-GB","http.request.header.cookie":"","http.response.status_code":204},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"3f061bc80c80c593","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352610388190500","endTimeUnixNano":"1779352610446603084","durationMs":58.412584,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.server.updateSettings","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"45f4fa9a679d7411","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"internal","startTimeUnixNano":"1779352610679456000","endTimeUnixNano":"1779352610681684334","durationMs":2.228334,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"server.updateSettings","rpc.aggregate":"server"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"7fc8fed395255428d0cd5d776950bd9a","spanId":"ab96cc99ef09c278","parentSpanId":"45270740e89e5d70","sampled":true,"kind":"client","startTimeUnixNano":"1779352610951028750","endTimeUnixNano":"1779352610951096542","durationMs":0.067792,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n session_id AS \"sessionId\",\n subject AS \"subject\",\n role AS \"role\",\n method AS \"method\",\n client_label AS \"clientLabel\",\n client_ip_address AS \"clientIpAddress\",\n client_user_agent AS \"clientUserAgent\",\n client_device_type AS \"clientDeviceType\",\n client_os AS \"clientOs\",\n client_browser AS \"clientBrowser\",\n issued_at AS \"issuedAt\",\n expires_at AS \"expiresAt\",\n last_connected_at AS \"lastConnectedAt\",\n revoked_at AS \"revokedAt\"\n FROM auth_sessions\n WHERE session_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"otlp-span","name":"RpcClient.server.updateSettings","traceId":"52ad992b67f49a42ecac3159ad876f72","spanId":"5689d0549fe4734f","sampled":true,"kind":"internal","startTimeUnixNano":"1779352610778600000","endTimeUnixNano":"1779352610808800000","durationMs":30.2,"attributes":{},"resourceAttributes":{"service.runtime":"t3-web","service.mode":"electron","service.name":"t3-web","service.version":"0.0.24"},"scope":{"name":"t3-web","attributes":{}},"events":[],"links":[],"status":{"code":"1"}} -{"type":"effect-span","name":"http.server POST","traceId":"7fc8fed395255428d0cd5d776950bd9a","spanId":"45270740e89e5d70","sampled":true,"kind":"server","startTimeUnixNano":"1779352610950872417","endTimeUnixNano":"1779352610951323667","durationMs":0.45125,"attributes":{"http.route":"/api/observability/v1/traces","http.request.method":"POST","url.full":"http://127.0.0.1:14124/api/observability/v1/traces","url.path":"/api/observability/v1/traces","url.scheme":"http","user_agent.original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"close","http.request.header.content-length":"699","http.request.header.sec-ch-ua-platform":"\"macOS\"","http.request.header.user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.sec-ch-ua":"\"Not-A.Brand\";v=\"24\", \"Chromium\";v=\"146\"","http.request.header.content-type":"application/json","http.request.header.sec-ch-ua-mobile":"?0","http.request.header.accept":"*/*","http.request.header.origin":"http://127.0.0.1:6084","http.request.header.sec-fetch-site":"same-origin","http.request.header.sec-fetch-mode":"cors","http.request.header.sec-fetch-dest":"empty","http.request.header.referer":"http://127.0.0.1:6084/","http.request.header.accept-encoding":"gzip, deflate, br, zstd","http.request.header.accept-language":"en-GB","http.request.header.cookie":"","http.response.status_code":204},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.server.updateSettings","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"5c733df2165616db","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"internal","startTimeUnixNano":"1779352610996577125","endTimeUnixNano":"1779352610998298875","durationMs":1.72175,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"server.updateSettings","rpc.aggregate":"server"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.server.updateSettings","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"bbde527846258a16","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"internal","startTimeUnixNano":"1779352611605545042","endTimeUnixNano":"1779352611607515375","durationMs":1.970333,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"server.updateSettings","rpc.aggregate":"server"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5219866307b2120c86acdbf64bd50a86","spanId":"36f53695cf31065f","parentSpanId":"fde90855c2035436","sampled":true,"kind":"client","startTimeUnixNano":"1779352611956931459","endTimeUnixNano":"1779352611957159209","durationMs":0.22775,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n session_id AS \"sessionId\",\n subject AS \"subject\",\n role AS \"role\",\n method AS \"method\",\n client_label AS \"clientLabel\",\n client_ip_address AS \"clientIpAddress\",\n client_user_agent AS \"clientUserAgent\",\n client_device_type AS \"clientDeviceType\",\n client_os AS \"clientOs\",\n client_browser AS \"clientBrowser\",\n issued_at AS \"issuedAt\",\n expires_at AS \"expiresAt\",\n last_connected_at AS \"lastConnectedAt\",\n revoked_at AS \"revokedAt\"\n FROM auth_sessions\n WHERE session_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"otlp-span","name":"RpcClient.server.updateSettings","traceId":"9bee0b87a8e51b4dfa1d5788020aae84","spanId":"726abccd04aec558","sampled":true,"kind":"internal","startTimeUnixNano":"1779352611095700000","endTimeUnixNano":"1779352611116600000","durationMs":20.9,"attributes":{},"resourceAttributes":{"service.runtime":"t3-web","service.mode":"electron","service.name":"t3-web","service.version":"0.0.24"},"scope":{"name":"t3-web","attributes":{}},"events":[],"links":[],"status":{"code":"1"}} -{"type":"otlp-span","name":"RpcClient.server.updateSettings","traceId":"34697fc8378adbf7aeb5c88cbcf62a30","spanId":"e3acbc787e4f16a9","sampled":true,"kind":"internal","startTimeUnixNano":"1779352611704700000","endTimeUnixNano":"1779352611734500000","durationMs":29.8,"attributes":{},"resourceAttributes":{"service.runtime":"t3-web","service.mode":"electron","service.name":"t3-web","service.version":"0.0.24"},"scope":{"name":"t3-web","attributes":{}},"events":[],"links":[],"status":{"code":"1"}} -{"type":"effect-span","name":"http.server POST","traceId":"5219866307b2120c86acdbf64bd50a86","spanId":"fde90855c2035436","sampled":true,"kind":"server","startTimeUnixNano":"1779352611956452084","endTimeUnixNano":"1779352611957919959","durationMs":1.467875,"attributes":{"http.route":"/api/observability/v1/traces","http.request.method":"POST","url.full":"http://127.0.0.1:14124/api/observability/v1/traces","url.path":"/api/observability/v1/traces","url.scheme":"http","user_agent.original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"close","http.request.header.content-length":"1037","http.request.header.sec-ch-ua-platform":"\"macOS\"","http.request.header.user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.sec-ch-ua":"\"Not-A.Brand\";v=\"24\", \"Chromium\";v=\"146\"","http.request.header.content-type":"application/json","http.request.header.sec-ch-ua-mobile":"?0","http.request.header.accept":"*/*","http.request.header.origin":"http://127.0.0.1:6084","http.request.header.sec-fetch-site":"same-origin","http.request.header.sec-fetch-mode":"cors","http.request.header.sec-fetch-dest":"empty","http.request.header.referer":"http://127.0.0.1:6084/","http.request.header.accept-encoding":"gzip, deflate, br, zstd","http.request.header.accept-language":"en-GB","http.request.header.cookie":"","http.response.status_code":204},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.server.updateSettings","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"f583c2e1fdc279c5","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"internal","startTimeUnixNano":"1779352612165837375","endTimeUnixNano":"1779352612168285417","durationMs":2.448042,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"server.updateSettings","rpc.aggregate":"server"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.server.updateSettings","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"6850891d9fe67931","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"internal","startTimeUnixNano":"1779352612774301792","endTimeUnixNano":"1779352612776453917","durationMs":2.152125,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"server.updateSettings","rpc.aggregate":"server"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"53446e1e78046d28d00aeff303d4798e","spanId":"c23fc40efe2d4cee","parentSpanId":"851a39bf39708b14","sampled":true,"kind":"client","startTimeUnixNano":"1779352612962520500","endTimeUnixNano":"1779352612962589584","durationMs":0.069084,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n session_id AS \"sessionId\",\n subject AS \"subject\",\n role AS \"role\",\n method AS \"method\",\n client_label AS \"clientLabel\",\n client_ip_address AS \"clientIpAddress\",\n client_user_agent AS \"clientUserAgent\",\n client_device_type AS \"clientDeviceType\",\n client_os AS \"clientOs\",\n client_browser AS \"clientBrowser\",\n issued_at AS \"issuedAt\",\n expires_at AS \"expiresAt\",\n last_connected_at AS \"lastConnectedAt\",\n revoked_at AS \"revokedAt\"\n FROM auth_sessions\n WHERE session_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"otlp-span","name":"RpcClient.server.updateSettings","traceId":"727054617f5b162acc5e3382c6260c47","spanId":"d99ebb05b0600e09","sampled":true,"kind":"internal","startTimeUnixNano":"1779352612264800000","endTimeUnixNano":"1779352612289100000","durationMs":24.3,"attributes":{},"resourceAttributes":{"service.runtime":"t3-web","service.mode":"electron","service.name":"t3-web","service.version":"0.0.24"},"scope":{"name":"t3-web","attributes":{}},"events":[],"links":[],"status":{"code":"1"}} -{"type":"otlp-span","name":"RpcClient.server.updateSettings","traceId":"6ef74cc88aed11b0a5c38c158e4f27b6","spanId":"c62dd87357fead37","sampled":true,"kind":"internal","startTimeUnixNano":"1779352612873400000","endTimeUnixNano":"1779352612903100000","durationMs":29.7,"attributes":{},"resourceAttributes":{"service.runtime":"t3-web","service.mode":"electron","service.name":"t3-web","service.version":"0.0.24"},"scope":{"name":"t3-web","attributes":{}},"events":[],"links":[],"status":{"code":"1"}} -{"type":"effect-span","name":"http.server POST","traceId":"53446e1e78046d28d00aeff303d4798e","spanId":"851a39bf39708b14","sampled":true,"kind":"server","startTimeUnixNano":"1779352612962373875","endTimeUnixNano":"1779352612962810667","durationMs":0.436792,"attributes":{"http.route":"/api/observability/v1/traces","http.request.method":"POST","url.full":"http://127.0.0.1:14124/api/observability/v1/traces","url.path":"/api/observability/v1/traces","url.scheme":"http","user_agent.original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"close","http.request.header.content-length":"1037","http.request.header.sec-ch-ua-platform":"\"macOS\"","http.request.header.user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.sec-ch-ua":"\"Not-A.Brand\";v=\"24\", \"Chromium\";v=\"146\"","http.request.header.content-type":"application/json","http.request.header.sec-ch-ua-mobile":"?0","http.request.header.accept":"*/*","http.request.header.origin":"http://127.0.0.1:6084","http.request.header.sec-fetch-site":"same-origin","http.request.header.sec-fetch-mode":"cors","http.request.header.sec-fetch-dest":"empty","http.request.header.referer":"http://127.0.0.1:6084/","http.request.header.accept-encoding":"gzip, deflate, br, zstd","http.request.header.accept-language":"en-GB","http.request.header.cookie":"","http.response.status_code":204},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.server.updateSettings","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"35b9e94b4f67ad21","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"internal","startTimeUnixNano":"1779352614670522042","endTimeUnixNano":"1779352614672906709","durationMs":2.384667,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"server.updateSettings","rpc.aggregate":"server"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"170c9178bb5e47f4af2c4c295caaab66","spanId":"32f77cff3da64ea3","parentSpanId":"13194ecc4789c7ab","sampled":true,"kind":"client","startTimeUnixNano":"1779352614970840750","endTimeUnixNano":"1779352614971044334","durationMs":0.203584,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n session_id AS \"sessionId\",\n subject AS \"subject\",\n role AS \"role\",\n method AS \"method\",\n client_label AS \"clientLabel\",\n client_ip_address AS \"clientIpAddress\",\n client_user_agent AS \"clientUserAgent\",\n client_device_type AS \"clientDeviceType\",\n client_os AS \"clientOs\",\n client_browser AS \"clientBrowser\",\n issued_at AS \"issuedAt\",\n expires_at AS \"expiresAt\",\n last_connected_at AS \"lastConnectedAt\",\n revoked_at AS \"revokedAt\"\n FROM auth_sessions\n WHERE session_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"otlp-span","name":"RpcClient.server.updateSettings","traceId":"9b09374981292aa4fc7d07971be90e11","spanId":"b4ad6ce448e4da79","sampled":true,"kind":"internal","startTimeUnixNano":"1779352614769600000","endTimeUnixNano":"1779352614789400000","durationMs":19.8,"attributes":{},"resourceAttributes":{"service.runtime":"t3-web","service.mode":"electron","service.name":"t3-web","service.version":"0.0.24"},"scope":{"name":"t3-web","attributes":{}},"events":[],"links":[],"status":{"code":"1"}} -{"type":"effect-span","name":"http.server POST","traceId":"170c9178bb5e47f4af2c4c295caaab66","spanId":"13194ecc4789c7ab","sampled":true,"kind":"server","startTimeUnixNano":"1779352614970395834","endTimeUnixNano":"1779352614971858000","durationMs":1.462166,"attributes":{"http.route":"/api/observability/v1/traces","http.request.method":"POST","url.full":"http://127.0.0.1:14124/api/observability/v1/traces","url.path":"/api/observability/v1/traces","url.scheme":"http","user_agent.original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"close","http.request.header.content-length":"699","http.request.header.sec-ch-ua-platform":"\"macOS\"","http.request.header.user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.sec-ch-ua":"\"Not-A.Brand\";v=\"24\", \"Chromium\";v=\"146\"","http.request.header.content-type":"application/json","http.request.header.sec-ch-ua-mobile":"?0","http.request.header.accept":"*/*","http.request.header.origin":"http://127.0.0.1:6084","http.request.header.sec-fetch-site":"same-origin","http.request.header.sec-fetch-mode":"cors","http.request.header.sec-fetch-dest":"empty","http.request.header.referer":"http://127.0.0.1:6084/","http.request.header.accept-encoding":"gzip, deflate, br, zstd","http.request.header.accept-language":"en-GB","http.request.header.cookie":"","http.response.status_code":204},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.server.updateSettings","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"5123f81be57cfb84","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"internal","startTimeUnixNano":"1779352615143329584","endTimeUnixNano":"1779352615145648959","durationMs":2.319375,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"server.updateSettings","rpc.aggregate":"server"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"fc1202a97870b776","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352615448424542","endTimeUnixNano":"1779352615495067334","durationMs":46.642792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.server.updateSettings","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"9b97aea4aafead93","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"internal","startTimeUnixNano":"1779352615582307959","endTimeUnixNano":"1779352615584808709","durationMs":2.50075,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"server.updateSettings","rpc.aggregate":"server"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.server.updateSettings","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"cacf27baeb4f6d90","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"internal","startTimeUnixNano":"1779352615994425125","endTimeUnixNano":"1779352615997569209","durationMs":3.144084,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"server.updateSettings","rpc.aggregate":"server"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"d54dfecbe445b00cba59dd151a2991a3","spanId":"668bf7632e9f3a16","parentSpanId":"b6abf66dacfab94d","sampled":true,"kind":"client","startTimeUnixNano":"1779352615998268542","endTimeUnixNano":"1779352615998323834","durationMs":0.055292,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n session_id AS \"sessionId\",\n subject AS \"subject\",\n role AS \"role\",\n method AS \"method\",\n client_label AS \"clientLabel\",\n client_ip_address AS \"clientIpAddress\",\n client_user_agent AS \"clientUserAgent\",\n client_device_type AS \"clientDeviceType\",\n client_os AS \"clientOs\",\n client_browser AS \"clientBrowser\",\n issued_at AS \"issuedAt\",\n expires_at AS \"expiresAt\",\n last_connected_at AS \"lastConnectedAt\",\n revoked_at AS \"revokedAt\"\n FROM auth_sessions\n WHERE session_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"otlp-span","name":"RpcClient.server.updateSettings","traceId":"9bb128a86bdaf6d1f0931290e8905077","spanId":"df9aec8598980b24","sampled":true,"kind":"internal","startTimeUnixNano":"1779352615242400000","endTimeUnixNano":"1779352615272000000","durationMs":29.6,"attributes":{},"resourceAttributes":{"service.runtime":"t3-web","service.mode":"electron","service.name":"t3-web","service.version":"0.0.24"},"scope":{"name":"t3-web","attributes":{}},"events":[],"links":[],"status":{"code":"1"}} -{"type":"otlp-span","name":"RpcClient.server.updateSettings","traceId":"6fc0669a781a88d8106239133b9c3b31","spanId":"2740dfe5a3fc0b7f","sampled":true,"kind":"internal","startTimeUnixNano":"1779352615681500000","endTimeUnixNano":"1779352615703000000","durationMs":21.5,"attributes":{},"resourceAttributes":{"service.runtime":"t3-web","service.mode":"electron","service.name":"t3-web","service.version":"0.0.24"},"scope":{"name":"t3-web","attributes":{}},"events":[],"links":[],"status":{"code":"1"}} -{"type":"effect-span","name":"http.server POST","traceId":"d54dfecbe445b00cba59dd151a2991a3","spanId":"b6abf66dacfab94d","sampled":true,"kind":"server","startTimeUnixNano":"1779352615998159542","endTimeUnixNano":"1779352615998528167","durationMs":0.368625,"attributes":{"http.route":"/api/observability/v1/traces","http.request.method":"POST","url.full":"http://127.0.0.1:14124/api/observability/v1/traces","url.path":"/api/observability/v1/traces","url.scheme":"http","user_agent.original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"close","http.request.header.content-length":"1037","http.request.header.sec-ch-ua-platform":"\"macOS\"","http.request.header.user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.sec-ch-ua":"\"Not-A.Brand\";v=\"24\", \"Chromium\";v=\"146\"","http.request.header.content-type":"application/json","http.request.header.sec-ch-ua-mobile":"?0","http.request.header.accept":"*/*","http.request.header.origin":"http://127.0.0.1:6084","http.request.header.sec-fetch-site":"same-origin","http.request.header.sec-fetch-mode":"cors","http.request.header.sec-fetch-dest":"empty","http.request.header.referer":"http://127.0.0.1:6084/","http.request.header.accept-encoding":"gzip, deflate, br, zstd","http.request.header.accept-language":"en-GB","http.request.header.cookie":"","http.response.status_code":204},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"5c99a324af43f9f3ddca689604ddec3f","spanId":"aebf8e1ba2e54d0d","parentSpanId":"8a85284545270e0e","sampled":true,"kind":"client","startTimeUnixNano":"1779352617032902000","endTimeUnixNano":"1779352617033127584","durationMs":0.225584,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n session_id AS \"sessionId\",\n subject AS \"subject\",\n role AS \"role\",\n method AS \"method\",\n client_label AS \"clientLabel\",\n client_ip_address AS \"clientIpAddress\",\n client_user_agent AS \"clientUserAgent\",\n client_device_type AS \"clientDeviceType\",\n client_os AS \"clientOs\",\n client_browser AS \"clientBrowser\",\n issued_at AS \"issuedAt\",\n expires_at AS \"expiresAt\",\n last_connected_at AS \"lastConnectedAt\",\n revoked_at AS \"revokedAt\"\n FROM auth_sessions\n WHERE session_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"otlp-span","name":"RpcClient.server.updateSettings","traceId":"3b613ccd98e9cb3241a6913e06749305","spanId":"e33bf3fd9bbdff85","sampled":true,"kind":"internal","startTimeUnixNano":"1779352616093600000","endTimeUnixNano":"1779352616098900000","durationMs":5.3,"attributes":{},"resourceAttributes":{"service.runtime":"t3-web","service.mode":"electron","service.name":"t3-web","service.version":"0.0.24"},"scope":{"name":"t3-web","attributes":{}},"events":[],"links":[],"status":{"code":"1"}} -{"type":"effect-span","name":"http.server POST","traceId":"5c99a324af43f9f3ddca689604ddec3f","spanId":"8a85284545270e0e","sampled":true,"kind":"server","startTimeUnixNano":"1779352617032285834","endTimeUnixNano":"1779352617033925917","durationMs":1.640083,"attributes":{"http.route":"/api/observability/v1/traces","http.request.method":"POST","url.full":"http://127.0.0.1:14124/api/observability/v1/traces","url.path":"/api/observability/v1/traces","url.scheme":"http","user_agent.original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"close","http.request.header.content-length":"699","http.request.header.sec-ch-ua-platform":"\"macOS\"","http.request.header.user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.sec-ch-ua":"\"Not-A.Brand\";v=\"24\", \"Chromium\";v=\"146\"","http.request.header.content-type":"application/json","http.request.header.sec-ch-ua-mobile":"?0","http.request.header.accept":"*/*","http.request.header.origin":"http://127.0.0.1:6084","http.request.header.sec-fetch-site":"same-origin","http.request.header.sec-fetch-mode":"cors","http.request.header.sec-fetch-dest":"empty","http.request.header.referer":"http://127.0.0.1:6084/","http.request.header.accept-encoding":"gzip, deflate, br, zstd","http.request.header.accept-language":"en-GB","http.request.header.cookie":"","http.response.status_code":204},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeClaudeEnvironment","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"ab06218e8709be69","parentSpanId":"5cefb477e5249d80","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620240105542","endTimeUnixNano":"1779352620240143959","durationMs":0.038417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runClaudeCommand","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"5cefb477e5249d80","parentSpanId":"7dfdee148e49be7b","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620240062084","endTimeUnixNano":"1779352620243715792","durationMs":3.653708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"PlatformError: NotFound: ChildProcess.spawn (claude --version)\n at Module.systemError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/PlatformError.js:59:39)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/internal/utils.js:28:24\n at toPlatformError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:25:54)\n at ChildProcess. (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:230:26)\n at ChildProcess.emit (node:events:509:28)\n at ChildProcess._handle.onexit (node:internal/child_process:293:12)\n at onErrorNT (node:internal/child_process:508:16)\n at processTicksAndRejections (node:internal/process/task_queues:90:21)\n at runNextTicks (node:internal/process/task_queues:69:3)\n at listOnTimeout (node:internal/timers:567:9)\n at runClaudeCommand (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:27894:30)\n at runClaudeCommand (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:27870:33)\n at checkClaudeProviderStatus (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30400:25)\n at checkClaudeProviderStatus (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:27878:42)\n at applySnapshot (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30277:83)\n at applySnapshot (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30257:35)\n at refreshSnapshot (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30282:102)\n at refreshSnapshot (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30278:33)\n at makeManagedServerProvider (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30401:27)\n at makeManagedServerProvider (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30222:42) {\n [cause]: Error: spawn claude ENOENT\n at ChildProcess._handle.onexit (node:internal/child_process:287:19)\n at onErrorNT (node:internal/child_process:508:16)\n at processTicksAndRejections (node:internal/process/task_queues:90:21)\n at runNextTicks (node:internal/process/task_queues:69:3)\n at listOnTimeout (node:internal/timers:567:9)\n at process.processTimers (node:internal/timers:541:7)\n}"}} -{"type":"effect-span","name":"checkClaudeProviderStatus","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"7dfdee148e49be7b","parentSpanId":"ddb60a0f2fdafa21","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620239844750","endTimeUnixNano":"1779352620244101125","durationMs":4.256375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"689d4627b18ceffa7a72145a62a9452f","spanId":"03fa63008dc4b733","parentSpanId":"a54eb788ca1084e1","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620244324542","endTimeUnixNano":"1779352620244344167","durationMs":0.019625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"689d4627b18ceffa7a72145a62a9452f","spanId":"49c240be297aa093","parentSpanId":"a54eb788ca1084e1","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620244507334","endTimeUnixNano":"1779352620244537125","durationMs":0.029791,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"4ff06af085e133da","parentSpanId":"ddb60a0f2fdafa21","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620244710209","endTimeUnixNano":"1779352620244798917","durationMs":0.088708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"ddb60a0f2fdafa21","parentSpanId":"250fc519cebfaad5","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620239790042","endTimeUnixNano":"1779352620244809417","durationMs":5.019375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"250fc519cebfaad5","parentSpanId":"d8882d30663dbbb0","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620239652917","endTimeUnixNano":"1779352620244825209","durationMs":5.172292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"checkCursorProviderStatus","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"1f5062d9db6ad478","parentSpanId":"931c8fda4ac45201","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620244951750","endTimeUnixNano":"1779352620244998459","durationMs":0.046709,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"a4ce97a28f3bf83fcd219b2fa02e3de2","spanId":"fd0ff918c8931a48","parentSpanId":"53e70a8a2ab04a11","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620245081834","endTimeUnixNano":"1779352620245094042","durationMs":0.012208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"a4ce97a28f3bf83fcd219b2fa02e3de2","spanId":"2615dada826a9fa6","parentSpanId":"53e70a8a2ab04a11","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620245159709","endTimeUnixNano":"1779352620245172584","durationMs":0.012875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"f0d143bf6f60a136","parentSpanId":"931c8fda4ac45201","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620245234167","endTimeUnixNano":"1779352620245293167","durationMs":0.059,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"931c8fda4ac45201","parentSpanId":"fb28fe15d0907cf9","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620244930875","endTimeUnixNano":"1779352620245303084","durationMs":0.372209,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"fb28fe15d0907cf9","parentSpanId":"f4270506fde844da","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620244902375","endTimeUnixNano":"1779352620245312084","durationMs":0.409709,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"82abb7e2fb5d2dc4","parentSpanId":"4ff06af085e133da","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620245518959","endTimeUnixNano":"1779352620245536542","durationMs":0.017583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"07b9e01287975b2d","parentSpanId":"4ff06af085e133da","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620245558042","endTimeUnixNano":"1779352620245610500","durationMs":0.052458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"a1f4567c2bffefa2","parentSpanId":"f0d143bf6f60a136","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620245645000","endTimeUnixNano":"1779352620245655084","durationMs":0.010084,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"92009592eca8ffc7","parentSpanId":"f0d143bf6f60a136","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620245677709","endTimeUnixNano":"1779352620245714292","durationMs":0.036583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"a4ce97a28f3bf83fcd219b2fa02e3de2","spanId":"53e70a8a2ab04a11","parentSpanId":"f479cd91e58ec7e9","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620245059375","endTimeUnixNano":"1779352620247545834","durationMs":2.486459,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"a4ce97a28f3bf83fcd219b2fa02e3de2","spanId":"f479cd91e58ec7e9","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620245040750","endTimeUnixNano":"1779352620247566084","durationMs":2.525334,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"efa83238cc210e8770698afcddfa77ca","spanId":"f8d626d0bb77fdb2","parentSpanId":"8d2764cc4ae6259c","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620247674750","endTimeUnixNano":"1779352620247690959","durationMs":0.016209,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"efa83238cc210e8770698afcddfa77ca","spanId":"129a871fbd9e2017","parentSpanId":"8d2764cc4ae6259c","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620247775917","endTimeUnixNano":"1779352620247791917","durationMs":0.016,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"689d4627b18ceffa7a72145a62a9452f","spanId":"a54eb788ca1084e1","parentSpanId":"0a0bbae065d55fbe","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620244270042","endTimeUnixNano":"1779352620248589417","durationMs":4.319375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"689d4627b18ceffa7a72145a62a9452f","spanId":"0a0bbae065d55fbe","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620244232292","endTimeUnixNano":"1779352620248603000","durationMs":4.370708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"94dc45c7ed702ab82c413bc8def88377","spanId":"916fe8a4da626c3c","parentSpanId":"76bc6a7e85bcce9c","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620248685875","endTimeUnixNano":"1779352620248699792","durationMs":0.013917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"94dc45c7ed702ab82c413bc8def88377","spanId":"1eae59b40887596c","parentSpanId":"76bc6a7e85bcce9c","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620248768209","endTimeUnixNano":"1779352620248781542","durationMs":0.013333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"94dc45c7ed702ab82c413bc8def88377","spanId":"76bc6a7e85bcce9c","parentSpanId":"83d12cee715abb99","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620248661417","endTimeUnixNano":"1779352620250330167","durationMs":1.66875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"94dc45c7ed702ab82c413bc8def88377","spanId":"83d12cee715abb99","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620248638375","endTimeUnixNano":"1779352620250352667","durationMs":1.714292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"efa83238cc210e8770698afcddfa77ca","spanId":"8d2764cc4ae6259c","parentSpanId":"433e5fca0247ce60","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620247645292","endTimeUnixNano":"1779352620250391500","durationMs":2.746208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"efa83238cc210e8770698afcddfa77ca","spanId":"433e5fca0247ce60","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620247620667","endTimeUnixNano":"1779352620250402834","durationMs":2.782167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeCodexAppServerPatchedProtocol","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"44710149639f729e","parentSpanId":"783c8213875e0dd1","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620427678292","endTimeUnixNano":"1779352620427861000","durationMs":0.182708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"effect-codex-app-server/CodexAppServerClient.make","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"783c8213875e0dd1","parentSpanId":"09f0cdb9805cd88a","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620427623709","endTimeUnixNano":"1779352620427941417","durationMs":0.317708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"requestAllCodexModels","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"b170d72d3d05a149","parentSpanId":"09f0cdb9805cd88a","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620470249834","endTimeUnixNano":"1779352620471455709","durationMs":1.205875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"probeCodexAppServerProvider","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"09f0cdb9805cd88a","parentSpanId":"f0c4581d8c91a3af","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620424683542","endTimeUnixNano":"1779352620507602000","durationMs":82.918458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"checkCodexProviderStatus","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"f0c4581d8c91a3af","parentSpanId":"8d4e47407f61575d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620424405584","endTimeUnixNano":"1779352620509145584","durationMs":84.74,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"1a886c9d99a07e4ede41f0ef0b130993","spanId":"e0fa43052fd3fc45","parentSpanId":"6daf7b08372e5253","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620509227625","endTimeUnixNano":"1779352620509234250","durationMs":0.006625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"1a886c9d99a07e4ede41f0ef0b130993","spanId":"fd974ba6e0d9673e","parentSpanId":"6daf7b08372e5253","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620509343917","endTimeUnixNano":"1779352620509353375","durationMs":0.009458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"d63c55b3b9066e70","parentSpanId":"8d4e47407f61575d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620509422709","endTimeUnixNano":"1779352620509450542","durationMs":0.027833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"8d4e47407f61575d","parentSpanId":"9282742b1c7c50e8","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620424349917","endTimeUnixNano":"1779352620509454084","durationMs":85.104167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"9282742b1c7c50e8","parentSpanId":"5bc4cdb3beb605ab","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620424228042","endTimeUnixNano":"1779352620509458125","durationMs":85.230083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveLatestProviderVersion","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"f7d0a6fd65ff4a88","parentSpanId":"515284aae6a6af69","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620509479167","endTimeUnixNano":"1779352620509487834","durationMs":0.008667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"515284aae6a6af69","parentSpanId":"d63c55b3b9066e70","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620509472209","endTimeUnixNano":"1779352620509509042","durationMs":0.036833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"849d679cce929274","parentSpanId":"d63c55b3b9066e70","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620509514959","endTimeUnixNano":"1779352620509531209","durationMs":0.01625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"1a886c9d99a07e4ede41f0ef0b130993","spanId":"6daf7b08372e5253","parentSpanId":"e89ed4e042417fae","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620509212459","endTimeUnixNano":"1779352620510030000","durationMs":0.817541,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"1a886c9d99a07e4ede41f0ef0b130993","spanId":"e89ed4e042417fae","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620509196750","endTimeUnixNano":"1779352620510036875","durationMs":0.840125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"d1595bd0bba01a76e6e36f969ea6c510","spanId":"4c4c89a1fc89b77e","parentSpanId":"e221439c84f8d99a","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620510079542","endTimeUnixNano":"1779352620510085125","durationMs":0.005583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"d1595bd0bba01a76e6e36f969ea6c510","spanId":"7c4f712c9bc2ac82","parentSpanId":"e221439c84f8d99a","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620510120667","endTimeUnixNano":"1779352620510127667","durationMs":0.007,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"d1595bd0bba01a76e6e36f969ea6c510","spanId":"e221439c84f8d99a","parentSpanId":"54b07c21e68a70f1","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620510068292","endTimeUnixNano":"1779352620510537042","durationMs":0.46875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"d1595bd0bba01a76e6e36f969ea6c510","spanId":"54b07c21e68a70f1","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620510055959","endTimeUnixNano":"1779352620510540459","durationMs":0.4845,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"953c086c02eb7240","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352620497376625","endTimeUnixNano":"1779352620523303042","durationMs":25.926417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"9c222a79013464bbed30efe9f66a4107","spanId":"7bbcd33695618d61","parentSpanId":"bdaa4ceb2b2577ba","sampled":true,"kind":"client","startTimeUnixNano":"1779352624778552625","endTimeUnixNano":"1779352624778625292","durationMs":0.072667,"attributes":{"server.mode":"desktop","server.port":14124,"server.host":"127.0.0.1","startup.phase":"reactors.start","db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n thread_id AS \"threadId\",\n provider_name AS \"providerName\",\n provider_instance_id AS \"providerInstanceId\",\n adapter_key AS \"adapterKey\",\n runtime_mode AS \"runtimeMode\",\n status,\n last_seen_at AS \"lastSeenAt\",\n resume_cursor_json AS \"resumeCursor\",\n runtime_payload_json AS \"runtimePayload\"\n FROM provider_session_runtime\n ORDER BY last_seen_at ASC, thread_id ASC\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"opencode.app.agents","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"665a5404078814a5","parentSpanId":"31cd4cd65b2de57a","sampled":true,"kind":"internal","startTimeUnixNano":"1779352625129049625","endTimeUnixNano":"1779352625332108250","durationMs":203.058625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"opencode.provider.list","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"eb56f3d39782afc8","parentSpanId":"31cd4cd65b2de57a","sampled":true,"kind":"internal","startTimeUnixNano":"1779352625128991250","endTimeUnixNano":"1779352625459535417","durationMs":330.544167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"94074f284666863a","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352625524978084","endTimeUnixNano":"1779352625551232834","durationMs":26.25475,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"checkOpenCodeProviderStatus","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"31cd4cd65b2de57a","parentSpanId":"0a09c7ac0f088a88","sampled":true,"kind":"internal","startTimeUnixNano":"1779352624417798375","endTimeUnixNano":"1779352626462858375","durationMs":2045.06,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"461b37b58f860cd1ddf8b8a3198797a5","spanId":"6d91dcc72d353ab0","parentSpanId":"30eda55a761d9a4d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352626463214334","endTimeUnixNano":"1779352626463244000","durationMs":0.029666,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"461b37b58f860cd1ddf8b8a3198797a5","spanId":"28c2a55b9ae111da","parentSpanId":"30eda55a761d9a4d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352626465003542","endTimeUnixNano":"1779352626465033834","durationMs":0.030292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"00318244629d38d8","parentSpanId":"0a09c7ac0f088a88","sampled":true,"kind":"internal","startTimeUnixNano":"1779352626465630917","endTimeUnixNano":"1779352626465752417","durationMs":0.1215,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"0a09c7ac0f088a88","parentSpanId":"73ab1281c3f5d821","sampled":true,"kind":"internal","startTimeUnixNano":"1779352624417737959","endTimeUnixNano":"1779352626465766209","durationMs":2048.02825,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"73ab1281c3f5d821","parentSpanId":"2f989ef1cbf60c79","sampled":true,"kind":"internal","startTimeUnixNano":"1779352624417603542","endTimeUnixNano":"1779352626465781625","durationMs":2048.178083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveLatestProviderVersion","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"6c835354bc9266d6","parentSpanId":"1b01c6de9095ebb6","sampled":true,"kind":"internal","startTimeUnixNano":"1779352626465860625","endTimeUnixNano":"1779352626465890084","durationMs":0.029459,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"1b01c6de9095ebb6","parentSpanId":"00318244629d38d8","sampled":true,"kind":"internal","startTimeUnixNano":"1779352626465836667","endTimeUnixNano":"1779352626465963334","durationMs":0.126667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"f4b1946d9fb77669","parentSpanId":"00318244629d38d8","sampled":true,"kind":"internal","startTimeUnixNano":"1779352626465982042","endTimeUnixNano":"1779352626466054250","durationMs":0.072208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"461b37b58f860cd1ddf8b8a3198797a5","spanId":"30eda55a761d9a4d","parentSpanId":"181aea34f15d9912","sampled":true,"kind":"internal","startTimeUnixNano":"1779352626463118084","endTimeUnixNano":"1779352626467940375","durationMs":4.822291,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"461b37b58f860cd1ddf8b8a3198797a5","spanId":"181aea34f15d9912","sampled":true,"kind":"internal","startTimeUnixNano":"1779352626463061584","endTimeUnixNano":"1779352626467964000","durationMs":4.902416,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"dba9255529ebc948e305600cb187350f","spanId":"7f1bfe1a68ec61ae","parentSpanId":"5d427ba9de411bcb","sampled":true,"kind":"internal","startTimeUnixNano":"1779352626468075459","endTimeUnixNano":"1779352626468090500","durationMs":0.015041,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"dba9255529ebc948e305600cb187350f","spanId":"1e032df3b0133d92","parentSpanId":"5d427ba9de411bcb","sampled":true,"kind":"internal","startTimeUnixNano":"1779352626468219792","endTimeUnixNano":"1779352626468234375","durationMs":0.014583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"dba9255529ebc948e305600cb187350f","spanId":"5d427ba9de411bcb","parentSpanId":"04887d085543c267","sampled":true,"kind":"internal","startTimeUnixNano":"1779352626468045834","endTimeUnixNano":"1779352626470068917","durationMs":2.023083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"dba9255529ebc948e305600cb187350f","spanId":"04887d085543c267","sampled":true,"kind":"internal","startTimeUnixNano":"1779352626468019042","endTimeUnixNano":"1779352626470082917","durationMs":2.063875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"4cc18aab34098be4","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352630552797459","endTimeUnixNano":"1779352630609743000","durationMs":56.945541,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"invalidateRemoteStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"3f55ae79302784bb","parentSpanId":"8e1a370a3cd135ba","sampled":true,"kind":"internal","startTimeUnixNano":"1779352630879738209","endTimeUnixNano":"1779352630880474584","durationMs":0.736375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProjectConfig.findConfigPath","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"c6c8e81197fb48d6","parentSpanId":"3eb2b983d51d1d84","sampled":true,"kind":"internal","startTimeUnixNano":"1779352630880889167","endTimeUnixNano":"1779352630881592334","durationMs":0.703167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProjectConfig.resolveKind","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"3eb2b983d51d1d84","parentSpanId":"0a950a1a17a0bca4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352630880807500","endTimeUnixNano":"1779352630881619667","durationMs":0.812167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"966361194dca8bf2","parentSpanId":"47379866c8779c15","sampled":true,"kind":"internal","startTimeUnixNano":"1779352630884475209","endTimeUnixNano":"1779352630894719084","durationMs":10.243875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"111e4c5939ace33c","parentSpanId":"47379866c8779c15","sampled":true,"kind":"internal","startTimeUnixNano":"1779352630884361209","endTimeUnixNano":"1779352630894845125","durationMs":10.483916,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"47379866c8779c15","parentSpanId":"59d735e6cf51cfe3","sampled":true,"kind":"internal","startTimeUnixNano":"1779352630882349834","endTimeUnixNano":"1779352630894908042","durationMs":12.558208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProcess.run","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"59d735e6cf51cfe3","parentSpanId":"910113dfafc34651","sampled":true,"kind":"internal","startTimeUnixNano":"1779352630882184917","endTimeUnixNano":"1779352630895271667","durationMs":13.08675,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"detectRepository","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"910113dfafc34651","parentSpanId":"f64a620a46b34791","sampled":true,"kind":"internal","startTimeUnixNano":"1779352630882020334","endTimeUnixNano":"1779352630895291875","durationMs":13.271541,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsDriverRegistry.detectWithDriver","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"f64a620a46b34791","parentSpanId":"7ea5012d16af2280","sampled":true,"kind":"internal","startTimeUnixNano":"1779352630881877167","endTimeUnixNano":"1779352630895307250","durationMs":13.430083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsDriverRegistry.detectResolvedKind","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"7ea5012d16af2280","parentSpanId":"0a950a1a17a0bca4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352630881802792","endTimeUnixNano":"1779352630895331042","durationMs":13.52825,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsDriverRegistry.detect","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"0a950a1a17a0bca4","parentSpanId":"1d3f72bd05546180","sampled":true,"kind":"internal","startTimeUnixNano":"1779352630880728584","endTimeUnixNano":"1779352630895361625","durationMs":14.633041,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"GitWorkflowService.detectGitRepositoryForStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"1d3f72bd05546180","parentSpanId":"8e1a370a3cd135ba","sampled":true,"kind":"internal","startTimeUnixNano":"1779352630880599375","endTimeUnixNano":"1779352630895375834","durationMs":14.776459,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.updateCachedRemoteStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"4ddbe424089e9ef7","parentSpanId":"8e1a370a3cd135ba","sampled":true,"kind":"internal","startTimeUnixNano":"1779352630895429417","endTimeUnixNano":"1779352630895485375","durationMs":0.055958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.refreshRemoteStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"8e1a370a3cd135ba","parentSpanId":"15519d49086c4fd0","sampled":true,"kind":"internal","startTimeUnixNano":"1779352630879652917","endTimeUnixNano":"1779352630895496250","durationMs":15.843333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"f52d9c6e95bf6e7a","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352635611549584","endTimeUnixNano":"1779352635668831417","durationMs":57.281833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"9ac11e6db1bbaa59","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352640670221125","endTimeUnixNano":"1779352640728310375","durationMs":58.08925,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"0b1eb975cb7f682d","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352645730666625","endTimeUnixNano":"1779352645788349209","durationMs":57.682584,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"51a114ade233af01","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352650790369542","endTimeUnixNano":"1779352650848772917","durationMs":58.403375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"e6033adc03feec56","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352655850063250","endTimeUnixNano":"1779352655907133084","durationMs":57.069834,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"invalidateRemoteStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"94d82dbb813b193f","parentSpanId":"c32d547acd58329d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352660896829167","endTimeUnixNano":"1779352660897499834","durationMs":0.670667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProjectConfig.findConfigPath","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"5d01298098fa4227","parentSpanId":"1ba89d72fcba823f","sampled":true,"kind":"internal","startTimeUnixNano":"1779352660897836542","endTimeUnixNano":"1779352660899320209","durationMs":1.483667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProjectConfig.resolveKind","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"1ba89d72fcba823f","parentSpanId":"5a5e59da73984854","sampled":true,"kind":"internal","startTimeUnixNano":"1779352660897778584","endTimeUnixNano":"1779352660899356834","durationMs":1.57825,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"e48d4593e498dad8","parentSpanId":"dba410bdba21f3c5","sampled":true,"kind":"internal","startTimeUnixNano":"1779352660901872167","endTimeUnixNano":"1779352660912238334","durationMs":10.366167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"e51cb87e53d436bc","parentSpanId":"dba410bdba21f3c5","sampled":true,"kind":"internal","startTimeUnixNano":"1779352660901762167","endTimeUnixNano":"1779352660912311125","durationMs":10.548958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"dba410bdba21f3c5","parentSpanId":"66258aca95d56c88","sampled":true,"kind":"internal","startTimeUnixNano":"1779352660899766500","endTimeUnixNano":"1779352660912359917","durationMs":12.593417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProcess.run","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"66258aca95d56c88","parentSpanId":"b8f2b6fdf4dfcbd8","sampled":true,"kind":"internal","startTimeUnixNano":"1779352660899661292","endTimeUnixNano":"1779352660912540000","durationMs":12.878708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"detectRepository","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"b8f2b6fdf4dfcbd8","parentSpanId":"e0560f3c0c113d52","sampled":true,"kind":"internal","startTimeUnixNano":"1779352660899579167","endTimeUnixNano":"1779352660912552875","durationMs":12.973708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsDriverRegistry.detectWithDriver","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"e0560f3c0c113d52","parentSpanId":"e9b03343e54257d3","sampled":true,"kind":"internal","startTimeUnixNano":"1779352660899548625","endTimeUnixNano":"1779352660912562000","durationMs":13.013375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsDriverRegistry.detectResolvedKind","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"e9b03343e54257d3","parentSpanId":"5a5e59da73984854","sampled":true,"kind":"internal","startTimeUnixNano":"1779352660899494209","endTimeUnixNano":"1779352660912571125","durationMs":13.076916,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsDriverRegistry.detect","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"5a5e59da73984854","parentSpanId":"3279fb83aeffd3e6","sampled":true,"kind":"internal","startTimeUnixNano":"1779352660897716375","endTimeUnixNano":"1779352660912588750","durationMs":14.872375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"GitWorkflowService.detectGitRepositoryForStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"3279fb83aeffd3e6","parentSpanId":"c32d547acd58329d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352660897622084","endTimeUnixNano":"1779352660912597834","durationMs":14.97575,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.updateCachedRemoteStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"7d8d978293ed479a","parentSpanId":"c32d547acd58329d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352660912630209","endTimeUnixNano":"1779352660912663084","durationMs":0.032875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.refreshRemoteStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"c32d547acd58329d","parentSpanId":"15519d49086c4fd0","sampled":true,"kind":"internal","startTimeUnixNano":"1779352660896742000","endTimeUnixNano":"1779352660912670917","durationMs":15.928917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"e3f4353dac02b8b6","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352660908894250","endTimeUnixNano":"1779352660957121292","durationMs":48.227042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"104ac68638d23f17","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352665959115917","endTimeUnixNano":"1779352666015316000","durationMs":56.200083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"719d43684e23c80e","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352671017695292","endTimeUnixNano":"1779352671074935875","durationMs":57.240583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"1ad89b7d0cbb1dae","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352676075873584","endTimeUnixNano":"1779352676133503334","durationMs":57.62975,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"f1523d002f11a24f","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352681135626500","endTimeUnixNano":"1779352681193488625","durationMs":57.862125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"54439dc1a574461e","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352686195176125","endTimeUnixNano":"1779352686251627292","durationMs":56.451167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"invalidateRemoteStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"2052a28bcc6850c2","parentSpanId":"4c5ebca65dedae80","sampled":true,"kind":"internal","startTimeUnixNano":"1779352690913998792","endTimeUnixNano":"1779352690914695167","durationMs":0.696375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProjectConfig.findConfigPath","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"d93378fc33ef5bc3","parentSpanId":"408d3e235065b258","sampled":true,"kind":"internal","startTimeUnixNano":"1779352690915038084","endTimeUnixNano":"1779352690916971875","durationMs":1.933791,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProjectConfig.resolveKind","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"408d3e235065b258","parentSpanId":"2f24070236e14ed0","sampled":true,"kind":"internal","startTimeUnixNano":"1779352690914981125","endTimeUnixNano":"1779352690917015334","durationMs":2.034209,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"aa9dddd6d93bb01f","parentSpanId":"8abbc214288425cc","sampled":true,"kind":"internal","startTimeUnixNano":"1779352690919695375","endTimeUnixNano":"1779352690929589209","durationMs":9.893834,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"cdf9b757931922ad","parentSpanId":"8abbc214288425cc","sampled":true,"kind":"internal","startTimeUnixNano":"1779352690919589459","endTimeUnixNano":"1779352690929705667","durationMs":10.116208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"8abbc214288425cc","parentSpanId":"59a0c1d8170a041e","sampled":true,"kind":"internal","startTimeUnixNano":"1779352690917614084","endTimeUnixNano":"1779352690929774000","durationMs":12.159916,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProcess.run","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"59a0c1d8170a041e","parentSpanId":"53f5ce57670378dd","sampled":true,"kind":"internal","startTimeUnixNano":"1779352690917422584","endTimeUnixNano":"1779352690930078292","durationMs":12.655708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"detectRepository","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"53f5ce57670378dd","parentSpanId":"4ab3eba0860ae7d5","sampled":true,"kind":"internal","startTimeUnixNano":"1779352690917301167","endTimeUnixNano":"1779352690930103209","durationMs":12.802042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsDriverRegistry.detectWithDriver","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"4ab3eba0860ae7d5","parentSpanId":"dae545640346fc9a","sampled":true,"kind":"internal","startTimeUnixNano":"1779352690917241125","endTimeUnixNano":"1779352690930123042","durationMs":12.881917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsDriverRegistry.detectResolvedKind","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"dae545640346fc9a","parentSpanId":"2f24070236e14ed0","sampled":true,"kind":"internal","startTimeUnixNano":"1779352690917169625","endTimeUnixNano":"1779352690930140334","durationMs":12.970709,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsDriverRegistry.detect","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"2f24070236e14ed0","parentSpanId":"a2a1ff66337b8923","sampled":true,"kind":"internal","startTimeUnixNano":"1779352690914919667","endTimeUnixNano":"1779352690930174709","durationMs":15.255042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"GitWorkflowService.detectGitRepositoryForStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"a2a1ff66337b8923","parentSpanId":"4c5ebca65dedae80","sampled":true,"kind":"internal","startTimeUnixNano":"1779352690914838500","endTimeUnixNano":"1779352690930188834","durationMs":15.350334,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.updateCachedRemoteStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"492ccf6846ac6462","parentSpanId":"4c5ebca65dedae80","sampled":true,"kind":"internal","startTimeUnixNano":"1779352690930228792","endTimeUnixNano":"1779352690930281792","durationMs":0.053,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.refreshRemoteStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"4c5ebca65dedae80","parentSpanId":"15519d49086c4fd0","sampled":true,"kind":"internal","startTimeUnixNano":"1779352690913919834","endTimeUnixNano":"1779352690930293042","durationMs":16.373208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"5ddce89d9e35add3","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352691251915250","endTimeUnixNano":"1779352691307734334","durationMs":55.819084,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"492f4457bb21a3e3","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352696307807459","endTimeUnixNano":"1779352696366823875","durationMs":59.016416,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"c670fceef3c49aac","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352701367778750","endTimeUnixNano":"1779352701427558584","durationMs":59.779834,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"aba832ca8409ec20","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352706429309209","endTimeUnixNano":"1779352706487255084","durationMs":57.945875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"3851273b6e79143e","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352711488109875","endTimeUnixNano":"1779352711547119292","durationMs":59.009417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"51fb343ddf26a11c","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352716549807959","endTimeUnixNano":"1779352716603264334","durationMs":53.456375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"invalidateRemoteStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"65299779e0647bec","parentSpanId":"fc533183a1009133","sampled":true,"kind":"internal","startTimeUnixNano":"1779352720932201542","endTimeUnixNano":"1779352720932857042","durationMs":0.6555,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProjectConfig.findConfigPath","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"79acfb1e3a78a8c0","parentSpanId":"6313df5c17d354aa","sampled":true,"kind":"internal","startTimeUnixNano":"1779352720933251042","endTimeUnixNano":"1779352720935045209","durationMs":1.794167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProjectConfig.resolveKind","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"6313df5c17d354aa","parentSpanId":"beade0aaf1840cf2","sampled":true,"kind":"internal","startTimeUnixNano":"1779352720933185375","endTimeUnixNano":"1779352720935104084","durationMs":1.918709,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"fb266de18912e00b","parentSpanId":"276f8e2cf4ace693","sampled":true,"kind":"internal","startTimeUnixNano":"1779352720937716250","endTimeUnixNano":"1779352720947917292","durationMs":10.201042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"e6c9532ccfccdc8f","parentSpanId":"276f8e2cf4ace693","sampled":true,"kind":"internal","startTimeUnixNano":"1779352720937606584","endTimeUnixNano":"1779352720948023834","durationMs":10.41725,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"276f8e2cf4ace693","parentSpanId":"6ceb92b03c8c2379","sampled":true,"kind":"internal","startTimeUnixNano":"1779352720935615084","endTimeUnixNano":"1779352720948092709","durationMs":12.477625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProcess.run","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"6ceb92b03c8c2379","parentSpanId":"764c58feaf1eab92","sampled":true,"kind":"internal","startTimeUnixNano":"1779352720935469917","endTimeUnixNano":"1779352720948412000","durationMs":12.942083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"detectRepository","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"764c58feaf1eab92","parentSpanId":"5a6ba87d62af0d76","sampled":true,"kind":"internal","startTimeUnixNano":"1779352720935356125","endTimeUnixNano":"1779352720948433375","durationMs":13.07725,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsDriverRegistry.detectWithDriver","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"5a6ba87d62af0d76","parentSpanId":"6eada6235e49e87f","sampled":true,"kind":"internal","startTimeUnixNano":"1779352720935303500","endTimeUnixNano":"1779352720948449750","durationMs":13.14625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsDriverRegistry.detectResolvedKind","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"6eada6235e49e87f","parentSpanId":"beade0aaf1840cf2","sampled":true,"kind":"internal","startTimeUnixNano":"1779352720935239959","endTimeUnixNano":"1779352720948463084","durationMs":13.223125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsDriverRegistry.detect","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"beade0aaf1840cf2","parentSpanId":"a05ede1729371d63","sampled":true,"kind":"internal","startTimeUnixNano":"1779352720933117834","endTimeUnixNano":"1779352720948513959","durationMs":15.396125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"GitWorkflowService.detectGitRepositoryForStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"a05ede1729371d63","parentSpanId":"fc533183a1009133","sampled":true,"kind":"internal","startTimeUnixNano":"1779352720933014584","endTimeUnixNano":"1779352720948526792","durationMs":15.512208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.updateCachedRemoteStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"ab71a17a95c51982","parentSpanId":"fc533183a1009133","sampled":true,"kind":"internal","startTimeUnixNano":"1779352720948571584","endTimeUnixNano":"1779352720948620792","durationMs":0.049208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.refreshRemoteStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"fc533183a1009133","parentSpanId":"15519d49086c4fd0","sampled":true,"kind":"internal","startTimeUnixNano":"1779352720932092042","endTimeUnixNano":"1779352720948630917","durationMs":16.538875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"0e7abefbb618964d","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352721605785667","endTimeUnixNano":"1779352721664305959","durationMs":58.520292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"57773a1bee1cc93d","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352726666508084","endTimeUnixNano":"1779352726723804542","durationMs":57.296458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"3c437d5c0d4fec37","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352731724790959","endTimeUnixNano":"1779352731780861209","durationMs":56.07025,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"38e802bff4c62996","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352736782258500","endTimeUnixNano":"1779352736840851084","durationMs":58.592584,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"0a055b9eaf7bbf88","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352741842534625","endTimeUnixNano":"1779352741900073042","durationMs":57.538417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"1e57b45b039b7633","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352746902263417","endTimeUnixNano":"1779352746959844792","durationMs":57.581375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"invalidateRemoteStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"d8d1563a25d7573a","parentSpanId":"e7233977cf383398","sampled":true,"kind":"internal","startTimeUnixNano":"1779352750950310667","endTimeUnixNano":"1779352750952306375","durationMs":1.995708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProjectConfig.findConfigPath","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"efa35bf184f43de6","parentSpanId":"5b3e185bfeffe3de","sampled":true,"kind":"internal","startTimeUnixNano":"1779352750952597917","endTimeUnixNano":"1779352750953135167","durationMs":0.53725,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProjectConfig.resolveKind","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"5b3e185bfeffe3de","parentSpanId":"c3c36f512ac2934f","sampled":true,"kind":"internal","startTimeUnixNano":"1779352750952552167","endTimeUnixNano":"1779352750953156584","durationMs":0.604417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"40dba209a1c9698c","parentSpanId":"24525dc100c0406f","sampled":true,"kind":"internal","startTimeUnixNano":"1779352750955620709","endTimeUnixNano":"1779352750965948542","durationMs":10.327833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"556344010c906f7a","parentSpanId":"24525dc100c0406f","sampled":true,"kind":"internal","startTimeUnixNano":"1779352750955512292","endTimeUnixNano":"1779352750966065375","durationMs":10.553083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"24525dc100c0406f","parentSpanId":"b7100bb239002b70","sampled":true,"kind":"internal","startTimeUnixNano":"1779352750953630167","endTimeUnixNano":"1779352750966133042","durationMs":12.502875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProcess.run","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"b7100bb239002b70","parentSpanId":"408d728555362b3e","sampled":true,"kind":"internal","startTimeUnixNano":"1779352750953493500","endTimeUnixNano":"1779352750966467834","durationMs":12.974334,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"detectRepository","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"408d728555362b3e","parentSpanId":"0a482b8244c16ddc","sampled":true,"kind":"internal","startTimeUnixNano":"1779352750953387584","endTimeUnixNano":"1779352750966490459","durationMs":13.102875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsDriverRegistry.detectWithDriver","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"0a482b8244c16ddc","parentSpanId":"3b542b3a7b22f71b","sampled":true,"kind":"internal","startTimeUnixNano":"1779352750953345334","endTimeUnixNano":"1779352750966505542","durationMs":13.160208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsDriverRegistry.detectResolvedKind","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"3b542b3a7b22f71b","parentSpanId":"c3c36f512ac2934f","sampled":true,"kind":"internal","startTimeUnixNano":"1779352750953295459","endTimeUnixNano":"1779352750966536292","durationMs":13.240833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsDriverRegistry.detect","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"c3c36f512ac2934f","parentSpanId":"5b8a758c7c24b2ca","sampled":true,"kind":"internal","startTimeUnixNano":"1779352750952505000","endTimeUnixNano":"1779352750966567667","durationMs":14.062667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"GitWorkflowService.detectGitRepositoryForStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"5b8a758c7c24b2ca","parentSpanId":"e7233977cf383398","sampled":true,"kind":"internal","startTimeUnixNano":"1779352750952443000","endTimeUnixNano":"1779352750966579917","durationMs":14.136917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.updateCachedRemoteStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"4f5607da0d28af1a","parentSpanId":"e7233977cf383398","sampled":true,"kind":"internal","startTimeUnixNano":"1779352750966658167","endTimeUnixNano":"1779352750966717834","durationMs":0.059667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.refreshRemoteStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"e7233977cf383398","parentSpanId":"15519d49086c4fd0","sampled":true,"kind":"internal","startTimeUnixNano":"1779352750950216542","endTimeUnixNano":"1779352750966726500","durationMs":16.509958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"6de2b824005d0de9","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352751961571792","endTimeUnixNano":"1779352752018676084","durationMs":57.104292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"532fbd0a53965a38","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352757020457125","endTimeUnixNano":"1779352757076597209","durationMs":56.140084,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"c7d592ad155b5675","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352762077928209","endTimeUnixNano":"1779352762135767792","durationMs":57.839583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"22ca6cc4dc4fc69c","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352767137692792","endTimeUnixNano":"1779352767197728792","durationMs":60.036,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"60b15af145655d0e","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352772199453959","endTimeUnixNano":"1779352772257001042","durationMs":57.547083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"881b5840eedd8bb3","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352777259257209","endTimeUnixNano":"1779352777318940917","durationMs":59.683708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"invalidateRemoteStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"b4cac26bb0fe53fd","parentSpanId":"7a37ddd6bb5e25ad","sampled":true,"kind":"internal","startTimeUnixNano":"1779352780969011375","endTimeUnixNano":"1779352780969665875","durationMs":0.6545,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProjectConfig.findConfigPath","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"ca5be29d16be3985","parentSpanId":"5c2001c753e71143","sampled":true,"kind":"internal","startTimeUnixNano":"1779352780970013917","endTimeUnixNano":"1779352780970571209","durationMs":0.557292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProjectConfig.resolveKind","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"5c2001c753e71143","parentSpanId":"3a376ecb3c09e2b1","sampled":true,"kind":"internal","startTimeUnixNano":"1779352780969943125","endTimeUnixNano":"1779352780970587625","durationMs":0.6445,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"1f439a2c0c66bfc6","parentSpanId":"5c635806adc15630","sampled":true,"kind":"internal","startTimeUnixNano":"1779352780973045500","endTimeUnixNano":"1779352780983454709","durationMs":10.409209,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"31acf4c1cf6c53e8","parentSpanId":"5c635806adc15630","sampled":true,"kind":"internal","startTimeUnixNano":"1779352780972935209","endTimeUnixNano":"1779352780983577334","durationMs":10.642125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"5c635806adc15630","parentSpanId":"9b07835ea28fd00e","sampled":true,"kind":"internal","startTimeUnixNano":"1779352780971021042","endTimeUnixNano":"1779352780983649125","durationMs":12.628083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProcess.run","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"9b07835ea28fd00e","parentSpanId":"20f6024189197eb2","sampled":true,"kind":"internal","startTimeUnixNano":"1779352780970869709","endTimeUnixNano":"1779352780983974750","durationMs":13.105041,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"detectRepository","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"20f6024189197eb2","parentSpanId":"cf3a33e6313614b0","sampled":true,"kind":"internal","startTimeUnixNano":"1779352780970791250","endTimeUnixNano":"1779352780983996125","durationMs":13.204875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsDriverRegistry.detectWithDriver","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"cf3a33e6313614b0","parentSpanId":"f75233ba0f9a7608","sampled":true,"kind":"internal","startTimeUnixNano":"1779352780970743125","endTimeUnixNano":"1779352780984010750","durationMs":13.267625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsDriverRegistry.detectResolvedKind","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"f75233ba0f9a7608","parentSpanId":"3a376ecb3c09e2b1","sampled":true,"kind":"internal","startTimeUnixNano":"1779352780970685542","endTimeUnixNano":"1779352780984027667","durationMs":13.342125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsDriverRegistry.detect","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"3a376ecb3c09e2b1","parentSpanId":"13255ea2cdc5f628","sampled":true,"kind":"internal","startTimeUnixNano":"1779352780969877542","endTimeUnixNano":"1779352780984065375","durationMs":14.187833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"GitWorkflowService.detectGitRepositoryForStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"13255ea2cdc5f628","parentSpanId":"7a37ddd6bb5e25ad","sampled":true,"kind":"internal","startTimeUnixNano":"1779352780969785375","endTimeUnixNano":"1779352780984085334","durationMs":14.299959,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.updateCachedRemoteStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"c8e8de0882219b0a","parentSpanId":"7a37ddd6bb5e25ad","sampled":true,"kind":"internal","startTimeUnixNano":"1779352780984127500","endTimeUnixNano":"1779352780984188125","durationMs":0.060625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.refreshRemoteStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"7a37ddd6bb5e25ad","parentSpanId":"15519d49086c4fd0","sampled":true,"kind":"internal","startTimeUnixNano":"1779352780968921959","endTimeUnixNano":"1779352780984198042","durationMs":15.276083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"947761f91234b8af","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352782319348000","endTimeUnixNano":"1779352782377337625","durationMs":57.989625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"adf8a12b20d328e4","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352787379665584","endTimeUnixNano":"1779352787437984875","durationMs":58.319291,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"e2c91253a70408bc","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352792440703625","endTimeUnixNano":"1779352792512889209","durationMs":72.185584,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"1a7b80309eb319ad","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352797514624334","endTimeUnixNano":"1779352797573293417","durationMs":58.669083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"869c0908c1f15476","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352802575707417","endTimeUnixNano":"1779352802629415334","durationMs":53.707917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"80fd096d3cb1053a","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352807631360167","endTimeUnixNano":"1779352807689169292","durationMs":57.809125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"invalidateRemoteStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"1f2114be33a2a3d4","parentSpanId":"da2c2848ea22299d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352810984050792","endTimeUnixNano":"1779352810984241000","durationMs":0.190208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProjectConfig.findConfigPath","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"69a02dc15c270611","parentSpanId":"7d0a0a9659af39d9","sampled":true,"kind":"internal","startTimeUnixNano":"1779352810984315125","endTimeUnixNano":"1779352810984456709","durationMs":0.141584,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProjectConfig.resolveKind","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"7d0a0a9659af39d9","parentSpanId":"69663c9ed533f569","sampled":true,"kind":"internal","startTimeUnixNano":"1779352810984305084","endTimeUnixNano":"1779352810984462000","durationMs":0.156916,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"6a427d156520759b","parentSpanId":"1d3d34880b7df29b","sampled":true,"kind":"internal","startTimeUnixNano":"1779352810985205125","endTimeUnixNano":"1779352810989232042","durationMs":4.026917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"10e54ad51b24e827","parentSpanId":"1d3d34880b7df29b","sampled":true,"kind":"internal","startTimeUnixNano":"1779352810985172459","endTimeUnixNano":"1779352810989271292","durationMs":4.098833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"1d3d34880b7df29b","parentSpanId":"378897671482ee20","sampled":true,"kind":"internal","startTimeUnixNano":"1779352810984569584","endTimeUnixNano":"1779352810989298834","durationMs":4.72925,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProcess.run","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"378897671482ee20","parentSpanId":"f2d98642b96e98b5","sampled":true,"kind":"internal","startTimeUnixNano":"1779352810984542000","endTimeUnixNano":"1779352810989390625","durationMs":4.848625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"detectRepository","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"f2d98642b96e98b5","parentSpanId":"a9c1ba74e8824c85","sampled":true,"kind":"internal","startTimeUnixNano":"1779352810984512292","endTimeUnixNano":"1779352810989397417","durationMs":4.885125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsDriverRegistry.detectWithDriver","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"a9c1ba74e8824c85","parentSpanId":"1fa95b3476ee945c","sampled":true,"kind":"internal","startTimeUnixNano":"1779352810984502667","endTimeUnixNano":"1779352810989401375","durationMs":4.898708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsDriverRegistry.detectResolvedKind","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"1fa95b3476ee945c","parentSpanId":"69663c9ed533f569","sampled":true,"kind":"internal","startTimeUnixNano":"1779352810984491084","endTimeUnixNano":"1779352810989405875","durationMs":4.914791,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsDriverRegistry.detect","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"69663c9ed533f569","parentSpanId":"4936d97cc6eae599","sampled":true,"kind":"internal","startTimeUnixNano":"1779352810984292584","endTimeUnixNano":"1779352810989414709","durationMs":5.122125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"GitWorkflowService.detectGitRepositoryForStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"4936d97cc6eae599","parentSpanId":"da2c2848ea22299d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352810984271584","endTimeUnixNano":"1779352810989420584","durationMs":5.149,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.updateCachedRemoteStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"939b48700f3fc1ec","parentSpanId":"da2c2848ea22299d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352810989432292","endTimeUnixNano":"1779352810989446917","durationMs":0.014625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.refreshRemoteStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"da2c2848ea22299d","parentSpanId":"15519d49086c4fd0","sampled":true,"kind":"internal","startTimeUnixNano":"1779352810984030667","endTimeUnixNano":"1779352810989450709","durationMs":5.420042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"18e953b6a49b7d71","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352812691504709","endTimeUnixNano":"1779352812747441917","durationMs":55.937208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"341e69faef5284b1","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352817749152834","endTimeUnixNano":"1779352817807913042","durationMs":58.760208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.releaseRemotePoller","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"e9905cc04939bd0a","parentSpanId":"2dad6716c4a3cab9","sampled":true,"kind":"internal","startTimeUnixNano":"1779352820221738459","endTimeUnixNano":"1779352820221801292","durationMs":0.062833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.subscribeVcsStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"2dad6716c4a3cab9","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600869422000","endTimeUnixNano":"1779352820221914417","durationMs":219352.492417,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"subscribeVcsStatus","rpc.aggregate":"vcs"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.getCachedStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"e806477f87fb19bb","parentSpanId":"9ac9a0a0794834cf","sampled":true,"kind":"internal","startTimeUnixNano":"1779352820240778375","endTimeUnixNano":"1779352820240787250","durationMs":0.008875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.getOrLoadLocalStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"9ac9a0a0794834cf","parentSpanId":"d7ffc9a51d150c55","sampled":true,"kind":"internal","startTimeUnixNano":"1779352820240764959","endTimeUnixNano":"1779352820240797500","durationMs":0.032541,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.getCachedStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"52005ba1f92c3125","parentSpanId":"d7ffc9a51d150c55","sampled":true,"kind":"internal","startTimeUnixNano":"1779352820240803542","endTimeUnixNano":"1779352820240808542","durationMs":0.005,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.retainRemotePoller","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"a1d260ecbc3c9e80","parentSpanId":"d7ffc9a51d150c55","sampled":true,"kind":"internal","startTimeUnixNano":"1779352820240814584","endTimeUnixNano":"1779352820240839667","durationMs":0.025083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProjectConfig.findConfigPath","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"17059d45f381835c","parentSpanId":"b59956e8d6025d60","sampled":true,"kind":"internal","startTimeUnixNano":"1779352820240664875","endTimeUnixNano":"1779352820241071500","durationMs":0.406625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProjectConfig.resolveKind","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"b59956e8d6025d60","parentSpanId":"b655a7c993ffcb22","sampled":true,"kind":"internal","startTimeUnixNano":"1779352820240657084","endTimeUnixNano":"1779352820241076417","durationMs":0.419333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"invalidateRemoteStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"c6128f845d0b1b74","parentSpanId":"9133add8c6b2ee0e","sampled":true,"kind":"internal","startTimeUnixNano":"1779352820241004250","endTimeUnixNano":"1779352820241200209","durationMs":0.195959,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProjectConfig.findConfigPath","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"68e082f02cb5ba74","parentSpanId":"2660d599dbf7497e","sampled":true,"kind":"internal","startTimeUnixNano":"1779352820241268542","endTimeUnixNano":"1779352820242162834","durationMs":0.894292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProjectConfig.resolveKind","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"2660d599dbf7497e","parentSpanId":"c57bd943746d803b","sampled":true,"kind":"internal","startTimeUnixNano":"1779352820241258125","endTimeUnixNano":"1779352820242167292","durationMs":0.909167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"d761918d9507336e","parentSpanId":"29195acae1c0ac8f","sampled":true,"kind":"internal","startTimeUnixNano":"1779352820242084167","endTimeUnixNano":"1779352820248796125","durationMs":6.711958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.collectText","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"aeca78edc45d9596","parentSpanId":"29195acae1c0ac8f","sampled":true,"kind":"internal","startTimeUnixNano":"1779352820242051459","endTimeUnixNano":"1779352820248833959","durationMs":6.7825,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"processRunner.runProcessCore","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"29195acae1c0ac8f","parentSpanId":"0a2858002a4088cd","sampled":true,"kind":"internal","startTimeUnixNano":"1779352820241163625","endTimeUnixNano":"1779352820248861834","durationMs":7.698209,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsProcess.run","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"0a2858002a4088cd","parentSpanId":"5544883356a73a63","sampled":true,"kind":"internal","startTimeUnixNano":"1779352820241130292","endTimeUnixNano":"1779352820248956417","durationMs":7.826125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"detectRepository","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"5544883356a73a63","parentSpanId":"6633440ed8fbc11a","sampled":true,"kind":"internal","startTimeUnixNano":"1779352820241116750","endTimeUnixNano":"1779352820248962334","durationMs":7.845584,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsDriverRegistry.detectWithDriver","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"6633440ed8fbc11a","parentSpanId":"240d3e2585f74126","sampled":true,"kind":"internal","startTimeUnixNano":"1779352820241109709","endTimeUnixNano":"1779352820248965125","durationMs":7.855416,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsDriverRegistry.detectResolvedKind","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"240d3e2585f74126","parentSpanId":"b655a7c993ffcb22","sampled":true,"kind":"internal","startTimeUnixNano":"1779352820241100417","endTimeUnixNano":"1779352820248968167","durationMs":7.86775,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsDriverRegistry.detect","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"c57bd943746d803b","parentSpanId":"c866a3caca44a196","sampled":true,"kind":"internal","startTimeUnixNano":"1779352820241247042","endTimeUnixNano":"1779352820248972250","durationMs":7.725208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"GitWorkflowService.detectGitRepositoryForStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"c866a3caca44a196","parentSpanId":"9133add8c6b2ee0e","sampled":true,"kind":"internal","startTimeUnixNano":"1779352820241212209","endTimeUnixNano":"1779352820248975625","durationMs":7.763416,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.updateCachedRemoteStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"4c3b4845e4fe5647","parentSpanId":"9133add8c6b2ee0e","sampled":true,"kind":"internal","startTimeUnixNano":"1779352820248988542","endTimeUnixNano":"1779352820249003417","durationMs":0.014875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.refreshRemoteStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"9133add8c6b2ee0e","parentSpanId":"a1d260ecbc3c9e80","sampled":true,"kind":"internal","startTimeUnixNano":"1779352820240994459","endTimeUnixNano":"1779352820249005750","durationMs":8.011291,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"VcsDriverRegistry.detect","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"b655a7c993ffcb22","parentSpanId":"c4e651befa8eb8ff","sampled":true,"kind":"internal","startTimeUnixNano":"1779352820240646584","endTimeUnixNano":"1779352820249049584","durationMs":8.403,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"GitWorkflowService.detectGitRepositoryForCommand","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"c4e651befa8eb8ff","parentSpanId":"ca42c803aaa5fc16","sampled":true,"kind":"internal","startTimeUnixNano":"1779352820240630542","endTimeUnixNano":"1779352820249054750","durationMs":8.424208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.vcs.listRefs","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"ca42c803aaa5fc16","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"internal","startTimeUnixNano":"1779352820240614000","endTimeUnixNano":"1779352820249105834","durationMs":8.491834,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"vcs.listRefs","rpc.aggregate":"vcs"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"3b32914b9a9ca7b6a0d142227af62804","spanId":"052e822fc4a4c96b","parentSpanId":"6184c81f15b20617","sampled":true,"kind":"client","startTimeUnixNano":"1779352820257189792","endTimeUnixNano":"1779352820257241292","durationMs":0.0515,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n session_id AS \"sessionId\",\n subject AS \"subject\",\n role AS \"role\",\n method AS \"method\",\n client_label AS \"clientLabel\",\n client_ip_address AS \"clientIpAddress\",\n client_user_agent AS \"clientUserAgent\",\n client_device_type AS \"clientDeviceType\",\n client_os AS \"clientOs\",\n client_browser AS \"clientBrowser\",\n issued_at AS \"issuedAt\",\n expires_at AS \"expiresAt\",\n last_connected_at AS \"lastConnectedAt\",\n revoked_at AS \"revokedAt\"\n FROM auth_sessions\n WHERE session_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"otlp-span","name":"RpcClient.subscribeVcsStatus","traceId":"00c52af0c629a0b43ceac0dbcc2c92b7","spanId":"5ceef4ce8e111383","sampled":true,"kind":"internal","startTimeUnixNano":"1779352600966600000","endTimeUnixNano":"1779352820321100000","durationMs":219354.5,"attributes":{"span.label":"⚠︎ Interrupted","status.interrupted":true},"resourceAttributes":{"service.runtime":"t3-web","service.mode":"electron","service.name":"t3-web","service.version":"0.0.24"},"scope":{"name":"t3-web","attributes":{}},"events":[],"links":[],"status":{"code":"1","message":"Interrupted"}} -{"type":"effect-span","name":"http.server POST","traceId":"3b32914b9a9ca7b6a0d142227af62804","spanId":"6184c81f15b20617","sampled":true,"kind":"server","startTimeUnixNano":"1779352820257066042","endTimeUnixNano":"1779352820257547250","durationMs":0.481208,"attributes":{"http.route":"/api/observability/v1/traces","http.request.method":"POST","url.full":"http://127.0.0.1:14124/api/observability/v1/traces","url.path":"/api/observability/v1/traces","url.scheme":"http","user_agent.original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"close","http.request.header.content-length":"841","http.request.header.sec-ch-ua-platform":"\"macOS\"","http.request.header.user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.sec-ch-ua":"\"Not-A.Brand\";v=\"24\", \"Chromium\";v=\"146\"","http.request.header.content-type":"application/json","http.request.header.sec-ch-ua-mobile":"?0","http.request.header.accept":"*/*","http.request.header.origin":"http://127.0.0.1:6084","http.request.header.sec-fetch-site":"same-origin","http.request.header.sec-fetch-mode":"cors","http.request.header.sec-fetch-dest":"empty","http.request.header.referer":"http://127.0.0.1:6084/","http.request.header.accept-encoding":"gzip, deflate, br, zstd","http.request.header.accept-language":"en-GB","http.request.header.cookie":"","http.response.status_code":204},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"e0f061fe6f936d457afc5f9cc15aae2d","spanId":"f052271114b78f1c","parentSpanId":"a4c0b88496aa66ce","sampled":true,"kind":"client","startTimeUnixNano":"1779352821308215792","endTimeUnixNano":"1779352821308421125","durationMs":0.205333,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n session_id AS \"sessionId\",\n subject AS \"subject\",\n role AS \"role\",\n method AS \"method\",\n client_label AS \"clientLabel\",\n client_ip_address AS \"clientIpAddress\",\n client_user_agent AS \"clientUserAgent\",\n client_device_type AS \"clientDeviceType\",\n client_os AS \"clientOs\",\n client_browser AS \"clientBrowser\",\n issued_at AS \"issuedAt\",\n expires_at AS \"expiresAt\",\n last_connected_at AS \"lastConnectedAt\",\n revoked_at AS \"revokedAt\"\n FROM auth_sessions\n WHERE session_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"otlp-span","name":"RpcClient.vcs.listRefs","traceId":"64d6775fa358c1facca08f8e7e0b1419","spanId":"9c4f973f3336e256","sampled":true,"kind":"internal","startTimeUnixNano":"1779352820339600000","endTimeUnixNano":"1779352820368100000","durationMs":28.5,"attributes":{},"resourceAttributes":{"service.runtime":"t3-web","service.mode":"electron","service.name":"t3-web","service.version":"0.0.24"},"scope":{"name":"t3-web","attributes":{}},"events":[],"links":[],"status":{"code":"1"}} -{"type":"effect-span","name":"http.server POST","traceId":"e0f061fe6f936d457afc5f9cc15aae2d","spanId":"a4c0b88496aa66ce","sampled":true,"kind":"server","startTimeUnixNano":"1779352821307683000","endTimeUnixNano":"1779352821309195042","durationMs":1.512042,"attributes":{"http.route":"/api/observability/v1/traces","http.request.method":"POST","url.full":"http://127.0.0.1:14124/api/observability/v1/traces","url.path":"/api/observability/v1/traces","url.scheme":"http","user_agent.original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"close","http.request.header.content-length":"690","http.request.header.sec-ch-ua-platform":"\"macOS\"","http.request.header.user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.sec-ch-ua":"\"Not-A.Brand\";v=\"24\", \"Chromium\";v=\"146\"","http.request.header.content-type":"application/json","http.request.header.sec-ch-ua-mobile":"?0","http.request.header.accept":"*/*","http.request.header.origin":"http://127.0.0.1:6084","http.request.header.sec-fetch-site":"same-origin","http.request.header.sec-fetch-mode":"cors","http.request.header.sec-fetch-dest":"empty","http.request.header.referer":"http://127.0.0.1:6084/","http.request.header.accept-encoding":"gzip, deflate, br, zstd","http.request.header.accept-language":"en-GB","http.request.header.cookie":"","http.response.status_code":204},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"05a7558147c35610","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352822809247625","endTimeUnixNano":"1779352822867511167","durationMs":58.263542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"cc3c2701d622b019","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352827869158542","endTimeUnixNano":"1779352827926775875","durationMs":57.617333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"3282f8129f6b92d7","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"client","startTimeUnixNano":"1779352829166009375","endTimeUnixNano":"1779352829166095959","durationMs":0.086584,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n session_id AS \"sessionId\",\n subject AS \"subject\",\n role AS \"role\",\n method AS \"method\",\n client_label AS \"clientLabel\",\n client_ip_address AS \"clientIpAddress\",\n client_user_agent AS \"clientUserAgent\",\n client_device_type AS \"clientDeviceType\",\n client_os AS \"clientOs\",\n client_browser AS \"clientBrowser\",\n issued_at AS \"issuedAt\",\n expires_at AS \"expiresAt\",\n last_connected_at AS \"lastConnectedAt\",\n revoked_at AS \"revokedAt\"\n FROM auth_sessions\n WHERE session_id = ?\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.orchestration.subscribeShell","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"2ea2cdc31ee0588a","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570662252292","endTimeUnixNano":"1779352829166525292","durationMs":258504.273,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"orchestration.subscribeShell","rpc.aggregate":"orchestration"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.subscribeTerminalEvents","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"067602df07bdce5b","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570667016834","endTimeUnixNano":"1779352829166813959","durationMs":258499.797125,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"subscribeTerminalEvents","rpc.aggregate":"terminal"},"events":[],"links":[],"exit":{"_tag":"Interrupted","cause":"InterruptError: All fibers interrupted without error {\n [cause]: InterruptCause: The fiber was interrupted by:\n at fiber (#1548)\n}"}} -{"type":"effect-span","name":"ws.rpc.subscribeServerLifecycle","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"a7faa6b3be106e26","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570680813667","endTimeUnixNano":"1779352829167104667","durationMs":258486.291,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"subscribeServerLifecycle","rpc.aggregate":"server"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.subscribeServerConfig","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"e37a73ca0ab12f2b","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"internal","startTimeUnixNano":"1779352570681685667","endTimeUnixNano":"1779352829167466334","durationMs":258485.780667,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"subscribeServerConfig","rpc.aggregate":"server"},"events":[],"links":[],"exit":{"_tag":"Interrupted","cause":"InterruptError: All fibers interrupted without error {\n [cause]: InterruptCause: The fiber was interrupted by:\n at fiber (#1548)\n}"}} -{"type":"effect-span","name":"VcsStatusBroadcaster.releaseRemotePoller","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"e8542f3e037b9039","parentSpanId":"d7ffc9a51d150c55","sampled":true,"kind":"internal","startTimeUnixNano":"1779352829167545667","endTimeUnixNano":"1779352829167592209","durationMs":0.046542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"ws.rpc.subscribeVcsStatus","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"d7ffc9a51d150c55","parentSpanId":"32a5dc8ce34ec628","sampled":true,"kind":"internal","startTimeUnixNano":"1779352820240218292","endTimeUnixNano":"1779352829167642542","durationMs":8927.42425,"attributes":{"rpc.transport":"websocket","rpc.system":"effect-rpc","rpc.method":"subscribeVcsStatus","rpc.aggregate":"vcs"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"http.server GET","traceId":"f0814d439c8640fb198de1691a0bd403","spanId":"32a5dc8ce34ec628","sampled":true,"kind":"server","startTimeUnixNano":"1779352570653554125","endTimeUnixNano":"1779352829166304042","durationMs":258512.749917,"attributes":{"http.route":"/ws","http.request.method":"GET","url.full":"http://127.0.0.1:14124/ws","url.path":"/ws","url.scheme":"http","user_agent.original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.host":"127.0.0.1:14124","http.request.header.connection":"Upgrade","http.request.header.pragma":"no-cache","http.request.header.cache-control":"no-cache","http.request.header.user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) T3Code(Dev)/41.5.0 Chrome/146.0.7680.216 Electron/41.5.0 Safari/537.36","http.request.header.upgrade":"websocket","http.request.header.origin":"http://127.0.0.1:6084","http.request.header.sec-websocket-version":"13","http.request.header.accept-encoding":"gzip, deflate, br, zstd","http.request.header.accept-language":"en-GB","http.request.header.cookie":"","http.request.header.sec-websocket-key":"JeNW9ZRRI/ctkF9GSih0xw==","http.request.header.sec-websocket-extensions":"permessage-deflate; client_max_window_bits","http.response.status_code":204},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"007c65d80dd7dac6","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352832928379542","endTimeUnixNano":"1779352832953731625","durationMs":25.352083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"90ad8ca175eed8ea","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352837955175542","endTimeUnixNano":"1779352838017048042","durationMs":61.8725,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"cff14b42f0741cb2","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352843019061042","endTimeUnixNano":"1779352843044437417","durationMs":25.376375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"9b47125ed50a96ab","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352848045858625","endTimeUnixNano":"1779352848106063084","durationMs":60.204459,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"17e2bd1754a49ceb","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352853108041334","endTimeUnixNano":"1779352853136565542","durationMs":28.524208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"65b99a7e3926ae8e","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352858137628167","endTimeUnixNano":"1779352858161975667","durationMs":24.3475,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"cce5c36539f22574","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352863162863834","endTimeUnixNano":"1779352863187819375","durationMs":24.955541,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"d7773be845f56a00","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352868188369709","endTimeUnixNano":"1779352868246673709","durationMs":58.304,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"cf8f888ffc3a2fd7","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352873246873042","endTimeUnixNano":"1779352873305708584","durationMs":58.835542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"9656fff75019f0ef","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352878307144584","endTimeUnixNano":"1779352878364225875","durationMs":57.081291,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"c90ba646c47d38c0","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352883365400625","endTimeUnixNano":"1779352883420680875","durationMs":55.28025,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"dd39d15477ba4f9a","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352888422520250","endTimeUnixNano":"1779352888480260667","durationMs":57.740417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"a577b863aa8c3f93","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352893482648625","endTimeUnixNano":"1779352893539596875","durationMs":56.94825,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"d6b7ddf81493996b","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352898541647709","endTimeUnixNano":"1779352898598342709","durationMs":56.695,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"4853e43a5751474b","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352903599989209","endTimeUnixNano":"1779352903657326917","durationMs":57.337708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"f4b6dd07856ac995","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352908659787875","endTimeUnixNano":"1779352908717842167","durationMs":58.054292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"f6b0cca91ab284e7","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352913720579584","endTimeUnixNano":"1779352913779076959","durationMs":58.497375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"fb2f95beba4e9016","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352918781026750","endTimeUnixNano":"1779352918840133792","durationMs":59.107042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeClaudeEnvironment","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"18a46cb9121d2439","parentSpanId":"245da78bf7d908a1","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920247948750","endTimeUnixNano":"1779352920247983542","durationMs":0.034792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runClaudeCommand","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"245da78bf7d908a1","parentSpanId":"ae924c39ca6b2ec7","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920247909792","endTimeUnixNano":"1779352920251885584","durationMs":3.975792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"PlatformError: NotFound: ChildProcess.spawn (claude --version)\n at Module.systemError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/PlatformError.js:59:39)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/internal/utils.js:28:24\n at toPlatformError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:25:54)\n at ChildProcess. (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:230:26)\n at ChildProcess.emit (node:events:509:28)\n at ChildProcess._handle.onexit (node:internal/child_process:293:12)\n at onErrorNT (node:internal/child_process:508:16)\n at processTicksAndRejections (node:internal/process/task_queues:90:21)\n at runNextTicks (node:internal/process/task_queues:69:3)\n at listOnTimeout (node:internal/timers:567:9)\n at runClaudeCommand (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:27894:30)\n at runClaudeCommand (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:27870:33)\n at checkClaudeProviderStatus (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30400:25)\n at checkClaudeProviderStatus (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:27878:42)\n at applySnapshot (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30277:83)\n at applySnapshot (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30257:35)\n at refreshSnapshot (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30282:102)\n at refreshSnapshot (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30278:33)\n at makeManagedServerProvider (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30401:27)\n at makeManagedServerProvider (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30222:42) {\n [cause]: Error: spawn claude ENOENT\n at ChildProcess._handle.onexit (node:internal/child_process:287:19)\n at onErrorNT (node:internal/child_process:508:16)\n at processTicksAndRejections (node:internal/process/task_queues:90:21)\n at runNextTicks (node:internal/process/task_queues:69:3)\n at listOnTimeout (node:internal/timers:567:9)\n at process.processTimers (node:internal/timers:541:7)\n}"}} -{"type":"effect-span","name":"checkClaudeProviderStatus","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"ae924c39ca6b2ec7","parentSpanId":"3ae1e099c1d3c80b","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920247697000","endTimeUnixNano":"1779352920252518417","durationMs":4.821417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"aa630929672f9778ed5ecd8786ca417e","spanId":"4b55bd0c7adcc46a","parentSpanId":"20c7b98b3329314b","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920252750167","endTimeUnixNano":"1779352920252772250","durationMs":0.022083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"aa630929672f9778ed5ecd8786ca417e","spanId":"e154103fd18eacc0","parentSpanId":"20c7b98b3329314b","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920253213459","endTimeUnixNano":"1779352920253238667","durationMs":0.025208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"65138022ad8741b7","parentSpanId":"3ae1e099c1d3c80b","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920253414584","endTimeUnixNano":"1779352920253499000","durationMs":0.084416,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"3ae1e099c1d3c80b","parentSpanId":"2a6ea18f6642fb48","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920247644959","endTimeUnixNano":"1779352920253511417","durationMs":5.866458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"2a6ea18f6642fb48","parentSpanId":"d8882d30663dbbb0","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920247518875","endTimeUnixNano":"1779352920253532500","durationMs":6.013625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"checkCursorProviderStatus","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"1146bb4620d37385","parentSpanId":"54f56092e68c3bff","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920253665250","endTimeUnixNano":"1779352920253720125","durationMs":0.054875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"150381372f9196428e56ee72d95c45b4","spanId":"8249926df5ab403d","parentSpanId":"75ead8e75375a362","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920253812542","endTimeUnixNano":"1779352920253825459","durationMs":0.012917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"150381372f9196428e56ee72d95c45b4","spanId":"9943b1b6433e531e","parentSpanId":"75ead8e75375a362","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920253888334","endTimeUnixNano":"1779352920253913792","durationMs":0.025458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"3819e85beaf58e23","parentSpanId":"54f56092e68c3bff","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920253980709","endTimeUnixNano":"1779352920254042750","durationMs":0.062041,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"54f56092e68c3bff","parentSpanId":"d442045a6e452a9a","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920253642709","endTimeUnixNano":"1779352920254052084","durationMs":0.409375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"d442045a6e452a9a","parentSpanId":"f4270506fde844da","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920253611167","endTimeUnixNano":"1779352920254060792","durationMs":0.449625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"6b4e26d65d7c9138","parentSpanId":"65138022ad8741b7","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920254956667","endTimeUnixNano":"1779352920254984792","durationMs":0.028125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"ca7fa95d48b4a07b","parentSpanId":"65138022ad8741b7","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920255016084","endTimeUnixNano":"1779352920255076750","durationMs":0.060666,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"2d849dea26f84e19","parentSpanId":"3819e85beaf58e23","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920255118292","endTimeUnixNano":"1779352920255128459","durationMs":0.010167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"1319f8853e16a1cd","parentSpanId":"3819e85beaf58e23","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920255153834","endTimeUnixNano":"1779352920255191917","durationMs":0.038083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"aa630929672f9778ed5ecd8786ca417e","spanId":"20c7b98b3329314b","parentSpanId":"39ee4c2f714d63b4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920252696625","endTimeUnixNano":"1779352920257057625","durationMs":4.361,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"aa630929672f9778ed5ecd8786ca417e","spanId":"39ee4c2f714d63b4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920252653709","endTimeUnixNano":"1779352920257078292","durationMs":4.424583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"7054f8ead72c10d08aebb835c63e58ac","spanId":"9c53096128c6646d","parentSpanId":"d79d3ae372542e71","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920257176084","endTimeUnixNano":"1779352920257190709","durationMs":0.014625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"7054f8ead72c10d08aebb835c63e58ac","spanId":"d9e30c2a713c2b24","parentSpanId":"d79d3ae372542e71","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920257266625","endTimeUnixNano":"1779352920257281292","durationMs":0.014667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"150381372f9196428e56ee72d95c45b4","spanId":"75ead8e75375a362","parentSpanId":"c010ca3e623496d0","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920253790125","endTimeUnixNano":"1779352920257384500","durationMs":3.594375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"150381372f9196428e56ee72d95c45b4","spanId":"c010ca3e623496d0","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920253767250","endTimeUnixNano":"1779352920257396125","durationMs":3.628875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"6adc86eef0f47c7408076d13e4f603dc","spanId":"a31b2684cbf575db","parentSpanId":"5267927a4d1e728f","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920257456417","endTimeUnixNano":"1779352920257467584","durationMs":0.011167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"6adc86eef0f47c7408076d13e4f603dc","spanId":"418334c7d659f638","parentSpanId":"5267927a4d1e728f","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920257513375","endTimeUnixNano":"1779352920257525292","durationMs":0.011917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"6adc86eef0f47c7408076d13e4f603dc","spanId":"5267927a4d1e728f","parentSpanId":"efab064af38ce525","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920257437084","endTimeUnixNano":"1779352920258768709","durationMs":1.331625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"6adc86eef0f47c7408076d13e4f603dc","spanId":"efab064af38ce525","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920257419500","endTimeUnixNano":"1779352920258786417","durationMs":1.366917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"7054f8ead72c10d08aebb835c63e58ac","spanId":"d79d3ae372542e71","parentSpanId":"58a7eb0d4ac9e614","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920257149125","endTimeUnixNano":"1779352920258823584","durationMs":1.674459,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"7054f8ead72c10d08aebb835c63e58ac","spanId":"58a7eb0d4ac9e614","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920257126709","endTimeUnixNano":"1779352920258831792","durationMs":1.705083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeCodexAppServerPatchedProtocol","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"cce010fec54ed7bb","parentSpanId":"df434128536dfad7","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920514428209","endTimeUnixNano":"1779352920514566917","durationMs":0.138708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"effect-codex-app-server/CodexAppServerClient.make","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"df434128536dfad7","parentSpanId":"38507cbaefccdfb6","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920514364292","endTimeUnixNano":"1779352920514634542","durationMs":0.27025,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"requestAllCodexModels","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"c82f1055f1e0f3f4","parentSpanId":"38507cbaefccdfb6","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920554828834","endTimeUnixNano":"1779352920555995167","durationMs":1.166333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"probeCodexAppServerProvider","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"38507cbaefccdfb6","parentSpanId":"809ce5362406894e","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920511484375","endTimeUnixNano":"1779352920587919584","durationMs":76.435209,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"checkCodexProviderStatus","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"809ce5362406894e","parentSpanId":"58c8fc7e4f667140","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920511184084","endTimeUnixNano":"1779352920589320209","durationMs":78.136125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"fb05e51574cc7c857672f3813bb3127c","spanId":"584b8074ff8c2237","parentSpanId":"8b3acf09a95c174a","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920589393375","endTimeUnixNano":"1779352920589399250","durationMs":0.005875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"fb05e51574cc7c857672f3813bb3127c","spanId":"b140793028dac327","parentSpanId":"8b3acf09a95c174a","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920589513875","endTimeUnixNano":"1779352920589522584","durationMs":0.008709,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"3d09f1060a83bbc7","parentSpanId":"58c8fc7e4f667140","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920589599834","endTimeUnixNano":"1779352920589622417","durationMs":0.022583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"58c8fc7e4f667140","parentSpanId":"6b07ef188e93aff7","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920511135125","endTimeUnixNano":"1779352920589626000","durationMs":78.490875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"6b07ef188e93aff7","parentSpanId":"5bc4cdb3beb605ab","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920511012459","endTimeUnixNano":"1779352920589630084","durationMs":78.617625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveLatestProviderVersion","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"900f15544f25ccc0","parentSpanId":"6619c5e1c120dca5","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920589650542","endTimeUnixNano":"1779352920589659042","durationMs":0.0085,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"6619c5e1c120dca5","parentSpanId":"3d09f1060a83bbc7","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920589642000","endTimeUnixNano":"1779352920589679417","durationMs":0.037417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"3e76e77988f11a25","parentSpanId":"3d09f1060a83bbc7","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920589685292","endTimeUnixNano":"1779352920589702000","durationMs":0.016708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"fb05e51574cc7c857672f3813bb3127c","spanId":"8b3acf09a95c174a","parentSpanId":"41b139784fe1b961","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920589378959","endTimeUnixNano":"1779352920590164709","durationMs":0.78575,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"fb05e51574cc7c857672f3813bb3127c","spanId":"41b139784fe1b961","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920589365167","endTimeUnixNano":"1779352920590167959","durationMs":0.802792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"58a8c02e4a3b91c7c1584987f4874137","spanId":"6e05ef07cf741eec","parentSpanId":"87e8030473aff39f","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920590191167","endTimeUnixNano":"1779352920590195292","durationMs":0.004125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"58a8c02e4a3b91c7c1584987f4874137","spanId":"88b3cb366694c117","parentSpanId":"87e8030473aff39f","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920590217042","endTimeUnixNano":"1779352920590221209","durationMs":0.004167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"58a8c02e4a3b91c7c1584987f4874137","spanId":"87e8030473aff39f","parentSpanId":"44a6e3f5d8f17b8f","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920590184000","endTimeUnixNano":"1779352920590644084","durationMs":0.460084,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"58a8c02e4a3b91c7c1584987f4874137","spanId":"44a6e3f5d8f17b8f","sampled":true,"kind":"internal","startTimeUnixNano":"1779352920590177875","endTimeUnixNano":"1779352920590651125","durationMs":0.47325,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"c5bece9dd164bcf4","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352923842530875","endTimeUnixNano":"1779352923905610084","durationMs":63.079209,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"9c222a79013464bbed30efe9f66a4107","spanId":"e5eaec6d10d4e218","parentSpanId":"bdaa4ceb2b2577ba","sampled":true,"kind":"client","startTimeUnixNano":"1779352924779268084","endTimeUnixNano":"1779352924779880167","durationMs":0.612083,"attributes":{"server.mode":"desktop","server.port":14124,"server.host":"127.0.0.1","startup.phase":"reactors.start","db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n thread_id AS \"threadId\",\n provider_name AS \"providerName\",\n provider_instance_id AS \"providerInstanceId\",\n adapter_key AS \"adapterKey\",\n runtime_mode AS \"runtimeMode\",\n status,\n last_seen_at AS \"lastSeenAt\",\n resume_cursor_json AS \"resumeCursor\",\n runtime_payload_json AS \"runtimePayload\"\n FROM provider_session_runtime\n ORDER BY last_seen_at ASC, thread_id ASC\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"opencode.app.agents","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"1651820e887648ee","parentSpanId":"afc3d295cf51267e","sampled":true,"kind":"internal","startTimeUnixNano":"1779352927276559042","endTimeUnixNano":"1779352927482030417","durationMs":205.471375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"opencode.provider.list","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"6451845a7dfa8089","parentSpanId":"afc3d295cf51267e","sampled":true,"kind":"internal","startTimeUnixNano":"1779352927276497875","endTimeUnixNano":"1779352927594835000","durationMs":318.337125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"checkOpenCodeProviderStatus","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"afc3d295cf51267e","parentSpanId":"e013f02b393f7103","sampled":true,"kind":"internal","startTimeUnixNano":"1779352926466913167","endTimeUnixNano":"1779352928596785084","durationMs":2129.871917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"ffd9c26fd77f984f5e4b666f1ed4e264","spanId":"1ed3551fc54cecd5","parentSpanId":"b476d586ad729b8e","sampled":true,"kind":"internal","startTimeUnixNano":"1779352928597130417","endTimeUnixNano":"1779352928597153667","durationMs":0.02325,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"ffd9c26fd77f984f5e4b666f1ed4e264","spanId":"0b4823a7874e2fbe","parentSpanId":"b476d586ad729b8e","sampled":true,"kind":"internal","startTimeUnixNano":"1779352928598959959","endTimeUnixNano":"1779352928599000917","durationMs":0.040958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"081646f3674dd0d8","parentSpanId":"e013f02b393f7103","sampled":true,"kind":"internal","startTimeUnixNano":"1779352928599647042","endTimeUnixNano":"1779352928599755792","durationMs":0.10875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"e013f02b393f7103","parentSpanId":"17e36bbde602d892","sampled":true,"kind":"internal","startTimeUnixNano":"1779352926466837375","endTimeUnixNano":"1779352928599769084","durationMs":2132.931709,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"17e36bbde602d892","parentSpanId":"2f989ef1cbf60c79","sampled":true,"kind":"internal","startTimeUnixNano":"1779352926466667542","endTimeUnixNano":"1779352928599786250","durationMs":2133.118708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveLatestProviderVersion","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"3a8724368233a10c","parentSpanId":"1c45eafaa3dc0a5e","sampled":true,"kind":"internal","startTimeUnixNano":"1779352928599863792","endTimeUnixNano":"1779352928599900167","durationMs":0.036375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"1c45eafaa3dc0a5e","parentSpanId":"081646f3674dd0d8","sampled":true,"kind":"internal","startTimeUnixNano":"1779352928599841209","endTimeUnixNano":"1779352928599969209","durationMs":0.128,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"17361cdf0ffb50d9","parentSpanId":"081646f3674dd0d8","sampled":true,"kind":"internal","startTimeUnixNano":"1779352928599987792","endTimeUnixNano":"1779352928600052667","durationMs":0.064875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"ffd9c26fd77f984f5e4b666f1ed4e264","spanId":"b476d586ad729b8e","parentSpanId":"e30523eeea75e6f4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352928597063875","endTimeUnixNano":"1779352928602085625","durationMs":5.02175,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"ffd9c26fd77f984f5e4b666f1ed4e264","spanId":"e30523eeea75e6f4","sampled":true,"kind":"internal","startTimeUnixNano":"1779352928597007625","endTimeUnixNano":"1779352928602111750","durationMs":5.104125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"cc6a2a51647b7dc3c5006034aec8ad09","spanId":"ee85359d13ad109e","parentSpanId":"697a722f1d95b5db","sampled":true,"kind":"internal","startTimeUnixNano":"1779352928602231209","endTimeUnixNano":"1779352928602247792","durationMs":0.016583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"cc6a2a51647b7dc3c5006034aec8ad09","spanId":"3a0f68a88b37bd0f","parentSpanId":"697a722f1d95b5db","sampled":true,"kind":"internal","startTimeUnixNano":"1779352928602400084","endTimeUnixNano":"1779352928602414250","durationMs":0.014166,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"cc6a2a51647b7dc3c5006034aec8ad09","spanId":"697a722f1d95b5db","parentSpanId":"23130c7d3fa7d80b","sampled":true,"kind":"internal","startTimeUnixNano":"1779352928602195584","endTimeUnixNano":"1779352928604730459","durationMs":2.534875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"cc6a2a51647b7dc3c5006034aec8ad09","spanId":"23130c7d3fa7d80b","sampled":true,"kind":"internal","startTimeUnixNano":"1779352928602166375","endTimeUnixNano":"1779352928604752375","durationMs":2.586,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"9cebdf10fd1344e0","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352928907593584","endTimeUnixNano":"1779352928964196500","durationMs":56.602916,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"4027df7274546772","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352933965774834","endTimeUnixNano":"1779352933989341834","durationMs":23.567,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"3ddaf28ccb90b7eb","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352938991521042","endTimeUnixNano":"1779352939051967542","durationMs":60.4465,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"e6c9a04aa4744f82","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352944053454584","endTimeUnixNano":"1779352944112372125","durationMs":58.917541,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"2e9b36ba157fcb0c","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352949112876500","endTimeUnixNano":"1779352949171413834","durationMs":58.537334,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"8cc63bf072c4fbec","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352954173605500","endTimeUnixNano":"1779352954231991542","durationMs":58.386042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"84832e6674b8c93d","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352959234082875","endTimeUnixNano":"1779352959291473417","durationMs":57.390542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"c68caa94698fc581","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352964292615792","endTimeUnixNano":"1779352964349105709","durationMs":56.489917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"5b1d3049d04a6200","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352969351607625","endTimeUnixNano":"1779352969408799459","durationMs":57.191834,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"55eed5ec90a13545","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352974409744500","endTimeUnixNano":"1779352974467342834","durationMs":57.598334,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"8018f8fb21f75c8c","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352979468935667","endTimeUnixNano":"1779352979527265667","durationMs":58.33,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"d0f91aec784b72e6","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352984528108625","endTimeUnixNano":"1779352984584393209","durationMs":56.284584,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"c33baec44e45c28a","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352989585619417","endTimeUnixNano":"1779352989642292667","durationMs":56.67325,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"1f7c019326fe9d6d","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352994644295834","endTimeUnixNano":"1779352994703121375","durationMs":58.825541,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"ee9ccc4768077f30","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779352999705045042","endTimeUnixNano":"1779352999765328334","durationMs":60.283292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"7134374a66102047","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353004766287292","endTimeUnixNano":"1779353004824380292","durationMs":58.093,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"630f7f062f28bbec","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353009826501125","endTimeUnixNano":"1779353009886701334","durationMs":60.200209,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"9f0d8b773b49746e","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353014887701584","endTimeUnixNano":"1779353014947504334","durationMs":59.80275,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"fefc5d6b2a4fa3dc","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353019949047375","endTimeUnixNano":"1779353020005549709","durationMs":56.502334,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"8c37e4c5f81bfbe8","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353025006905209","endTimeUnixNano":"1779353025064360584","durationMs":57.455375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"2d6b19d383146610","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353030066613667","endTimeUnixNano":"1779353030125544125","durationMs":58.930458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"07482f3bc4c39cd3","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353035127668000","endTimeUnixNano":"1779353035187492167","durationMs":59.824167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"19e106dfb09ef6a6","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353040189236417","endTimeUnixNano":"1779353040247204042","durationMs":57.967625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"39c54a996f4c341e","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353045248747584","endTimeUnixNano":"1779353045308182167","durationMs":59.434583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"94b997cc2bdc16b3","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353050309444417","endTimeUnixNano":"1779353050366960625","durationMs":57.516208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"bc1671dca0b363d9","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353055369546292","endTimeUnixNano":"1779353055428044167","durationMs":58.497875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"b6999de7c4b8e4c9","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353060430208750","endTimeUnixNano":"1779353060487258875","durationMs":57.050125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"0faf692a316f2185","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353065489160917","endTimeUnixNano":"1779353065548632834","durationMs":59.471917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"09f0b3f3a7dc84e0","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353070550405000","endTimeUnixNano":"1779353070607989334","durationMs":57.584334,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"20151c0028499f05","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353075610655667","endTimeUnixNano":"1779353075668684417","durationMs":58.02875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"2483ce0ed8ef1604","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353080669610542","endTimeUnixNano":"1779353080731523792","durationMs":61.91325,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"b59e909a080ce120","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353085733475375","endTimeUnixNano":"1779353085791392459","durationMs":57.917084,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"33d09d72a9f98d66","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353090792913959","endTimeUnixNano":"1779353090850869667","durationMs":57.955708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"99346be97a67cf9e","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353095852675334","endTimeUnixNano":"1779353095912138709","durationMs":59.463375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"387d97552bf575db","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353100913963292","endTimeUnixNano":"1779353100971290417","durationMs":57.327125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"eebb52c7fd246e21","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353105973586709","endTimeUnixNano":"1779353106030344750","durationMs":56.758041,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"383ac5f9345e516e","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353111032493167","endTimeUnixNano":"1779353111093550042","durationMs":61.056875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"9dff1d7b00d5cc58","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353116095239209","endTimeUnixNano":"1779353116155047875","durationMs":59.808666,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"39ec99991cd78c43","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353121157370125","endTimeUnixNano":"1779353121185297875","durationMs":27.92775,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"ccc7dafdb7f6a17c","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353126186831875","endTimeUnixNano":"1779353126245613959","durationMs":58.782084,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"087c8602073e1c29","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353131247753084","endTimeUnixNano":"1779353131306761625","durationMs":59.008541,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"47949afb4fca98b5","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353136308078125","endTimeUnixNano":"1779353136365768500","durationMs":57.690375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"0fdb909a95831b57","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353141367810417","endTimeUnixNano":"1779353141427738834","durationMs":59.928417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"30ee75f9c839d556","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353146429346375","endTimeUnixNano":"1779353146489062125","durationMs":59.71575,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"9bce709da8ce0246","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353151491930709","endTimeUnixNano":"1779353151551612959","durationMs":59.68225,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"490e974d27a48eb6","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353156553374042","endTimeUnixNano":"1779353156613338250","durationMs":59.964208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"d8ba8490b26087ef","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353161614931542","endTimeUnixNano":"1779353161672829125","durationMs":57.897583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"e74906723add610a","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353166675248459","endTimeUnixNano":"1779353166730933500","durationMs":55.685041,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"9d5ca1bf959cffc2","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353171733428500","endTimeUnixNano":"1779353171793381750","durationMs":59.95325,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"6a86753c72b01199","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353176796318334","endTimeUnixNano":"1779353176852792334","durationMs":56.474,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"5aaa4d8e09d351cd","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353181854626834","endTimeUnixNano":"1779353181914747292","durationMs":60.120458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"ef80ff19cfbcc785","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353186917424375","endTimeUnixNano":"1779353186974658459","durationMs":57.234084,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"769bf9dfba7b00af","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353191976233917","endTimeUnixNano":"1779353192034124334","durationMs":57.890417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"03d5f9256517c5c9","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353197037596417","endTimeUnixNano":"1779353197096526500","durationMs":58.930083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"ef76aa06cb5d114b","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353202099192625","endTimeUnixNano":"1779353202156844209","durationMs":57.651584,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"f757a80adada9b8c","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353207159091834","endTimeUnixNano":"1779353207215898042","durationMs":56.806208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"036bd202873d6b13","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353212218530625","endTimeUnixNano":"1779353212275559375","durationMs":57.02875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"09de5855ad08714b","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353217276109667","endTimeUnixNano":"1779353217332104750","durationMs":55.995083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeClaudeEnvironment","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"aa3dd38ddc9b4d5c","parentSpanId":"01abb76f51978580","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220257232625","endTimeUnixNano":"1779353220257274167","durationMs":0.041542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runClaudeCommand","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"01abb76f51978580","parentSpanId":"2b427cba8de52d4f","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220257188584","endTimeUnixNano":"1779353220262277792","durationMs":5.089208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"PlatformError: NotFound: ChildProcess.spawn (claude --version)\n at Module.systemError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/PlatformError.js:59:39)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/internal/utils.js:28:24\n at toPlatformError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:25:54)\n at ChildProcess. (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:230:26)\n at ChildProcess.emit (node:events:509:28)\n at ChildProcess._handle.onexit (node:internal/child_process:293:12)\n at onErrorNT (node:internal/child_process:508:16)\n at processTicksAndRejections (node:internal/process/task_queues:90:21)\n at runNextTicks (node:internal/process/task_queues:69:3)\n at listOnTimeout (node:internal/timers:567:9)\n at runClaudeCommand (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:27894:30)\n at runClaudeCommand (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:27870:33)\n at checkClaudeProviderStatus (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30400:25)\n at checkClaudeProviderStatus (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:27878:42)\n at applySnapshot (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30277:83)\n at applySnapshot (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30257:35)\n at refreshSnapshot (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30282:102)\n at refreshSnapshot (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30278:33)\n at makeManagedServerProvider (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30401:27)\n at makeManagedServerProvider (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30222:42) {\n [cause]: Error: spawn claude ENOENT\n at ChildProcess._handle.onexit (node:internal/child_process:287:19)\n at onErrorNT (node:internal/child_process:508:16)\n at processTicksAndRejections (node:internal/process/task_queues:90:21)\n at runNextTicks (node:internal/process/task_queues:69:3)\n at listOnTimeout (node:internal/timers:567:9)\n at process.processTimers (node:internal/timers:541:7)\n}"}} -{"type":"effect-span","name":"checkClaudeProviderStatus","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"2b427cba8de52d4f","parentSpanId":"a3e792a603b8440d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220256934500","endTimeUnixNano":"1779353220263004959","durationMs":6.070459,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"a0401c35ae445400b45889209371542a","spanId":"7acf27f64c894ba8","parentSpanId":"7668e2041493392e","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220263257334","endTimeUnixNano":"1779353220263280584","durationMs":0.02325,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"a0401c35ae445400b45889209371542a","spanId":"ce0781c87c091ad3","parentSpanId":"7668e2041493392e","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220263714500","endTimeUnixNano":"1779353220263745750","durationMs":0.03125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"48432e4f32d8256e","parentSpanId":"a3e792a603b8440d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220263939625","endTimeUnixNano":"1779353220264033792","durationMs":0.094167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"a3e792a603b8440d","parentSpanId":"722d82e004fc8ea2","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220256872125","endTimeUnixNano":"1779353220264047667","durationMs":7.175542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"722d82e004fc8ea2","parentSpanId":"d8882d30663dbbb0","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220256731042","endTimeUnixNano":"1779353220264067084","durationMs":7.336042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"checkCursorProviderStatus","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"7e2b0eee3e7c7eda","parentSpanId":"05d463e00a2d4431","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220264206750","endTimeUnixNano":"1779353220264269000","durationMs":0.06225,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"24354f52b1b479dd091452818cd5e724","spanId":"fcb580b814c4c16b","parentSpanId":"5bc42bf8e094509a","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220264356917","endTimeUnixNano":"1779353220264370875","durationMs":0.013958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"24354f52b1b479dd091452818cd5e724","spanId":"fa83c1a20bd7711f","parentSpanId":"5bc42bf8e094509a","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220264431334","endTimeUnixNano":"1779353220264446084","durationMs":0.01475,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"51831516bc62663e","parentSpanId":"05d463e00a2d4431","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220264515917","endTimeUnixNano":"1779353220264598500","durationMs":0.082583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"05d463e00a2d4431","parentSpanId":"cc59d23124dee853","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220264179334","endTimeUnixNano":"1779353220264609417","durationMs":0.430083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"cc59d23124dee853","parentSpanId":"f4270506fde844da","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220264144834","endTimeUnixNano":"1779353220264618375","durationMs":0.473541,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"8318d7dc24e14aae","parentSpanId":"48432e4f32d8256e","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220264844542","endTimeUnixNano":"1779353220264863417","durationMs":0.018875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"4c6ae414449f18f2","parentSpanId":"48432e4f32d8256e","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220264885375","endTimeUnixNano":"1779353220264929000","durationMs":0.043625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"43d098452cbd08d5","parentSpanId":"51831516bc62663e","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220264962084","endTimeUnixNano":"1779353220264971834","durationMs":0.00975,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"3f0410966f393cf4","parentSpanId":"51831516bc62663e","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220264995542","endTimeUnixNano":"1779353220265029167","durationMs":0.033625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"a0401c35ae445400b45889209371542a","spanId":"7668e2041493392e","parentSpanId":"cae0ea120477e383","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220263196459","endTimeUnixNano":"1779353220266885292","durationMs":3.688833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"a0401c35ae445400b45889209371542a","spanId":"cae0ea120477e383","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220263149459","endTimeUnixNano":"1779353220266907792","durationMs":3.758333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"c6861b9a7b0c992cfb277014b0d1d9bc","spanId":"6d54618217c1f3e2","parentSpanId":"d7aa27e403f60b46","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220267011375","endTimeUnixNano":"1779353220267025959","durationMs":0.014584,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"c6861b9a7b0c992cfb277014b0d1d9bc","spanId":"149e7b6c3fcd3f06","parentSpanId":"d7aa27e403f60b46","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220267118125","endTimeUnixNano":"1779353220267132542","durationMs":0.014417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"24354f52b1b479dd091452818cd5e724","spanId":"5bc42bf8e094509a","parentSpanId":"71dd2d0a0e06f327","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220264333042","endTimeUnixNano":"1779353220267851500","durationMs":3.518458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"24354f52b1b479dd091452818cd5e724","spanId":"71dd2d0a0e06f327","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220264312750","endTimeUnixNano":"1779353220267865209","durationMs":3.552459,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"d4a50ed851b7a476e1ebd44676a0aac6","spanId":"9f168d9a9b105cc3","parentSpanId":"99afa2ef9d35680a","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220267945792","endTimeUnixNano":"1779353220267960042","durationMs":0.01425,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"d4a50ed851b7a476e1ebd44676a0aac6","spanId":"1dccfc1772f919e8","parentSpanId":"99afa2ef9d35680a","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220268023542","endTimeUnixNano":"1779353220268037709","durationMs":0.014167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"d4a50ed851b7a476e1ebd44676a0aac6","spanId":"99afa2ef9d35680a","parentSpanId":"661e88f68ce97749","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220267921125","endTimeUnixNano":"1779353220269323000","durationMs":1.401875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"d4a50ed851b7a476e1ebd44676a0aac6","spanId":"661e88f68ce97749","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220267898000","endTimeUnixNano":"1779353220269344917","durationMs":1.446917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"c6861b9a7b0c992cfb277014b0d1d9bc","spanId":"d7aa27e403f60b46","parentSpanId":"d12e41d452af915a","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220266982709","endTimeUnixNano":"1779353220269385500","durationMs":2.402791,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"c6861b9a7b0c992cfb277014b0d1d9bc","spanId":"d12e41d452af915a","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220266958917","endTimeUnixNano":"1779353220269395250","durationMs":2.436333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeCodexAppServerPatchedProtocol","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"bde3ebd9adc869b2","parentSpanId":"1151fe378a414602","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220595230125","endTimeUnixNano":"1779353220595376000","durationMs":0.145875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"effect-codex-app-server/CodexAppServerClient.make","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"1151fe378a414602","parentSpanId":"02e546cf439e527e","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220595149625","endTimeUnixNano":"1779353220595440084","durationMs":0.290459,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"requestAllCodexModels","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"fc6749a7e2e3b247","parentSpanId":"02e546cf439e527e","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220633582917","endTimeUnixNano":"1779353221017891125","durationMs":384.308208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"probeCodexAppServerProvider","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"02e546cf439e527e","parentSpanId":"60521eadbe590099","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220592093500","endTimeUnixNano":"1779353221018036667","durationMs":425.943167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"checkCodexProviderStatus","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"60521eadbe590099","parentSpanId":"5fbed61523a74006","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220591826125","endTimeUnixNano":"1779353221023726250","durationMs":431.900125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"3d6fc231d551c380eb543ec0090c5056","spanId":"50ef26e8af2454bd","parentSpanId":"6d27995d2e42b0e1","sampled":true,"kind":"internal","startTimeUnixNano":"1779353221024002750","endTimeUnixNano":"1779353221024024334","durationMs":0.021584,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"3d6fc231d551c380eb543ec0090c5056","spanId":"53b02e40af5e6bcc","parentSpanId":"6d27995d2e42b0e1","sampled":true,"kind":"internal","startTimeUnixNano":"1779353221024353250","endTimeUnixNano":"1779353221024384334","durationMs":0.031084,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"d505fa9aff385d7c","parentSpanId":"5fbed61523a74006","sampled":true,"kind":"internal","startTimeUnixNano":"1779353221024658625","endTimeUnixNano":"1779353221024762334","durationMs":0.103709,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"5fbed61523a74006","parentSpanId":"e239758fecf6bec7","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220591774875","endTimeUnixNano":"1779353221024772459","durationMs":432.997584,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"e239758fecf6bec7","parentSpanId":"5bc4cdb3beb605ab","sampled":true,"kind":"internal","startTimeUnixNano":"1779353220591649167","endTimeUnixNano":"1779353221024786000","durationMs":433.136833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveLatestProviderVersion","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"145a5f0465fb8cef","parentSpanId":"6e9a1ccbd4e57750","sampled":true,"kind":"internal","startTimeUnixNano":"1779353221024858125","endTimeUnixNano":"1779353221024886209","durationMs":0.028084,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"6e9a1ccbd4e57750","parentSpanId":"d505fa9aff385d7c","sampled":true,"kind":"internal","startTimeUnixNano":"1779353221024832625","endTimeUnixNano":"1779353221024959375","durationMs":0.12675,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"fe2a3d477be1748c","parentSpanId":"d505fa9aff385d7c","sampled":true,"kind":"internal","startTimeUnixNano":"1779353221024978042","endTimeUnixNano":"1779353221025026334","durationMs":0.048292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"3d6fc231d551c380eb543ec0090c5056","spanId":"6d27995d2e42b0e1","parentSpanId":"1a7717fc124a0edf","sampled":true,"kind":"internal","startTimeUnixNano":"1779353221023959625","endTimeUnixNano":"1779353221026691375","durationMs":2.73175,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"3d6fc231d551c380eb543ec0090c5056","spanId":"1a7717fc124a0edf","sampled":true,"kind":"internal","startTimeUnixNano":"1779353221023911500","endTimeUnixNano":"1779353221026713334","durationMs":2.801834,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"a462d5ccae62460e70eba809bb7218ab","spanId":"882ca8cf0399dc5c","parentSpanId":"c0362542c6b8bede","sampled":true,"kind":"internal","startTimeUnixNano":"1779353221026837750","endTimeUnixNano":"1779353221026862084","durationMs":0.024334,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"a462d5ccae62460e70eba809bb7218ab","spanId":"aaa41054a077a050","parentSpanId":"c0362542c6b8bede","sampled":true,"kind":"internal","startTimeUnixNano":"1779353221026962125","endTimeUnixNano":"1779353221026980167","durationMs":0.018042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"a462d5ccae62460e70eba809bb7218ab","spanId":"c0362542c6b8bede","parentSpanId":"b569f8045448310e","sampled":true,"kind":"internal","startTimeUnixNano":"1779353221026797167","endTimeUnixNano":"1779353221028217209","durationMs":1.420042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"a462d5ccae62460e70eba809bb7218ab","spanId":"b569f8045448310e","sampled":true,"kind":"internal","startTimeUnixNano":"1779353221026769042","endTimeUnixNano":"1779353221028237292","durationMs":1.46825,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"fa80b445f3b98dd3","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353222334920792","endTimeUnixNano":"1779353222392138125","durationMs":57.217333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"9c222a79013464bbed30efe9f66a4107","spanId":"39ff3ab8ce5166f9","parentSpanId":"bdaa4ceb2b2577ba","sampled":true,"kind":"client","startTimeUnixNano":"1779353224781459542","endTimeUnixNano":"1779353224781748375","durationMs":0.288833,"attributes":{"server.mode":"desktop","server.port":14124,"server.host":"127.0.0.1","startup.phase":"reactors.start","db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n thread_id AS \"threadId\",\n provider_name AS \"providerName\",\n provider_instance_id AS \"providerInstanceId\",\n adapter_key AS \"adapterKey\",\n runtime_mode AS \"runtimeMode\",\n status,\n last_seen_at AS \"lastSeenAt\",\n resume_cursor_json AS \"resumeCursor\",\n runtime_payload_json AS \"runtimePayload\"\n FROM provider_session_runtime\n ORDER BY last_seen_at ASC, thread_id ASC\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"aeea7c60d21487c9","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353227395615000","endTimeUnixNano":"1779353227452670500","durationMs":57.0555,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"opencode.app.agents","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"e57460e8c077e10c","parentSpanId":"5233c92832765c86","sampled":true,"kind":"internal","startTimeUnixNano":"1779353229311241500","endTimeUnixNano":"1779353229523084917","durationMs":211.843417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"opencode.provider.list","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"9e1691196b5e612d","parentSpanId":"5233c92832765c86","sampled":true,"kind":"internal","startTimeUnixNano":"1779353229311168125","endTimeUnixNano":"1779353229635702959","durationMs":324.534834,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"checkOpenCodeProviderStatus","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"5233c92832765c86","parentSpanId":"cee5a012d3fba321","sampled":true,"kind":"internal","startTimeUnixNano":"1779353228602698792","endTimeUnixNano":"1779353230638229709","durationMs":2035.530917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"6a99b515296b8140f838432382c1f5e9","spanId":"05944a004d8be1be","parentSpanId":"3b327089127c7145","sampled":true,"kind":"internal","startTimeUnixNano":"1779353230638661250","endTimeUnixNano":"1779353230638697084","durationMs":0.035834,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"6a99b515296b8140f838432382c1f5e9","spanId":"288c21c6d5836f67","parentSpanId":"3b327089127c7145","sampled":true,"kind":"internal","startTimeUnixNano":"1779353230641402667","endTimeUnixNano":"1779353230641445167","durationMs":0.0425,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"695bf9ee36719884","parentSpanId":"cee5a012d3fba321","sampled":true,"kind":"internal","startTimeUnixNano":"1779353230642147625","endTimeUnixNano":"1779353230642276125","durationMs":0.1285,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"cee5a012d3fba321","parentSpanId":"23fa6d22d71811a3","sampled":true,"kind":"internal","startTimeUnixNano":"1779353228602636000","endTimeUnixNano":"1779353230642290417","durationMs":2039.654417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"23fa6d22d71811a3","parentSpanId":"2f989ef1cbf60c79","sampled":true,"kind":"internal","startTimeUnixNano":"1779353228602499250","endTimeUnixNano":"1779353230642307042","durationMs":2039.807792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveLatestProviderVersion","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"5bc91cc3c7472eaf","parentSpanId":"8ce6a2992eb099d8","sampled":true,"kind":"internal","startTimeUnixNano":"1779353230642392459","endTimeUnixNano":"1779353230642426542","durationMs":0.034083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"8ce6a2992eb099d8","parentSpanId":"695bf9ee36719884","sampled":true,"kind":"internal","startTimeUnixNano":"1779353230642368542","endTimeUnixNano":"1779353230642499292","durationMs":0.13075,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"df04bc81a81f7272","parentSpanId":"695bf9ee36719884","sampled":true,"kind":"internal","startTimeUnixNano":"1779353230642520709","endTimeUnixNano":"1779353230642596834","durationMs":0.076125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"6a99b515296b8140f838432382c1f5e9","spanId":"3b327089127c7145","parentSpanId":"1aae8503065d2a75","sampled":true,"kind":"internal","startTimeUnixNano":"1779353230638569584","endTimeUnixNano":"1779353230644560250","durationMs":5.990666,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"6a99b515296b8140f838432382c1f5e9","spanId":"1aae8503065d2a75","sampled":true,"kind":"internal","startTimeUnixNano":"1779353230638481750","endTimeUnixNano":"1779353230644585042","durationMs":6.103292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"b3948be296c12f7689b7766817c69085","spanId":"1e84a281762236d1","parentSpanId":"ec651966f464c5c5","sampled":true,"kind":"internal","startTimeUnixNano":"1779353230644742834","endTimeUnixNano":"1779353230644763125","durationMs":0.020291,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"b3948be296c12f7689b7766817c69085","spanId":"c24d94930baff7e9","parentSpanId":"ec651966f464c5c5","sampled":true,"kind":"internal","startTimeUnixNano":"1779353230644900417","endTimeUnixNano":"1779353230644922584","durationMs":0.022167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"b3948be296c12f7689b7766817c69085","spanId":"ec651966f464c5c5","parentSpanId":"015a800b67b40090","sampled":true,"kind":"internal","startTimeUnixNano":"1779353230644704375","endTimeUnixNano":"1779353230647016167","durationMs":2.311792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"b3948be296c12f7689b7766817c69085","spanId":"015a800b67b40090","sampled":true,"kind":"internal","startTimeUnixNano":"1779353230644663167","endTimeUnixNano":"1779353230647038709","durationMs":2.375542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"f8189929facff0f3","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353232455273875","endTimeUnixNano":"1779353232511814167","durationMs":56.540292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"0d7cecd79389bd6d","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353237513906417","endTimeUnixNano":"1779353237571124459","durationMs":57.218042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"d36f07a7952d8fb3","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353242574662542","endTimeUnixNano":"1779353242633543625","durationMs":58.881083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"6db9972b08e15406","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353247634912292","endTimeUnixNano":"1779353247693230209","durationMs":58.317917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"58424ae8781bb9fa","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353252696697292","endTimeUnixNano":"1779353252758151959","durationMs":61.454667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"0748d738c7c9f307","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353257759432000","endTimeUnixNano":"1779353257815591417","durationMs":56.159417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"18623d030ece4e9c","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353262818417750","endTimeUnixNano":"1779353262879219250","durationMs":60.8015,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"e1f726d8a0e572b2","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353267880893500","endTimeUnixNano":"1779353267937997500","durationMs":57.104,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"4303da6dcfa2e959","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353272939507834","endTimeUnixNano":"1779353272996821084","durationMs":57.31325,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"82027bbe8edd92b5","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353277999847042","endTimeUnixNano":"1779353278057168167","durationMs":57.321125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"4b2c6ad951a5cdf8","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353283060346125","endTimeUnixNano":"1779353283118065000","durationMs":57.718875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"2f3e0a8ed64a6ae3","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353288120532500","endTimeUnixNano":"1779353288178444459","durationMs":57.911959,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"329b3d1dfa5d7927","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353293180906250","endTimeUnixNano":"1779353293240822417","durationMs":59.916167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"d460cf7e770e99a3","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353298242784000","endTimeUnixNano":"1779353298301601834","durationMs":58.817834,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"43b2e15bfddc9b56","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353303304263292","endTimeUnixNano":"1779353303360885167","durationMs":56.621875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"93c38fd5765c7ea9","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353308363723959","endTimeUnixNano":"1779353308423671917","durationMs":59.947958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"e4a199fda4b9598a","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353313426011042","endTimeUnixNano":"1779353313484615917","durationMs":58.604875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"835d309465c60773","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353318487242834","endTimeUnixNano":"1779353318526340375","durationMs":39.097541,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"b949be41120b8a66","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353323529157125","endTimeUnixNano":"1779353323589568875","durationMs":60.41175,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"be3aa9ef09028b14","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353328591474750","endTimeUnixNano":"1779353328648750750","durationMs":57.276,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"6e022bf0899f67e0","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353333652593625","endTimeUnixNano":"1779353333711016417","durationMs":58.422792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"ba9a479abfdf751a","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353338712931125","endTimeUnixNano":"1779353338771406375","durationMs":58.47525,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"9ae502ba591e4ec0","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353343772737167","endTimeUnixNano":"1779353343832015500","durationMs":59.278333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"02231a20bbb579be","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353348835746125","endTimeUnixNano":"1779353348890508875","durationMs":54.76275,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"b59adea8f1727a57","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353353892850417","endTimeUnixNano":"1779353353951113375","durationMs":58.262958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"b6e3f44252939aef","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353358952245084","endTimeUnixNano":"1779353359012505584","durationMs":60.2605,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"c83511e27b6e6515","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353364014995042","endTimeUnixNano":"1779353364074624459","durationMs":59.629417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"4cc5ff1ef9087dc8","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353369077039625","endTimeUnixNano":"1779353369109487000","durationMs":32.447375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"ce3abcbf71ce7ccf","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353374111014417","endTimeUnixNano":"1779353374171923000","durationMs":60.908583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"68f52ebed754f4cb","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353379175609917","endTimeUnixNano":"1779353379231915459","durationMs":56.305542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"7dbe1807f23bacb3","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353384234675084","endTimeUnixNano":"1779353384291914167","durationMs":57.239083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"010ee1e93ac6e650","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353389293222875","endTimeUnixNano":"1779353389338676042","durationMs":45.453167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"54cb7ecd3f107903","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353394340860584","endTimeUnixNano":"1779353394404048917","durationMs":63.188333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"5c8b439cc7f059d5","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353399406626625","endTimeUnixNano":"1779353399463461792","durationMs":56.835167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"2a941e61ae563757","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353404465459959","endTimeUnixNano":"1779353404522577334","durationMs":57.117375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"618683034339257f","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353409525128750","endTimeUnixNano":"1779353409580997417","durationMs":55.868667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"b4eb08ee2ed3f61c","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353414584381584","endTimeUnixNano":"1779353414640909834","durationMs":56.52825,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"35b8a397fbaf4988","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353419643517292","endTimeUnixNano":"1779353419701920292","durationMs":58.403,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"3ec406f091f485e5","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353424702154125","endTimeUnixNano":"1779353424760297542","durationMs":58.143417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"5e66b2dd0ca71a52","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353429761806084","endTimeUnixNano":"1779353429819968250","durationMs":58.162166,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"03f98ec6eea614ec","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353434823132459","endTimeUnixNano":"1779353434881190625","durationMs":58.058166,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"51f44ee891ece8ea","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353439882190792","endTimeUnixNano":"1779353439938831459","durationMs":56.640667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"6ae438cd5d95e05e","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353444939785084","endTimeUnixNano":"1779353444997346750","durationMs":57.561666,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"bf7070fb83476cc5","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353449999630375","endTimeUnixNano":"1779353450061003375","durationMs":61.373,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"46e6a816c42bd203","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353455064281042","endTimeUnixNano":"1779353455122245875","durationMs":57.964833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"cbd05a300c8db895","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353460125589500","endTimeUnixNano":"1779353460182891709","durationMs":57.302209,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"c1d69cd966f6b40a","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353465186482042","endTimeUnixNano":"1779353465222122000","durationMs":35.639958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"3700757d35cf0aba","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353470224423875","endTimeUnixNano":"1779353470281491042","durationMs":57.067167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"36b23a538dd8d352","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353475284012000","endTimeUnixNano":"1779353475341533292","durationMs":57.521292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"74fbe6d7955b7a6c","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353480343965292","endTimeUnixNano":"1779353480399636542","durationMs":55.67125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"266761cb1ba5de28","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353485400357125","endTimeUnixNano":"1779353485457534750","durationMs":57.177625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"411f863a35dc893d","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353490458533917","endTimeUnixNano":"1779353490513660625","durationMs":55.126708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"5c462b5af13e6d85","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353495515967917","endTimeUnixNano":"1779353495575674292","durationMs":59.706375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"dd104590e49fdfcd","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353500578460750","endTimeUnixNano":"1779353500633725667","durationMs":55.264917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"368b44bc865a7cdd","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353505636151625","endTimeUnixNano":"1779353505693973667","durationMs":57.822042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"40b26ed5fbf729ea","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353510696102959","endTimeUnixNano":"1779353510756943209","durationMs":60.84025,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"91a82c559fd3e473","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353515760803167","endTimeUnixNano":"1779353515819280417","durationMs":58.47725,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeClaudeEnvironment","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"54c940666500c031","parentSpanId":"e27f0091266d50c5","sampled":true,"kind":"internal","startTimeUnixNano":"1779353520266617084","endTimeUnixNano":"1779353520266671459","durationMs":0.054375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runClaudeCommand","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"e27f0091266d50c5","parentSpanId":"48d65b630ec65c2d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353520266576709","endTimeUnixNano":"1779353520270724917","durationMs":4.148208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Failure","cause":"PlatformError: NotFound: ChildProcess.spawn (claude --version)\n at Module.systemError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/effect@4.0.0-beta.59/node_modules/effect/dist/PlatformError.js:59:39)\n at file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/internal/utils.js:28:24\n at toPlatformError (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:25:54)\n at ChildProcess. (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/node_modules/.bun/@effect+platform-node-shared@4.0.0-beta.59+d23ff2b16fb00dbb/node_modules/@effect/platform-node-shared/dist/NodeChildProcessSpawner.js:230:26)\n at ChildProcess.emit (node:events:509:28)\n at ChildProcess._handle.onexit (node:internal/child_process:293:12)\n at onErrorNT (node:internal/child_process:508:16)\n at processTicksAndRejections (node:internal/process/task_queues:90:21)\n at runNextTicks (node:internal/process/task_queues:69:3)\n at listOnTimeout (node:internal/timers:567:9)\n at runClaudeCommand (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:27894:30)\n at runClaudeCommand (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:27870:33)\n at checkClaudeProviderStatus (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30400:25)\n at checkClaudeProviderStatus (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:27878:42)\n at applySnapshot (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30277:83)\n at applySnapshot (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30257:35)\n at refreshSnapshot (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30282:102)\n at refreshSnapshot (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30278:33)\n at makeManagedServerProvider (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30401:27)\n at makeManagedServerProvider (definition) (file:///Users/harrydawson/.t3/worktrees/h-code/t3code-2f47fd69/apps/server/dist/bin.mjs:30222:42) {\n [cause]: Error: spawn claude ENOENT\n at ChildProcess._handle.onexit (node:internal/child_process:287:19)\n at onErrorNT (node:internal/child_process:508:16)\n at processTicksAndRejections (node:internal/process/task_queues:90:21)\n at runNextTicks (node:internal/process/task_queues:69:3)\n at listOnTimeout (node:internal/timers:567:9)\n at process.processTimers (node:internal/timers:541:7)\n}"}} -{"type":"effect-span","name":"checkClaudeProviderStatus","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"48d65b630ec65c2d","parentSpanId":"c349ab19a5154a20","sampled":true,"kind":"internal","startTimeUnixNano":"1779353520266347709","endTimeUnixNano":"1779353520271362500","durationMs":5.014791,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"9f5fec0ed52bc79ef4f9c25002caa04c","spanId":"a77f62d75d35a866","parentSpanId":"0f2024e6242d1f55","sampled":true,"kind":"internal","startTimeUnixNano":"1779353520271614959","endTimeUnixNano":"1779353520271640375","durationMs":0.025416,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"9f5fec0ed52bc79ef4f9c25002caa04c","spanId":"6495b55272f283cd","parentSpanId":"0f2024e6242d1f55","sampled":true,"kind":"internal","startTimeUnixNano":"1779353520272138167","endTimeUnixNano":"1779353520272170792","durationMs":0.032625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"81ca09d6cdd20374","parentSpanId":"c349ab19a5154a20","sampled":true,"kind":"internal","startTimeUnixNano":"1779353520272365084","endTimeUnixNano":"1779353520272459542","durationMs":0.094458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"c349ab19a5154a20","parentSpanId":"0d9e8e9234474bc4","sampled":true,"kind":"internal","startTimeUnixNano":"1779353520266283375","endTimeUnixNano":"1779353520272473917","durationMs":6.190542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"0d9e8e9234474bc4","parentSpanId":"d8882d30663dbbb0","sampled":true,"kind":"internal","startTimeUnixNano":"1779353520266081959","endTimeUnixNano":"1779353520272492417","durationMs":6.410458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"checkCursorProviderStatus","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"f61de4fc5719ce60","parentSpanId":"a6606caa94ac4dc1","sampled":true,"kind":"internal","startTimeUnixNano":"1779353520273382042","endTimeUnixNano":"1779353520273435000","durationMs":0.052958,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"8dbd953ea5f17d83e9a84678089799e5","spanId":"acfe9759319aad28","parentSpanId":"be3bc30817d7d22a","sampled":true,"kind":"internal","startTimeUnixNano":"1779353520273547334","endTimeUnixNano":"1779353520273563042","durationMs":0.015708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"8dbd953ea5f17d83e9a84678089799e5","spanId":"bcb1adb14e2c609b","parentSpanId":"be3bc30817d7d22a","sampled":true,"kind":"internal","startTimeUnixNano":"1779353520273649084","endTimeUnixNano":"1779353520273669542","durationMs":0.020458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"bfc133b8ea79fe4b","parentSpanId":"a6606caa94ac4dc1","sampled":true,"kind":"internal","startTimeUnixNano":"1779353520273756209","endTimeUnixNano":"1779353520273843292","durationMs":0.087083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"a6606caa94ac4dc1","parentSpanId":"c75c62a6f99d536b","sampled":true,"kind":"internal","startTimeUnixNano":"1779353520272609334","endTimeUnixNano":"1779353520273854709","durationMs":1.245375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"c75c62a6f99d536b","parentSpanId":"f4270506fde844da","sampled":true,"kind":"internal","startTimeUnixNano":"1779353520272574750","endTimeUnixNano":"1779353520273866459","durationMs":1.291709,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"35363bc74004f369","parentSpanId":"81ca09d6cdd20374","sampled":true,"kind":"internal","startTimeUnixNano":"1779353520274097000","endTimeUnixNano":"1779353520274116125","durationMs":0.019125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"d0169c83f01e1b64eb5dc47e4ff6c8b0","spanId":"c38d8eebe3a807bc","parentSpanId":"81ca09d6cdd20374","sampled":true,"kind":"internal","startTimeUnixNano":"1779353520274142959","endTimeUnixNano":"1779353520274196084","durationMs":0.053125,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"0ee51628e407cf4a","parentSpanId":"bfc133b8ea79fe4b","sampled":true,"kind":"internal","startTimeUnixNano":"1779353520274225625","endTimeUnixNano":"1779353520274235917","durationMs":0.010292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"5038279188fd4e03552e6e0595e02a06","spanId":"dd04e524affb4eca","parentSpanId":"bfc133b8ea79fe4b","sampled":true,"kind":"internal","startTimeUnixNano":"1779353520274263875","endTimeUnixNano":"1779353520274297917","durationMs":0.034042,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"8dbd953ea5f17d83e9a84678089799e5","spanId":"be3bc30817d7d22a","parentSpanId":"1e37688e9bf62fd4","sampled":true,"kind":"internal","startTimeUnixNano":"1779353520273518584","endTimeUnixNano":"1779353520276190459","durationMs":2.671875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"8dbd953ea5f17d83e9a84678089799e5","spanId":"1e37688e9bf62fd4","sampled":true,"kind":"internal","startTimeUnixNano":"1779353520273498292","endTimeUnixNano":"1779353520276212834","durationMs":2.714542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"e65d9b4f163a6ba9c7087b284d6b6c96","spanId":"7b4be8ffc50ea158","parentSpanId":"bf3f1b07885c5d47","sampled":true,"kind":"internal","startTimeUnixNano":"1779353520276314167","endTimeUnixNano":"1779353520276329000","durationMs":0.014833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"e65d9b4f163a6ba9c7087b284d6b6c96","spanId":"754625bf0a74cc1f","parentSpanId":"bf3f1b07885c5d47","sampled":true,"kind":"internal","startTimeUnixNano":"1779353520276404292","endTimeUnixNano":"1779353520276418500","durationMs":0.014208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"9f5fec0ed52bc79ef4f9c25002caa04c","spanId":"0f2024e6242d1f55","parentSpanId":"7b10b102d30a5d40","sampled":true,"kind":"internal","startTimeUnixNano":"1779353520271552625","endTimeUnixNano":"1779353520276498084","durationMs":4.945459,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"9f5fec0ed52bc79ef4f9c25002caa04c","spanId":"7b10b102d30a5d40","sampled":true,"kind":"internal","startTimeUnixNano":"1779353520271499417","endTimeUnixNano":"1779353520276516917","durationMs":5.0175,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"0b4584b562da422e897737f89614bd43","spanId":"2fc71dd406b96fca","parentSpanId":"c4ee234f89f1532b","sampled":true,"kind":"internal","startTimeUnixNano":"1779353520276579250","endTimeUnixNano":"1779353520276590792","durationMs":0.011542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"0b4584b562da422e897737f89614bd43","spanId":"aaa66fb6ccf77c7a","parentSpanId":"c4ee234f89f1532b","sampled":true,"kind":"internal","startTimeUnixNano":"1779353520276643167","endTimeUnixNano":"1779353520276654167","durationMs":0.011,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"e65d9b4f163a6ba9c7087b284d6b6c96","spanId":"bf3f1b07885c5d47","parentSpanId":"330444f34a193ff8","sampled":true,"kind":"internal","startTimeUnixNano":"1779353520276286209","endTimeUnixNano":"1779353520277975959","durationMs":1.68975,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"e65d9b4f163a6ba9c7087b284d6b6c96","spanId":"330444f34a193ff8","sampled":true,"kind":"internal","startTimeUnixNano":"1779353520276261959","endTimeUnixNano":"1779353520277991250","durationMs":1.729291,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"0b4584b562da422e897737f89614bd43","spanId":"c4ee234f89f1532b","parentSpanId":"4640f5bedc5652bd","sampled":true,"kind":"internal","startTimeUnixNano":"1779353520276559709","endTimeUnixNano":"1779353520278030125","durationMs":1.470416,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"0b4584b562da422e897737f89614bd43","spanId":"4640f5bedc5652bd","sampled":true,"kind":"internal","startTimeUnixNano":"1779353520276541542","endTimeUnixNano":"1779353520278040334","durationMs":1.498792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"e813655b95dc643c","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353520822080875","endTimeUnixNano":"1779353520878618667","durationMs":56.537792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"makeCodexAppServerPatchedProtocol","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"a2832ed3194c4faf","parentSpanId":"084e08125c2cc2b9","sampled":true,"kind":"internal","startTimeUnixNano":"1779353521028091750","endTimeUnixNano":"1779353521028222000","durationMs":0.13025,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"effect-codex-app-server/CodexAppServerClient.make","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"084e08125c2cc2b9","parentSpanId":"03d33c91d97af0e5","sampled":true,"kind":"internal","startTimeUnixNano":"1779353521028034792","endTimeUnixNano":"1779353521028258459","durationMs":0.223667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"requestAllCodexModels","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"2819030fd2c0e82e","parentSpanId":"03d33c91d97af0e5","sampled":true,"kind":"internal","startTimeUnixNano":"1779353521067468084","endTimeUnixNano":"1779353521413853375","durationMs":346.385291,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"probeCodexAppServerProvider","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"03d33c91d97af0e5","parentSpanId":"159b7e6f3939d476","sampled":true,"kind":"internal","startTimeUnixNano":"1779353521025804167","endTimeUnixNano":"1779353521414015792","durationMs":388.211625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"checkCodexProviderStatus","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"159b7e6f3939d476","parentSpanId":"52661391a9a4abae","sampled":true,"kind":"internal","startTimeUnixNano":"1779353521025668209","endTimeUnixNano":"1779353521419382209","durationMs":393.714,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"f65d0afa302bf296dc10e3ca03e81ee9","spanId":"0df9c6f7986d2a48","parentSpanId":"d56721a8777cec82","sampled":true,"kind":"internal","startTimeUnixNano":"1779353521419647459","endTimeUnixNano":"1779353521419672542","durationMs":0.025083,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"f65d0afa302bf296dc10e3ca03e81ee9","spanId":"d58e1f562e6ed3eb","parentSpanId":"d56721a8777cec82","sampled":true,"kind":"internal","startTimeUnixNano":"1779353521420008167","endTimeUnixNano":"1779353521420036959","durationMs":0.028792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"90e9097ca416dace","parentSpanId":"52661391a9a4abae","sampled":true,"kind":"internal","startTimeUnixNano":"1779353521420287250","endTimeUnixNano":"1779353521420370542","durationMs":0.083292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"52661391a9a4abae","parentSpanId":"39d4b9a4e7e3bc9c","sampled":true,"kind":"internal","startTimeUnixNano":"1779353521025636917","endTimeUnixNano":"1779353521420382417","durationMs":394.7455,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"39d4b9a4e7e3bc9c","parentSpanId":"5bc4cdb3beb605ab","sampled":true,"kind":"internal","startTimeUnixNano":"1779353521025569542","endTimeUnixNano":"1779353521420401459","durationMs":394.831917,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveLatestProviderVersion","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"b7eec60ba036ddba","parentSpanId":"5f505e0e2a396132","sampled":true,"kind":"internal","startTimeUnixNano":"1779353521420469375","endTimeUnixNano":"1779353521420495209","durationMs":0.025834,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"5f505e0e2a396132","parentSpanId":"90e9097ca416dace","sampled":true,"kind":"internal","startTimeUnixNano":"1779353521420444875","endTimeUnixNano":"1779353521420562750","durationMs":0.117875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"694403bea65268df2f5ef05c68beeae5","spanId":"02a4e3d6af136865","parentSpanId":"90e9097ca416dace","sampled":true,"kind":"internal","startTimeUnixNano":"1779353521420585209","endTimeUnixNano":"1779353521420633667","durationMs":0.048458,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"f65d0afa302bf296dc10e3ca03e81ee9","spanId":"d56721a8777cec82","parentSpanId":"c7efddc2f89b0377","sampled":true,"kind":"internal","startTimeUnixNano":"1779353521419602167","endTimeUnixNano":"1779353521422967709","durationMs":3.365542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"f65d0afa302bf296dc10e3ca03e81ee9","spanId":"c7efddc2f89b0377","sampled":true,"kind":"internal","startTimeUnixNano":"1779353521419555167","endTimeUnixNano":"1779353521422993417","durationMs":3.43825,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"c090342f2da2dc60c0d8bf02732df545","spanId":"ef27245c66bb0f80","parentSpanId":"3d0f0e1b2de273b8","sampled":true,"kind":"internal","startTimeUnixNano":"1779353521423125125","endTimeUnixNano":"1779353521423142375","durationMs":0.01725,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"c090342f2da2dc60c0d8bf02732df545","spanId":"1d5d57cd75cd53c1","parentSpanId":"3d0f0e1b2de273b8","sampled":true,"kind":"internal","startTimeUnixNano":"1779353521423245875","endTimeUnixNano":"1779353521423262542","durationMs":0.016667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"c090342f2da2dc60c0d8bf02732df545","spanId":"3d0f0e1b2de273b8","parentSpanId":"c67d4491ac952dc0","sampled":true,"kind":"internal","startTimeUnixNano":"1779353521423090167","endTimeUnixNano":"1779353521424435334","durationMs":1.345167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"c090342f2da2dc60c0d8bf02732df545","spanId":"c67d4491ac952dc0","sampled":true,"kind":"internal","startTimeUnixNano":"1779353521423058042","endTimeUnixNano":"1779353521424446667","durationMs":1.388625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"9c222a79013464bbed30efe9f66a4107","spanId":"e044760df7c62efa","parentSpanId":"bdaa4ceb2b2577ba","sampled":true,"kind":"client","startTimeUnixNano":"1779353524782326917","endTimeUnixNano":"1779353524782906334","durationMs":0.579417,"attributes":{"server.mode":"desktop","server.port":14124,"server.host":"127.0.0.1","startup.phase":"reactors.start","db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n thread_id AS \"threadId\",\n provider_name AS \"providerName\",\n provider_instance_id AS \"providerInstanceId\",\n adapter_key AS \"adapterKey\",\n runtime_mode AS \"runtimeMode\",\n status,\n last_seen_at AS \"lastSeenAt\",\n resume_cursor_json AS \"resumeCursor\",\n runtime_payload_json AS \"runtimePayload\"\n FROM provider_session_runtime\n ORDER BY last_seen_at ASC, thread_id ASC\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"5fbe2ddc2917ebeb","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353525880910959","endTimeUnixNano":"1779353525941430375","durationMs":60.519416,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"cdb35a136a06a307","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353530943952459","endTimeUnixNano":"1779353530968102667","durationMs":24.150208,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"opencode.app.agents","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"1dd86ef52d8adde6","parentSpanId":"fc3e75e099459cb1","sampled":true,"kind":"internal","startTimeUnixNano":"1779353531348816250","endTimeUnixNano":"1779353531559491667","durationMs":210.675417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"opencode.provider.list","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"f899433db689932a","parentSpanId":"fc3e75e099459cb1","sampled":true,"kind":"internal","startTimeUnixNano":"1779353531348748084","endTimeUnixNano":"1779353531672814417","durationMs":324.066333,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"checkOpenCodeProviderStatus","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"fc3e75e099459cb1","parentSpanId":"2ef413dafffdd846","sampled":true,"kind":"internal","startTimeUnixNano":"1779353530645207500","endTimeUnixNano":"1779353532676679834","durationMs":2031.472334,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"7e8308d6d9852c2bafb7a88486a0d959","spanId":"8b7caa8108a7d053","parentSpanId":"3a40f0c2d5c19dec","sampled":true,"kind":"internal","startTimeUnixNano":"1779353532677027875","endTimeUnixNano":"1779353532677052625","durationMs":0.02475,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"7e8308d6d9852c2bafb7a88486a0d959","spanId":"a6d26f466fb42490","parentSpanId":"3a40f0c2d5c19dec","sampled":true,"kind":"internal","startTimeUnixNano":"1779353532678525000","endTimeUnixNano":"1779353532678554750","durationMs":0.02975,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"restartSnapshotEnrichment","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"2ce97adb96a7d9b7","parentSpanId":"2ef413dafffdd846","sampled":true,"kind":"internal","startTimeUnixNano":"1779353532679134375","endTimeUnixNano":"1779353532679246459","durationMs":0.112084,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applySnapshot","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"2ef413dafffdd846","parentSpanId":"d602b6d442b85a5a","sampled":true,"kind":"internal","startTimeUnixNano":"1779353530645152917","endTimeUnixNano":"1779353532679261167","durationMs":2034.10825,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"refreshSnapshot","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"d602b6d442b85a5a","parentSpanId":"2f989ef1cbf60c79","sampled":true,"kind":"internal","startTimeUnixNano":"1779353530645009584","endTimeUnixNano":"1779353532679278000","durationMs":2034.268416,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveLatestProviderVersion","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"4d9ab4c02e00eb51","parentSpanId":"c81831ffcfe04383","sampled":true,"kind":"internal","startTimeUnixNano":"1779353532679360042","endTimeUnixNano":"1779353532679394042","durationMs":0.034,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"enrichProviderSnapshotWithVersionAdvisory","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"c81831ffcfe04383","parentSpanId":"2ce97adb96a7d9b7","sampled":true,"kind":"internal","startTimeUnixNano":"1779353532679332709","endTimeUnixNano":"1779353532679461417","durationMs":0.128708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"publishEnrichedSnapshot","traceId":"309710dfced0992a32c7eae4acf5066b","spanId":"24284e0ec0380590","parentSpanId":"2ce97adb96a7d9b7","sampled":true,"kind":"internal","startTimeUnixNano":"1779353532679486709","endTimeUnixNano":"1779353532679557000","durationMs":0.070291,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"7e8308d6d9852c2bafb7a88486a0d959","spanId":"3a40f0c2d5c19dec","parentSpanId":"8f6a2a8873a9e1c8","sampled":true,"kind":"internal","startTimeUnixNano":"1779353532676968459","endTimeUnixNano":"1779353532681395459","durationMs":4.427,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"7e8308d6d9852c2bafb7a88486a0d959","spanId":"8f6a2a8873a9e1c8","sampled":true,"kind":"internal","startTimeUnixNano":"1779353532676913917","endTimeUnixNano":"1779353532681418417","durationMs":4.5045,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"applyProviderUpdateState","traceId":"4c78b32d1e20838a81b4fd56477d89fd","spanId":"4403b69de39e43e0","parentSpanId":"bb3fd24100d171b4","sampled":true,"kind":"internal","startTimeUnixNano":"1779353532681554750","endTimeUnixNano":"1779353532681574000","durationMs":0.01925,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"resolveProviderStatusCachePath","traceId":"4c78b32d1e20838a81b4fd56477d89fd","spanId":"c389988b488f64ee","parentSpanId":"bb3fd24100d171b4","sampled":true,"kind":"internal","startTimeUnixNano":"1779353532681711250","endTimeUnixNano":"1779353532681732542","durationMs":0.021292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"upsertProviders","traceId":"4c78b32d1e20838a81b4fd56477d89fd","spanId":"bb3fd24100d171b4","parentSpanId":"5d3a574fe3ea9cd8","sampled":true,"kind":"internal","startTimeUnixNano":"1779353532681514625","endTimeUnixNano":"1779353532683402875","durationMs":1.88825,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"syncProvider","traceId":"4c78b32d1e20838a81b4fd56477d89fd","spanId":"5d3a574fe3ea9cd8","sampled":true,"kind":"internal","startTimeUnixNano":"1779353532681486000","endTimeUnixNano":"1779353532683420667","durationMs":1.934667,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"dae47dab3412e6b4","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353535969736292","endTimeUnixNano":"1779353536026134667","durationMs":56.398375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"58db955fd3c3cdf0","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353541027741917","endTimeUnixNano":"1779353541084664084","durationMs":56.922167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"d7674843fd7b3a7d","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353546087281834","endTimeUnixNano":"1779353546145171584","durationMs":57.88975,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"319785ae537233d0","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353551148204750","endTimeUnixNano":"1779353551205129042","durationMs":56.924292,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"4ba4045950da395a","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353556208569750","endTimeUnixNano":"1779353556266318917","durationMs":57.749167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"09a1ec4f5f4ce283","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353561267282000","endTimeUnixNano":"1779353561323416500","durationMs":56.1345,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"eca82e54be74e045","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353566325949500","endTimeUnixNano":"1779353566387231750","durationMs":61.28225,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"2465acc9e5eddc11","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353571389583667","endTimeUnixNano":"1779353571445706542","durationMs":56.122875,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"6e8c9ad8b5f40b34","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353576448159000","endTimeUnixNano":"1779353576509138417","durationMs":60.979417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"d8e9eece6d3aca73","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353581512567709","endTimeUnixNano":"1779353581570571292","durationMs":58.003583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"4c054a3d96c43b37","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353586573711000","endTimeUnixNano":"1779353586630661334","durationMs":56.950334,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"7104789efe603a49","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353591632853292","endTimeUnixNano":"1779353591691119834","durationMs":58.266542,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"0115ab81793e5e19","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353596694271584","endTimeUnixNano":"1779353596753724417","durationMs":59.452833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"2d89e56b33fdf2f8","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353601757434792","endTimeUnixNano":"1779353601815234500","durationMs":57.799708,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"592b75f5592052c3","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353606818547459","endTimeUnixNano":"1779353606875323875","durationMs":56.776416,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"17d311dac5cc2895","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353611877577459","endTimeUnixNano":"1779353611934613750","durationMs":57.036291,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"08004cc4476fb285","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353616936971875","endTimeUnixNano":"1779353616994336667","durationMs":57.364792,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"7556d083313e8265","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353621995811292","endTimeUnixNano":"1779353622022021125","durationMs":26.209833,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"b093c63b4361a408","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353627025185125","endTimeUnixNano":"1779353627081029750","durationMs":55.844625,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"b8045d3c6bb6bbb8","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353632084000792","endTimeUnixNano":"1779353632139722209","durationMs":55.721417,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"ef242c47ada20f81","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353637141782792","endTimeUnixNano":"1779353637198197375","durationMs":56.414583,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"d82c125a032573d4","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353642200916459","endTimeUnixNano":"1779353642256948750","durationMs":56.032291,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"9819a646e1942a0d1e9061ad3054e5af","spanId":"6156d30ad030cf4e","parentSpanId":"3b9a256ba47fd19f","sampled":true,"kind":"client","startTimeUnixNano":"1779353647091639750","endTimeUnixNano":"1779353647091707250","durationMs":0.0675,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n thread_id AS \"threadId\",\n provider_name AS \"providerName\",\n provider_instance_id AS \"providerInstanceId\",\n adapter_key AS \"adapterKey\",\n runtime_mode AS \"runtimeMode\",\n status,\n last_seen_at AS \"lastSeenAt\",\n resume_cursor_json AS \"resumeCursor\",\n runtime_payload_json AS \"runtimePayload\"\n FROM provider_session_runtime\n ORDER BY last_seen_at ASC, thread_id ASC\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sql.execute","traceId":"9819a646e1942a0d1e9061ad3054e5af","spanId":"98c58be5d5b4463f","parentSpanId":"3b9a256ba47fd19f","sampled":true,"kind":"client","startTimeUnixNano":"1779353647092006834","endTimeUnixNano":"1779353647092035334","durationMs":0.0285,"attributes":{"db.name":"state.sqlite","service.name":"t3-server","db.system.name":"sqlite","db.operation.name":"execute","db.query.text":"\n SELECT\n thread_id AS \"threadId\",\n provider_name AS \"providerName\",\n provider_instance_id AS \"providerInstanceId\",\n adapter_key AS \"adapterKey\",\n runtime_mode AS \"runtimeMode\",\n status,\n last_seen_at AS \"lastSeenAt\",\n resume_cursor_json AS \"resumeCursor\",\n runtime_payload_json AS \"runtimePayload\"\n FROM provider_session_runtime\n ORDER BY last_seen_at ASC, thread_id ASC\n "},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"record","traceId":"9819a646e1942a0d1e9061ad3054e5af","spanId":"708703674c7c7055","parentSpanId":"3b9a256ba47fd19f","sampled":true,"kind":"internal","startTimeUnixNano":"1779353647092076459","endTimeUnixNano":"1779353647092161834","durationMs":0.085375,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runProcess","traceId":"a89de4f561686fa31f2ed31c7bfe6f3e","spanId":"986966d0c946d526","parentSpanId":"48b29d3d5342695d","sampled":true,"kind":"internal","startTimeUnixNano":"1779353647259980750","endTimeUnixNano":"1779353647287856917","durationMs":27.876167,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"http.client POST","traceId":"9819a646e1942a0d1e9061ad3054e5af","spanId":"c08dd7c6cab0cb4c","parentSpanId":"bfff931d04f2f21c","sampled":true,"kind":"client","startTimeUnixNano":"1779353647092702459","endTimeUnixNano":"1779353647762064459","durationMs":669.362,"attributes":{"http.request.method":"POST","server.address":"https://us.i.posthog.com","url.full":"https://us.i.posthog.com/batch/","url.path":"/batch/","url.scheme":"https","http.request.header.content-type":"application/json","http.request.header.content-length":"384","http.response.status_code":200,"http.response.header.access-control-allow-credentials":"true","http.response.header.connection":"keep-alive","http.response.header.content-length":"15","http.response.header.content-type":"application/json","http.response.header.date":"Thu, 21 May 2026 08:54:07 GMT","http.response.header.server":"envoy","http.response.header.strict-transport-security":"max-age=31536000; includeSubDomains","http.response.header.vary":"origin, access-control-request-method, access-control-request-headers","http.response.header.x-envoy-upstream-service-time":"22"},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"sendBatch","traceId":"9819a646e1942a0d1e9061ad3054e5af","spanId":"bfff931d04f2f21c","parentSpanId":"3b9a256ba47fd19f","sampled":true,"kind":"internal","startTimeUnixNano":"1779353647092203500","endTimeUnixNano":"1779353647762296084","durationMs":670.092584,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"runStopAll","traceId":"9819a646e1942a0d1e9061ad3054e5af","spanId":"3b9a256ba47fd19f","parentSpanId":"e3dac6c835a197fc","sampled":true,"kind":"internal","startTimeUnixNano":"1779353647091504917","endTimeUnixNano":"1779353647762354667","durationMs":670.84975,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"cancelIdleCloseFiber","traceId":"2596d247ab8f9051392b6558766c78f2","spanId":"77672b30ed71424e","parentSpanId":"38f7ccc336ea8ba2","sampled":true,"kind":"internal","startTimeUnixNano":"1779353647768141459","endTimeUnixNano":"1779353647768200709","durationMs":0.05925,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} -{"type":"effect-span","name":"closeSharedServer","traceId":"2596d247ab8f9051392b6558766c78f2","spanId":"7eee58750cff500e","parentSpanId":"38f7ccc336ea8ba2","sampled":true,"kind":"internal","startTimeUnixNano":"1779353647768241000","endTimeUnixNano":"1779353647768282834","durationMs":0.041834,"attributes":{},"events":[],"links":[],"exit":{"_tag":"Success"}} diff --git a/.t3-home/dev/secrets/server-signing-key.bin b/.t3-home/dev/secrets/server-signing-key.bin deleted file mode 100644 index fee273f4d899..000000000000 --- a/.t3-home/dev/secrets/server-signing-key.bin +++ /dev/null @@ -1,2 +0,0 @@ -cIT  -)\ $ɵe^ \ No newline at end of file diff --git a/.t3-home/dev/settings.json b/.t3-home/dev/settings.json deleted file mode 100644 index 7f55d546e60e..000000000000 --- a/.t3-home/dev/settings.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "projectThreadDefaults": { - "c3c533c1-415d-4b3b-ab05-63bdf7135dc7:/Users/harrydawson": "local" - }, - "manualSidebarGroups": [ - { - "id": "home", - "name": "home", - "collapsed": false - } - ], - "projectManualSidebarGroupAssignments": { - "c3c533c1-415d-4b3b-ab05-63bdf7135dc7:/Users/harrydawson": "home" - } -} diff --git a/.t3-home/dev/state.sqlite b/.t3-home/dev/state.sqlite deleted file mode 100644 index 786089821869..000000000000 Binary files a/.t3-home/dev/state.sqlite and /dev/null differ diff --git a/AGENTS.md b/AGENTS.md index 1e8b6a8a4564..85b112eaec30 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -88,20 +88,6 @@ Long term maintainability is a core priority. If you add new functionality, firs Use these as implementation references when designing protocol handling, UX flows, and operational safeguards. -## Agent skills - -### Issue tracker - -Issues for this repo are tracked in GitHub Issues for `harrryyd/h-code`. See `docs/agents/issue-tracker.md`. - -### Triage labels - -This repo uses the default triage label vocabulary: `needs-triage`, `needs-info`, `ready-for-agent`, `ready-for-human`, and `wontfix`. See `docs/agents/triage-labels.md`. - -### Domain docs - -This repo is configured as a single-context repo with a root `CONTEXT.md` and root `docs/adr/` when present. See `docs/agents/domain.md`. - ## Vendored Repositories This project vendors external repositories under `.repos/` as read-only reference material for coding diff --git a/CONTEXT.md b/CONTEXT.md deleted file mode 100644 index 06ca97e900af..000000000000 --- a/CONTEXT.md +++ /dev/null @@ -1,191 +0,0 @@ -# T3 Code Fork UX - -This context covers the user's navigation and workspace-management experience in the application. It defines the language for projects, threads, grouping, and PR-linked sidebar affordances so future changes use consistent terms. - -## Language - -**Project**: -A workspace entry that owns threads and points at a concrete working directory. -_Avoid_: Repo, folder, checkout - -**Thread**: -A conversational work item within a Project. -_Avoid_: Chat, session - -**Manager Console**: -The single persistent conversation used to coordinate work across one or more Worker Threads, potentially across multiple Projects. -_Avoid_: Supervisor chat, orchestration session, manager thread - -**Manager Workspace**: -The dedicated filesystem workspace that owns the Manager Console and its persistent context, separate from any specific Project checkout. -_Avoid_: Home project, root repo - -**Worker Thread**: -A first-class Thread created to execute delegated work on behalf of the Manager Console within a specific Project. -_Avoid_: Child session, background task - -**Refiner Thread**: -A first-class Thread created by the Manager Console to refine a seeded work item with the human inside a specific Project before delegation, typically using `grill-with-docs`. -_Avoid_: Planning chat, intake note - -**Worker Escalation**: -A structured event emitted from a Worker Thread to signal that the Manager Console must review, answer, or route something. -_Avoid_: Heuristic alert, transcript scan hit - -**Manager Queue Item**: -A linked coordination item created in the Manager Console from a Worker Escalation. -_Avoid_: Bead, inbox row, notification - -**Refinement Handoff**: -The manager-side update that records a Refiner Thread's outcome back onto the originating work item so delegation can continue, including the refined problem statement, acceptance criteria, and target Project. -_Avoid_: Thread closeout, planning summary - -**Manager Queue Discipline**: -The rule used to choose which Manager Queue Item the Manager Console handles next. -_Avoid_: Scheduling policy, priority system - -**Delegation Intake**: -The manager-side pass that reviews seeded work items before any Worker Thread is created. -_Avoid_: Auto-spawn, blind dispatch - -**Work Readiness**: -The classification of a seeded work item based on whether it is ready for delegation, needs refinement, or should stay with the human. -_Avoid_: Priority, estimate - -**Current Thread**: -The Thread that is actively open in the main chat view. -_Avoid_: Selected thread, focused thread - -**Thread Workspace Mode**: -The workspace strategy used for a new Thread, either Local Checkout or New Worktree. -_Avoid_: Checkout mode, env mode - -**Project Thread Default**: -The default Thread Workspace Mode used when creating a new Thread in a specific Project. -_Avoid_: Project env mode, project checkout preference - -**Logical Project Grouping**: -An automatic rule that determines when multiple Project entries should be presented as the same Project in the sidebar. -_Avoid_: Manual group, folder - -**Manual Sidebar Group**: -A user-defined, local-only container used to organize Projects in the sidebar. -_Avoid_: Project grouping, repository grouping - -**Project Picker Flow**: -The keyboard-first flow that opens `New thread in...`, lets the user choose a Project, and then creates a Thread in that Project. -_Avoid_: Selected project shortcut - -**Focus Chat Shortcut**: -A keyboard shortcut that moves focus to the composer for the Current Thread. -_Avoid_: Focus thread, focus window - -**Change Request Badge**: -A sidebar thread indicator that shows Change Request state and glanceable metadata for the Thread's linked Change Request. -_Avoid_: PR icon, badge - -**Change Request Review**: -A sub-mode of a Thread that provides an interactive diff review experience for the Change Request linked to that Thread, allowing inline comments, AI-assisted review responses, and GitHub review submission — all inside the app instead of on the Git provider's website. -_Avoid_: PR review mode, review panel - -**Review Draft**: -The locally cached set of Review Comments that have been authored but not yet posted to the Git provider. Persists across server restarts and is shared by all Threads linked to the same Change Request. -_Avoid_: Pending comments, local review state - -**Review Comment**: -An inline comment anchored to a file, optional line number, and commit SHA within a Change Request Review. -_Avoid_: Inline review, PR note - -**Background Review Agent**: -A short-lived AI agent spawned from a Review Comment to respond to or act on that comment. Runs in an isolated temp worktree, pushes commits directly to the Change Request branch, and streams responses back inline. -_Avoid_: Review bot, response agent - -**Delegation Badge**: -A sidebar thread indicator that marks a Worker Thread as delegated from the Manager Console. -_Avoid_: Agent badge, child badge - -**Manager Agent**: -The LLM-driven decision maker that operates within the Manager Console to classify work, handle Worker Escalations, create Refiner Threads, and propose Worker delegations. -_Avoid_: Manager AI, orchestration agent - -**Autonomous Turn**: -A manager turn triggered by domain events (not human input) where the Manager Agent runs Manager CLI commands to process its inbox. -_Avoid_: Scheduled turn, cron turn, background turn - -**Manager CLI**: -The standalone `foreman` command set that the Manager Agent uses via its provider's bash tool to interact with the orchestration system (classify, resolve, dismiss, refiner create, delegate propose, prefs, status). -_Avoid_: Manager API, manager SDK - -**Manager Inbox**: -A distinct sidebar section that contains the Manager Console separately from Project-owned Threads. -_Avoid_: Supervisor project, orchestration group - -**Server-Persisted User Preference**: -A user-specific setting stored by the local server in `userdata/settings.json`. -_Avoid_: Project metadata, browser-only setting - -## Relationships - -- A **Project** contains many **Threads** -- A **Manager Console** can coordinate many **Worker Threads** -- A **Manager Console** belongs to the **Manager Workspace** -- A **Manager Workspace** contains exactly one **Manager Console** -- A **Manager Console** contains many **Manager Queue Items** -- A **Manager Console** uses one **Manager Queue Discipline** -- A **Manager Console** performs **Delegation Intake** on seeded work items -- A **Manager Console** can create many **Refiner Threads** -- A **Worker Thread** belongs to exactly one **Project** -- A **Worker Thread** can belong to at most one **Manager Console** -- A **Worker Thread** can emit many **Worker Escalations** -- A **Worker Escalation** creates exactly one **Manager Queue Item** -- A **Refiner Thread** belongs to the **Manager Console** -- A **Refiner Thread** belongs to exactly one **Project** -- A **Refiner Thread** produces one **Refinement Handoff** -- A seeded work item has one **Work Readiness** -- A **Current Thread** is exactly one active **Thread** -- A **Project Thread Default** belongs to one **Project** -- A **Project Thread Default** selects one **Thread Workspace Mode** -- A **Project Thread Default** is a **Server-Persisted User Preference** -- A **Manager Agent** operates within the **Manager Console** -- A **Manager Agent** uses the **Manager CLI** to execute decisions -- A **Manager Agent** performs **Autonomous Turns** when triggered by domain events -- A **Manager Agent** follows the **Manager Queue Discipline** -- A **Manager Agent** performs **Delegation Intake** -- A **Manager Inbox** contains the **Manager Console** -- A **Manager Inbox** presents the **Manager Console** from the **Manager Workspace** -- A **Manual Sidebar Group** contains many **Projects** -- A **Project** belongs to at most one **Manual Sidebar Group** -- A **Project Picker Flow** chooses exactly one **Project** -- A **Focus Chat Shortcut** targets the **Current Thread** -- A **Logical Project Grouping** can combine multiple physical **Projects** into one sidebar presentation -- A **Change Request Badge** belongs to a **Thread** when that Thread is linked to a Change Request -- A **Change Request Review** belongs to a **Thread** that is linked to a Change Request -- A **Change Request Review** contains many **Review Comments** -- A **Review Draft** belongs to a **Change Request Review** -- A **Review Comment** is anchored to a file, optionally a line, and a commit SHA -- A **Review Comment** can spawn a **Background Review Agent** -- A **Background Review Agent** runs in an isolated temp worktree -- A **Background Review Agent** pushes commits to the Change Request branch -- A **Change Request Review** is shared across all **Threads** linked to the same Change Request -- A **Delegation Badge** belongs to a **Worker Thread** - -## Example dialogue - -> **Dev:** "If I create a new Thread from a Project with no Current Thread, should the Project Thread Default still decide whether it uses Local Checkout or New Worktree?" -> **Domain expert:** "Yes. The Project Thread Default belongs to the Project, not to the Current Thread." - -## Flagged ambiguities - -- "group" was used to mean both **Logical Project Grouping** and **Manual Sidebar Group** — resolved: these are distinct concepts. -- "selected project" was used to describe keyboard-driven creation without an active thread — resolved: use **Project Picker Flow** for this interaction instead of implying a separate sidebar selection model. -- "change request badge" and "PR badge" were used interchangeably — resolved: use **Change Request Badge** as the canonical term. -- "project picker flow" was ambiguous — resolved: it refers to the existing `New thread in...` interaction, ideally with its own shortcut. -- "manager session", "supervisor chat", and "manager thread" were used interchangeably — resolved: use **Manager Console** for the single coordinating conversation and **Worker Thread** for delegated execution conversations. -- "home project" and "manager home thread" were ambiguous — resolved: use **Manager Workspace** for the dedicated filesystem workspace that owns the **Manager Console** and its persistent context. -- "blocker detection" and "question detection" were described as possible transcript scanning — resolved: use explicit **Worker Escalations** that create linked **Manager Queue Items**. -- "priority" and "category" were at risk of being conflated — resolved: v1 uses FIFO **Manager Queue Discipline** while still categorizing **Manager Queue Items** by type. -- "starting work" was at risk of meaning both classification and delegation — resolved: use **Delegation Intake** for the pre-spawn classification pass and **Work Readiness** for the resulting state. -- "needs-refinement" was initially treated as a Manager Console-only state — resolved: it can spawn a dedicated **Refiner Thread** that returns a **Refinement Handoff** before worker delegation. -- "refinement workspace" was ambiguous — resolved: a **Refiner Thread** is project-specific because it uses repo-local context such as `CONTEXT.md` and ADRs. -- "refinement output" was at risk of becoming a full implementation spec — resolved: the minimum **Refinement Handoff** centers on refined problem statement, behavioral or functional acceptance criteria, and target **Project**, without forcing file-path-level guidance. -- "PR review" and "review panel" were used loosely — resolved: use **Change Request Review** as the canonical domain term, **Review Draft** for the locally cached comment set, and **Background Review Agent** for the AI spawned to respond to comments. "PR review" is acceptable in conversation since it maps to the common GitHub use case. diff --git a/README.md b/README.md index 33fa5838ca64..6aebfc7e8b85 100644 --- a/README.md +++ b/README.md @@ -85,10 +85,6 @@ Checkout their getting started guide for more information: https://viteplus.dev/ vp i ``` -T3 Cloud is optional and disabled in a fresh clone. To enable it for web, desktop, and mobile source -builds, copy [`.env.example`](./.env.example) to `.env` at the repository root and set the canonical -public configuration there. - Read [CONTRIBUTING.md](./CONTRIBUTING.md) before opening an issue or PR. Need support? Join the [Discord](https://discord.gg/jn4EGJjrvv). diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 0795c48a6ed4..e61587f65392 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -1,6 +1,6 @@ { "name": "@t3tools/desktop", - "version": "0.0.24", + "version": "0.0.26", "private": true, "type": "module", "main": "dist-electron/main.cjs", diff --git a/apps/desktop/src/backend/tailscaleEndpointProvider.ts b/apps/desktop/src/backend/tailscaleEndpointProvider.ts index cffe15724109..79c86f540e89 100644 --- a/apps/desktop/src/backend/tailscaleEndpointProvider.ts +++ b/apps/desktop/src/backend/tailscaleEndpointProvider.ts @@ -121,7 +121,7 @@ export const resolveTailscaleAdvertisedEndpoints = Effect.fn("resolveTailscaleAd input.readMagicDnsName ?? readTailscaleStatus.pipe( Effect.map((status) => status.magicDnsName), - Effect.catch(() => Effect.succeed(null)), + Effect.orElseSucceed((): string | null => null), ); const dnsName = input.statusJson === undefined diff --git a/apps/desktop/src/window/DesktopWindow.test.ts b/apps/desktop/src/window/DesktopWindow.test.ts index 271b35095e40..5e977de2dea9 100644 --- a/apps/desktop/src/window/DesktopWindow.test.ts +++ b/apps/desktop/src/window/DesktopWindow.test.ts @@ -165,7 +165,7 @@ describe("DesktopWindow", () => { assert.isTrue( DesktopWindow.isSameOriginRendererNavigation({ applicationUrl: "http://127.0.0.1:3773/", - navigationUrl: "http://127.0.0.1:3773/settings/cloud", + navigationUrl: "http://127.0.0.1:3773/settings/connections", }), ); assert.isFalse( diff --git a/apps/mobile/README.md b/apps/mobile/README.md index f5be27c6c3f7..ad0242c27141 100644 --- a/apps/mobile/README.md +++ b/apps/mobile/README.md @@ -16,7 +16,7 @@ This app has three variants: Run commands from `apps/mobile`. -T3 Cloud is optional and disabled in a fresh clone. Public configuration belongs in the +T3 Connect is optional and disabled in a fresh clone. Public configuration belongs in the repository-root `.env` or `.env.local`, not an `apps/mobile/.env` file. See [`../../.env.example`](../../.env.example). diff --git a/apps/mobile/app.config.ts b/apps/mobile/app.config.ts index e6f6e3cfb631..7cbb8335deb6 100644 --- a/apps/mobile/app.config.ts +++ b/apps/mobile/app.config.ts @@ -161,6 +161,11 @@ const config: ExpoConfig = { publishableKey: repoEnv.EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY ?? null, jwtTemplate: repoEnv.EXPO_PUBLIC_CLERK_JWT_TEMPLATE ?? null, }, + observability: { + tracesUrl: repoEnv.EXPO_PUBLIC_OTLP_TRACES_URL ?? "https://api.axiom.co/v1/traces", + tracesDataset: repoEnv.EXPO_PUBLIC_OTLP_TRACES_DATASET ?? null, + tracesToken: repoEnv.EXPO_PUBLIC_OTLP_TRACES_TOKEN ?? null, + }, eas: { projectId: "d763fcb8-d37c-41ea-a773-b54a0ab4a454", }, diff --git a/apps/mobile/src/features/agent-awareness/remoteRegistration.ts b/apps/mobile/src/features/agent-awareness/remoteRegistration.ts index b8342eaa30fa..3e49ec1e2579 100644 --- a/apps/mobile/src/features/agent-awareness/remoteRegistration.ts +++ b/apps/mobile/src/features/agent-awareness/remoteRegistration.ts @@ -41,7 +41,7 @@ export function normalizeAgentAwarenessRelayBaseUrl( } function readRelayConfig(): { readonly url: string } | null { - const relayUrl = resolveCloudPublicConfig().relayUrl; + const relayUrl = resolveCloudPublicConfig().relay.url; if (!relayUrl) { logRegistrationDebug("relay registration skipped; relay config missing"); return null; diff --git a/apps/mobile/src/features/cloud/CloudAuthProvider.tsx b/apps/mobile/src/features/cloud/CloudAuthProvider.tsx index f196944ef0c7..5fc3b96fdc8c 100644 --- a/apps/mobile/src/features/cloud/CloudAuthProvider.tsx +++ b/apps/mobile/src/features/cloud/CloudAuthProvider.tsx @@ -66,7 +66,9 @@ function CloudAuthBridge(props: { readonly children: ReactNode }) { } export function CloudAuthProvider(props: { readonly children: ReactNode }) { - const { clerkPublishableKey: publishableKey, relayUrl } = resolveCloudPublicConfig(); + const config = resolveCloudPublicConfig(); + const publishableKey = config.clerk.publishableKey; + const relayUrl = config.relay.url; useEffect(() => { if (!publishableKey || !relayUrl) { diff --git a/apps/mobile/src/features/cloud/linkEnvironment.test.ts b/apps/mobile/src/features/cloud/linkEnvironment.test.ts index 16a7a7453981..36544cf46cc3 100644 --- a/apps/mobile/src/features/cloud/linkEnvironment.test.ts +++ b/apps/mobile/src/features/cloud/linkEnvironment.test.ts @@ -572,7 +572,7 @@ describe("mobile cloud link environment client", () => { if (String(url).endsWith("/v1/client/environment-link-challenges")) { return Promise.resolve(Response.json(validLinkChallengeResponse())); } - if (String(url).endsWith("/api/cloud/link-proof")) { + if (String(url).endsWith("/api/connect/link-proof")) { return Promise.resolve(Response.json(validLinkProof())); } return Promise.resolve(Response.json(validLinkResponse("env-other"))); @@ -631,7 +631,7 @@ describe("mobile cloud link environment client", () => { if (String(url).endsWith("/v1/client/environment-link-challenges")) { return Promise.resolve(Response.json(validLinkChallengeResponse())); } - if (String(url).endsWith("/api/cloud/link-proof")) { + if (String(url).endsWith("/api/connect/link-proof")) { return Promise.resolve(Response.json(validLinkProof())); } return Promise.resolve( @@ -669,7 +669,7 @@ describe("mobile cloud link environment client", () => { if (String(url).endsWith("/v1/client/environment-link-challenges")) { return Promise.resolve(Response.json(validLinkChallengeResponse())); } - if (String(url).endsWith("/api/cloud/link-proof")) { + if (String(url).endsWith("/api/connect/link-proof")) { return Promise.resolve(Response.json(validLinkProof())); } return Promise.resolve( @@ -713,7 +713,7 @@ describe("mobile cloud link environment client", () => { if (String(url).endsWith("/v1/client/environment-link-challenges")) { return Promise.resolve(Response.json(validLinkChallengeResponse())); } - if (String(url).endsWith("/api/cloud/link-proof")) { + if (String(url).endsWith("/api/connect/link-proof")) { return Promise.resolve(Response.json(validLinkProof())); } if (String(url).endsWith("/v1/client/environment-links")) { diff --git a/apps/mobile/src/features/cloud/linkEnvironment.ts b/apps/mobile/src/features/cloud/linkEnvironment.ts index 61ebad262371..bca1ac21bc75 100644 --- a/apps/mobile/src/features/cloud/linkEnvironment.ts +++ b/apps/mobile/src/features/cloud/linkEnvironment.ts @@ -50,7 +50,7 @@ export function normalizeRelayBaseUrl(value: string | null | undefined): string } function readRelayUrl(): string | null { - return resolveCloudPublicConfig().relayUrl; + return resolveCloudPublicConfig().relay.url; } export class CloudEnvironmentLinkError extends Data.TaggedError("CloudEnvironmentLinkError")<{ @@ -301,7 +301,7 @@ export function linkEnvironmentToCloud(input: { ), ); const environmentClient = yield* makeEnvironmentHttpApiClient(input.connection.httpBaseUrl); - const proof = yield* environmentClient.cloud + const proof = yield* environmentClient.connect .linkProof({ headers: { authorization: `Bearer ${localBearerToken}` }, payload: { @@ -336,7 +336,7 @@ export function linkEnvironmentToCloud(input: { link, }); - yield* environmentClient.cloud + yield* environmentClient.connect .relayConfig({ headers: { authorization: `Bearer ${localBearerToken}` }, payload: { diff --git a/apps/mobile/src/features/cloud/managedRelayState.ts b/apps/mobile/src/features/cloud/managedRelayState.ts index a1ecc8b4ea9f..3394a519fd6e 100644 --- a/apps/mobile/src/features/cloud/managedRelayState.ts +++ b/apps/mobile/src/features/cloud/managedRelayState.ts @@ -1,7 +1,6 @@ import { useAtomValue } from "@effect/atom-react"; import { createManagedRelayQueryManager, - ManagedRelayClient, managedRelaySessionAtom, readManagedRelaySnapshotState, } from "@t3tools/client-runtime"; @@ -9,23 +8,13 @@ import type { RelayClientEnvironmentRecord, RelayEnvironmentStatusResponse, } from "@t3tools/contracts/relay"; -import * as Context from "effect/Context"; -import * as Effect from "effect/Effect"; -import * as Layer from "effect/Layer"; import { AsyncResult, Atom } from "effect/unstable/reactivity"; import { useCallback } from "react"; -import { mobileRuntime } from "../../lib/runtime"; +import { mobileRuntimeContextLayer } from "../../lib/runtime"; import { appAtomRegistry } from "../../state/atom-registry"; -const managedRelayAtomRuntime = Atom.runtime( - Layer.effect( - ManagedRelayClient, - mobileRuntime.contextEffect.pipe( - Effect.map((context) => Context.get(context, ManagedRelayClient)), - ), - ), -); +const managedRelayAtomRuntime = Atom.runtime(mobileRuntimeContextLayer); export const managedRelayQueryManager = createManagedRelayQueryManager(managedRelayAtomRuntime); diff --git a/apps/mobile/src/features/cloud/publicConfig.test.ts b/apps/mobile/src/features/cloud/publicConfig.test.ts index ed5567fe3ae7..d5094d71b8b3 100644 --- a/apps/mobile/src/features/cloud/publicConfig.test.ts +++ b/apps/mobile/src/features/cloud/publicConfig.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it, vi } from "vite-plus/test"; -import { resolveCloudPublicConfig } from "./publicConfig"; +import { hasMobileTracingPublicConfig, resolveCloudPublicConfig } from "./publicConfig"; vi.mock("expo-constants", () => ({ default: { @@ -13,9 +13,18 @@ vi.mock("expo-constants", () => ({ describe("resolveCloudPublicConfig", () => { it("returns no cloud configuration for an unconfigured build", () => { expect(resolveCloudPublicConfig({})).toEqual({ - clerkPublishableKey: null, - clerkJwtTemplate: null, - relayUrl: null, + clerk: { + publishableKey: null, + jwtTemplate: null, + }, + relay: { + url: null, + }, + observability: { + tracesUrl: null, + tracesDataset: null, + tracesToken: null, + }, }); }); @@ -24,11 +33,25 @@ describe("resolveCloudPublicConfig", () => { resolveCloudPublicConfig({ clerk: { publishableKey: " pk_test_example ", jwtTemplate: " t3-relay " }, relay: { url: " https://relay.example.test/// " }, + observability: { + tracesUrl: " https://api.axiom.co/v1/traces ", + tracesDataset: " mobile-traces ", + tracesToken: " public-ingest-token ", + }, }), ).toEqual({ - clerkPublishableKey: "pk_test_example", - clerkJwtTemplate: "t3-relay", - relayUrl: "https://relay.example.test", + clerk: { + publishableKey: "pk_test_example", + jwtTemplate: "t3-relay", + }, + relay: { + url: "https://relay.example.test", + }, + observability: { + tracesUrl: "https://api.axiom.co/v1/traces", + tracesDataset: "mobile-traces", + tracesToken: "public-ingest-token", + }, }); }); @@ -39,9 +62,59 @@ describe("resolveCloudPublicConfig", () => { relay: { url: "http://relay.example.test" }, }), ).toEqual({ - clerkPublishableKey: "pk_test_example", - clerkJwtTemplate: "t3-relay", - relayUrl: null, + clerk: { + publishableKey: "pk_test_example", + jwtTemplate: "t3-relay", + }, + relay: { + url: null, + }, + observability: { + tracesUrl: null, + tracesDataset: null, + tracesToken: null, + }, }); }); + + it("rejects an insecure traces URL", () => { + expect( + resolveCloudPublicConfig({ + observability: { + tracesUrl: "http://api.axiom.co/v1/traces", + tracesDataset: "mobile-traces", + tracesToken: "public-ingest-token", + }, + }).observability, + ).toEqual({ + tracesUrl: null, + tracesDataset: "mobile-traces", + tracesToken: "public-ingest-token", + }); + }); + + it("keeps tracing disabled unless every public tracing value is configured", () => { + expect(hasMobileTracingPublicConfig(resolveCloudPublicConfig({}))).toBe(false); + expect( + hasMobileTracingPublicConfig( + resolveCloudPublicConfig({ + observability: { + tracesUrl: "https://api.axiom.co/v1/traces", + tracesDataset: "mobile-traces", + }, + }), + ), + ).toBe(false); + expect( + hasMobileTracingPublicConfig( + resolveCloudPublicConfig({ + observability: { + tracesUrl: "https://api.axiom.co/v1/traces", + tracesDataset: "mobile-traces", + tracesToken: "public-ingest-token", + }, + }), + ), + ).toBe(true); + }); }); diff --git a/apps/mobile/src/features/cloud/publicConfig.ts b/apps/mobile/src/features/cloud/publicConfig.ts index fcd0ceb27286..7a8822eb9db5 100644 --- a/apps/mobile/src/features/cloud/publicConfig.ts +++ b/apps/mobile/src/features/cloud/publicConfig.ts @@ -2,40 +2,92 @@ import Constants from "expo-constants"; import { relayClerkTokenOptions } from "@t3tools/shared/relayAuth"; import { normalizeSecureRelayUrl } from "@t3tools/shared/relayUrl"; -type ExpoExtra = Readonly> | undefined; - export interface CloudPublicConfig { - readonly clerkPublishableKey: string | null; - readonly clerkJwtTemplate: string | null; - readonly relayUrl: string | null; + readonly clerk: { + readonly publishableKey: string | null; + readonly jwtTemplate: string | null; + }; + readonly relay: { + readonly url: string | null; + }; + readonly observability: { + readonly tracesUrl: string | null; + readonly tracesDataset: string | null; + readonly tracesToken: string | null; + }; } +type UntrustedSection = { + readonly [Key in keyof T]?: unknown; +}; + +type ExpoExtra = + | { + readonly [Section in keyof CloudPublicConfig]?: UntrustedSection; + } + | undefined; + function trimNonEmpty(value: unknown): string | null { return typeof value === "string" && value.trim() ? value.trim() : null; } -export function resolveCloudPublicConfig(extra: ExpoExtra = Constants.expoConfig?.extra) { - const clerk = extra?.clerk as - | { readonly publishableKey?: unknown; readonly jwtTemplate?: unknown } - | undefined; - const relay = extra?.relay as { readonly url?: unknown } | undefined; +function normalizeSecureUrl(value: unknown): string | null { + const raw = trimNonEmpty(value); + if (raw === null) { + return null; + } + try { + const url = new URL(raw); + return url.protocol === "https:" ? url.toString() : null; + } catch { + return null; + } +} +export function resolveCloudPublicConfig(extra: ExpoExtra = Constants.expoConfig?.extra) { return { - clerkPublishableKey: trimNonEmpty(clerk?.publishableKey), - clerkJwtTemplate: trimNonEmpty(clerk?.jwtTemplate), - relayUrl: normalizeSecureRelayUrl(trimNonEmpty(relay?.url) ?? ""), + clerk: { + publishableKey: trimNonEmpty(extra?.clerk?.publishableKey), + jwtTemplate: trimNonEmpty(extra?.clerk?.jwtTemplate), + }, + relay: { + url: normalizeSecureRelayUrl(trimNonEmpty(extra?.relay?.url) ?? ""), + }, + observability: { + tracesUrl: normalizeSecureUrl(extra?.observability?.tracesUrl), + tracesDataset: trimNonEmpty(extra?.observability?.tracesDataset), + tracesToken: trimNonEmpty(extra?.observability?.tracesToken), + }, } satisfies CloudPublicConfig; } export function hasCloudPublicConfig(): boolean { const config = resolveCloudPublicConfig(); - return Boolean(config.clerkPublishableKey && config.clerkJwtTemplate && config.relayUrl); + return Boolean(config.clerk.publishableKey && config.clerk.jwtTemplate && config.relay.url); +} + +type Configured = { + readonly [Key in keyof T]: NonNullable; +}; + +type MobileTracingPublicConfig = Omit & { + readonly observability: Configured; +}; + +export function hasMobileTracingPublicConfig( + config: CloudPublicConfig = resolveCloudPublicConfig(), +): config is MobileTracingPublicConfig { + return Boolean( + config.observability.tracesUrl && + config.observability.tracesDataset && + config.observability.tracesToken, + ); } export function resolveRelayClerkTokenOptions() { - const { clerkJwtTemplate } = resolveCloudPublicConfig(); - if (!clerkJwtTemplate) { + const { jwtTemplate } = resolveCloudPublicConfig().clerk; + if (!jwtTemplate) { throw new Error("T3CODE_CLERK_JWT_TEMPLATE is not configured."); } - return relayClerkTokenOptions(clerkJwtTemplate); + return relayClerkTokenOptions(jwtTemplate); } diff --git a/apps/mobile/src/features/observability/mobileTracing.test.ts b/apps/mobile/src/features/observability/mobileTracing.test.ts new file mode 100644 index 000000000000..53bf41604774 --- /dev/null +++ b/apps/mobile/src/features/observability/mobileTracing.test.ts @@ -0,0 +1,52 @@ +import { expect, it } from "@effect/vitest"; +import * as Effect from "effect/Effect"; +import * as Layer from "effect/Layer"; +import { vi } from "vite-plus/test"; + +import { remoteHttpClientLayer } from "@t3tools/client-runtime"; + +import { makeMobileTracingLayer } from "./mobileTracing"; + +vi.mock("expo-constants", () => ({ + default: { + expoConfig: { + extra: {}, + }, + }, +})); + +it.effect("exports spans through the scoped mobile OTLP layer", () => { + const fetchFn = vi.fn(async () => new Response(null, { status: 202 })); + const tracingLayer = makeMobileTracingLayer( + { + tracesUrl: "https://api.axiom.test/v1/traces", + tracesDataset: "mobile-traces", + tracesToken: "public-ingest-token", + }, + { + appVariant: "test", + serviceVersion: "1.2.3", + }, + ).pipe(Layer.provide(remoteHttpClientLayer(fetchFn))); + const tracedApplication = Layer.effectDiscard( + Effect.void.pipe(Effect.withSpan("mobile.test.span")), + ).pipe(Layer.provide(tracingLayer)); + + return Effect.gen(function* () { + yield* Layer.build(tracedApplication); + + expect(fetchFn).not.toHaveBeenCalled(); + }).pipe( + Effect.scoped, + Effect.andThen( + Effect.sync(() => { + expect(fetchFn).toHaveBeenCalledOnce(); + const [url, init] = fetchFn.mock.calls[0]!; + expect(String(url)).toBe("https://api.axiom.test/v1/traces"); + expect(new Headers(init?.headers).get("authorization")).toBe("Bearer public-ingest-token"); + expect(new Headers(init?.headers).get("x-axiom-dataset")).toBe("mobile-traces"); + expect(new TextDecoder().decode(init?.body as Uint8Array)).toContain("mobile.test.span"); + }), + ), + ); +}); diff --git a/apps/mobile/src/features/observability/mobileTracing.ts b/apps/mobile/src/features/observability/mobileTracing.ts new file mode 100644 index 000000000000..32f3d9f94c3b --- /dev/null +++ b/apps/mobile/src/features/observability/mobileTracing.ts @@ -0,0 +1,60 @@ +import Constants from "expo-constants"; +import * as Layer from "effect/Layer"; +import type { HttpClient } from "effect/unstable/http"; +import { OtlpSerialization, OtlpTracer } from "effect/unstable/observability"; + +import { hasMobileTracingPublicConfig, resolveCloudPublicConfig } from "../cloud/publicConfig"; + +export interface MobileTracingConfig { + readonly tracesUrl: string; + readonly tracesDataset: string; + readonly tracesToken: string; +} + +export interface MobileTracingResource { + readonly serviceVersion?: string; + readonly appVariant: string; +} + +export function resolveMobileTracingConfig(): MobileTracingConfig | null { + const config = resolveCloudPublicConfig(); + if (!hasMobileTracingPublicConfig(config)) { + return null; + } + const { tracesUrl, tracesDataset, tracesToken } = config.observability; + return { tracesUrl, tracesDataset, tracesToken }; +} + +export function makeMobileTracingLayer( + config: MobileTracingConfig | null, + resource: MobileTracingResource, +): Layer.Layer { + if (config === null) { + return Layer.empty; + } + + return OtlpTracer.layer({ + url: config.tracesUrl, + headers: { + Authorization: `Bearer ${config.tracesToken}`, + "X-Axiom-Dataset": config.tracesDataset, + }, + resource: { + serviceName: "t3-mobile", + serviceVersion: resource.serviceVersion, + attributes: { + "service.runtime": "react-native", + "service.component": "mobile", + "deployment.environment.name": resource.appVariant, + }, + }, + }).pipe(Layer.provide(OtlpSerialization.layerJson)); +} + +export const mobileTracingLayer = makeMobileTracingLayer(resolveMobileTracingConfig(), { + serviceVersion: Constants.expoConfig?.version, + appVariant: + typeof Constants.expoConfig?.extra?.appVariant === "string" + ? Constants.expoConfig.extra.appVariant + : "unknown", +}); diff --git a/apps/mobile/src/lib/runtime.ts b/apps/mobile/src/lib/runtime.ts index 80083869d755..ce37a41e8ab3 100644 --- a/apps/mobile/src/lib/runtime.ts +++ b/apps/mobile/src/lib/runtime.ts @@ -6,19 +6,20 @@ import { remoteHttpClientLayer } from "@t3tools/client-runtime"; import { mobileCryptoLayer } from "../features/cloud/dpop"; import { mobileManagedRelayClientLayer } from "../features/cloud/managedRelayLayer"; import { resolveCloudPublicConfig } from "../features/cloud/publicConfig"; +import { mobileTracingLayer } from "../features/observability/mobileTracing"; function configuredRelayUrl(): string { - return resolveCloudPublicConfig().relayUrl ?? "http://relay.invalid"; + return resolveCloudPublicConfig().relay.url ?? "http://relay.invalid"; } const mobileHttpClientLayer = remoteHttpClientLayer(fetch); export const mobileRuntime = ManagedRuntime.make( - Layer.mergeAll( - mobileHttpClientLayer, - mobileCryptoLayer, - mobileManagedRelayClientLayer(configuredRelayUrl()).pipe( - Layer.provide(Layer.mergeAll(mobileHttpClientLayer, mobileCryptoLayer)), - ), + mobileManagedRelayClientLayer(configuredRelayUrl()).pipe( + Layer.provideMerge(mobileCryptoLayer), + Layer.provideMerge(mobileHttpClientLayer), + Layer.provideMerge(mobileTracingLayer.pipe(Layer.provide(mobileHttpClientLayer))), ), ); + +export const mobileRuntimeContextLayer = Layer.effectContext(mobileRuntime.contextEffect); diff --git a/apps/mobile/src/lib/threadActivity.test.ts b/apps/mobile/src/lib/threadActivity.test.ts index d03c89d2acf7..96d63fa5c777 100644 --- a/apps/mobile/src/lib/threadActivity.test.ts +++ b/apps/mobile/src/lib/threadActivity.test.ts @@ -42,9 +42,9 @@ function makeThread( proposedPlans: [], activities: [], checkpoints: [], - contextTrimPoints: [], session: null, ...input, + contextTrimPoints: input.contextTrimPoints ?? [], }; } diff --git a/apps/server/integration/OrchestrationEngineHarness.integration.ts b/apps/server/integration/OrchestrationEngineHarness.integration.ts index df3aec129a17..19a4b56417c9 100644 --- a/apps/server/integration/OrchestrationEngineHarness.integration.ts +++ b/apps/server/integration/OrchestrationEngineHarness.integration.ts @@ -35,6 +35,7 @@ import { ProjectionCheckpointRepository } from "../src/persistence/Services/Proj import { ProjectionPendingApprovalRepository } from "../src/persistence/Services/ProjectionPendingApprovals.ts"; import { makeAdapterRegistryMock } from "../src/provider/testUtils/providerAdapterRegistryMock.ts"; import { ProviderAdapterRegistry } from "../src/provider/Services/ProviderAdapterRegistry.ts"; +import { makeProviderRegistryLayer } from "../src/provider/testUtils/providerRegistryMock.ts"; import { ProviderSessionDirectoryLive } from "../src/provider/Layers/ProviderSessionDirectory.ts"; import { ServerSettingsService } from "../src/serverSettings.ts"; import { makeProviderServiceLive } from "../src/provider/Layers/ProviderService.ts"; @@ -54,8 +55,6 @@ import { RuntimeReceiptBusTest } from "../src/orchestration/Layers/RuntimeReceip import { OrchestrationReactorLive } from "../src/orchestration/Layers/OrchestrationReactor.ts"; import { ProviderCommandReactorLive } from "../src/orchestration/Layers/ProviderCommandReactor.ts"; import { ProviderRuntimeIngestionLive } from "../src/orchestration/Layers/ProviderRuntimeIngestion.ts"; -import { SeededWorkItemWritebackLive } from "../src/orchestration/Layers/SeededWorkItemWriteback.ts"; -import { SeededWorkItemWritebackReactorLive } from "../src/orchestration/Layers/SeededWorkItemWritebackReactor.ts"; import { OrchestrationEngineService, type OrchestrationEngineShape, @@ -295,6 +294,7 @@ export const makeOrchestrationIntegrationHarness = ( Layer.provide(AnalyticsService.layerTest), Layer.provide(providerEventLoggersLayer), ); + const providerRegistryLayer = makeProviderRegistryLayer(); const checkpointStoreLayer = CheckpointStoreLive.pipe(Layer.provide(VcsDriverRegistry.layer)); const projectionSnapshotQueryLayer = OrchestrationProjectionSnapshotQueryLive; @@ -329,23 +329,24 @@ export const makeOrchestrationIntegrationHarness = ( Layer.provideMerge(textGenerationLayer), Layer.provideMerge(serverSettingsLayer), ); - const vcsStatusBroadcasterLayer = Layer.succeed(VcsStatusBroadcaster, { - getStatus: () => Effect.die("getStatus should not be called in this test"), - refreshLocalStatus: () => - Effect.succeed({ - isRepo: true, - hasPrimaryRemote: false, - isDefaultRef: true, - refName: "main", - hasWorkingTreeChanges: false, - workingTree: { files: [], insertions: 0, deletions: 0 }, - }), - refreshStatus: () => Effect.die("refreshStatus should not be called in this test"), - streamStatus: () => Stream.empty, - }); - const checkpointDependencies = Layer.empty.pipe( + const checkpointReactorLayer = CheckpointReactorLive.pipe( Layer.provideMerge(runtimeServicesLayer), - Layer.provideMerge(vcsStatusBroadcasterLayer), + Layer.provideMerge( + Layer.succeed(VcsStatusBroadcaster, { + getStatus: () => Effect.die("getStatus should not be called in this test"), + refreshLocalStatus: () => + Effect.succeed({ + isRepo: true, + hasPrimaryRemote: false, + isDefaultRef: true, + refName: "main", + hasWorkingTreeChanges: false, + workingTree: { files: [], insertions: 0, deletions: 0 }, + }), + refreshStatus: () => Effect.die("refreshStatus should not be called in this test"), + streamStatus: () => Stream.empty, + }), + ), Layer.provideMerge( WorkspaceEntriesLive.pipe( Layer.provide(WorkspacePathsLive), @@ -356,18 +357,10 @@ export const makeOrchestrationIntegrationHarness = ( Layer.provideMerge(WorkspacePathsLive), Layer.provideMerge(VcsProcess.layer), ); - const checkpointReactorLayer = CheckpointReactorLive.pipe( - Layer.provide(checkpointDependencies), - ); - const seededWorkItemWritebackReactorLayer = SeededWorkItemWritebackReactorLive.pipe( - Layer.provideMerge(runtimeServicesLayer), - Layer.provide(SeededWorkItemWritebackLive), - ); const orchestrationReactorLayer = OrchestrationReactorLive.pipe( Layer.provideMerge(runtimeIngestionLayer), Layer.provideMerge(providerCommandReactorLayer), Layer.provideMerge(checkpointReactorLayer), - Layer.provideMerge(seededWorkItemWritebackReactorLayer), Layer.provideMerge( Layer.succeed(ThreadDeletionReactor, { start: () => Effect.void, @@ -384,12 +377,11 @@ export const makeOrchestrationIntegrationHarness = ( const layer = Layer.empty.pipe( Layer.provideMerge(runtimeServicesLayer), Layer.provideMerge(orchestrationReactorLayer), + Layer.provideMerge(providerRegistryLayer), Layer.provide(persistenceLayer), Layer.provideMerge(RepositoryIdentityResolverLive), Layer.provideMerge(ServerSettingsService.layerTest()), Layer.provideMerge(ServerConfig.layerTest(workspaceDir, rootDir)), - Layer.provideMerge(vcsStatusBroadcasterLayer), - Layer.provideMerge(VcsProcess.layer), Layer.provideMerge(NodeServices.layer), ); diff --git a/apps/server/integration/TestProviderAdapter.integration.ts b/apps/server/integration/TestProviderAdapter.integration.ts index 4fd916eff954..3ccf23ac462b 100644 --- a/apps/server/integration/TestProviderAdapter.integration.ts +++ b/apps/server/integration/TestProviderAdapter.integration.ts @@ -488,10 +488,6 @@ export const makeTestProviderAdapterHarness = (options?: MakeTestProviderAdapter sessions.clear(); }); - const compactThread: ProviderAdapterShape["compactThread"] = ( - _threadId, - ) => Effect.succeed({ summary: "compacted", durationMs: 0 }); - const adapter: ProviderAdapterShape = { provider, capabilities: { @@ -508,7 +504,14 @@ export const makeTestProviderAdapterHarness = (options?: MakeTestProviderAdapter hasSession, readThread, rollbackThread, - compactThread, + compactThread: () => + Effect.fail( + new ProviderAdapterValidationError({ + provider, + operation: "compactThread", + issue: "Test provider does not support compaction.", + }), + ), stopAll, streamEvents: Stream.fromQueue(runtimeEvents), }; diff --git a/apps/server/package.json b/apps/server/package.json index 6f56ab0a2095..2043a7459501 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -1,6 +1,6 @@ { "name": "t3", - "version": "0.0.24", + "version": "0.0.26", "license": "MIT", "repository": { "type": "git", @@ -42,7 +42,6 @@ "@types/node": "catalog:", "effect-acp": "workspace:*", "effect-codex-app-server": "workspace:*", - "playwright": "^1.58.2", "vite-plus": "catalog:" }, "engines": { diff --git a/apps/server/scratchpad/e2e-smoke.ts b/apps/server/scratchpad/e2e-smoke.ts index aa03d2eac99e..ced5e7e582bb 100644 --- a/apps/server/scratchpad/e2e-smoke.ts +++ b/apps/server/scratchpad/e2e-smoke.ts @@ -25,7 +25,6 @@ * - ws credential: tries /api/auth/websocket-ticket (?wsTicket) then * /api/auth/ws-token (?wsToken) * - RPC tags referenced as string literals (stable across the range) - * - SeededWorkItemWriteback layer imported dynamically (absent at range start) */ import * as NodeRuntime from "@effect/platform-node/NodeRuntime"; import * as NodeServices from "@effect/platform-node/NodeServices"; @@ -59,12 +58,6 @@ const BOOTSTRAP_TOKEN = "e2e-smoke-bootstrap-token"; const STEP_TIMEOUT_SECONDS = 20; const BOOT_TIMEOUT_SECONDS = 45; -// Optional at the start of the bisect range. -const seededWritebackLayer: Layer.Layer = - await import("../src/orchestration/Layers/SeededWorkItemWriteback.ts") - .then((m: any) => m.SeededWorkItemWritebackLive ?? Layer.empty) - .catch(() => Layer.empty); - const findFreePort = () => new Promise((resolve, reject) => { const srv = Net.createServer(); @@ -481,7 +474,5 @@ const program = Effect.gen(function* () { ); NodeRuntime.runMain( - program.pipe( - Effect.provide(Layer.mergeAll(NodeServices.layer, NetService.layer, seededWritebackLayer)), - ), + program.pipe(Effect.provide(NodeServices.layer), Effect.provide(NetService.layer)), ); diff --git a/apps/server/scratchpad/pr-review-agent-e2e.ts b/apps/server/scratchpad/pr-review-agent-e2e.ts deleted file mode 100644 index f84443b2131e..000000000000 --- a/apps/server/scratchpad/pr-review-agent-e2e.ts +++ /dev/null @@ -1,588 +0,0 @@ -/** - * PR Review E2E — boots the REAL server in-process, clones a real GitHub - * repo, fetches a PR, exercises the full review flow via WS RPC, then runs - * the background agent and checks that the response does NOT contain the - * "Agent process failed or timed out: undefined" bug. - * - * 1. clone — clones the repo from GitHub to a temp directory - * 2. boot — server starts and serves HTTP within 45s - * 3. auth — bootstrap credential -> session cookie - * 4. ws-ticket — short-lived WS credential issued - * 5. project — orchestration.dispatchCommand project.create - * 6. thread — orchestration.dispatchCommand thread.create - * 7. worktree — preparePullRequestThread (worktree mode) - * 8. diff — changeRequest.getPrDiff, parse file+line to comment on - * 9. comment — changeRequest.upsertReviewComment on a specific file:line - * 10. agent — changeRequest.runBackgroundAgent (real opencode run) - * 11. verify — assert no "undefined" in error messages - * 12. verify — check agent produced file changes in worktree - * 13. cleanup — interrupt server, delete temp dirs - * - * Usage: - * T3_TEST_PR_REPO=harrryyd/h-code T3_TEST_PR_NUMBER=121 node scratchpad/pr-review-agent-e2e.ts - * - * Requires: - * - gh CLI authenticated (`gh auth status`) - * - opencode installed and on PATH - * - * Exit code 0 = all steps passed. 1 = a step failed or HUNG (timeout). - */ - -import * as NodeRuntime from "@effect/platform-node/NodeRuntime"; -import * as NodeServices from "@effect/platform-node/NodeServices"; -import * as NodeSocket from "@effect/platform-node/NodeSocket"; -import * as NetService from "@t3tools/shared/Net"; -import * as Cause from "effect/Cause"; -import * as Duration from "effect/Duration"; -import * as Effect from "effect/Effect"; -import * as Exit from "effect/Exit"; -import * as Fiber from "effect/Fiber"; -import * as Layer from "effect/Layer"; -import * as Option from "effect/Option"; -import * as Stream from "effect/Stream"; -import { RpcClient, RpcSerialization } from "effect/unstable/rpc"; -import * as Socket from "effect/unstable/socket/Socket"; -import { WsRpcGroup } from "@t3tools/contracts"; -import * as child_process from "node:child_process"; -import * as Fs from "node:fs/promises"; -import * as Net from "node:net"; -import * as Os from "node:os"; -import * as PathMod from "node:path"; - -import { - deriveServerPaths, - ensureServerDirectories, - ServerConfig, - type ServerConfigShape, -} from "../src/config.ts"; -import { runServer } from "../src/server.ts"; - -const BOOTSTRAP_TOKEN = "e2e-pr-review-agent-bootstrap-token"; -const STEP_TIMEOUT_SECONDS = 30; -const BOOT_TIMEOUT_SECONDS = 45; -const AGENT_TIMEOUT_SECONDS = 120; // 2 minutes max for fast model - -const results: Array<{ - name: string; - ok: boolean; - detail: string; - ms: number; -}> = []; -class StepFailure extends Error {} - -const step = ( - name: string, - effect: Effect.Effect, - options?: { timeoutSeconds?: number; describe?: (value: A) => string }, -): Effect.Effect => - Effect.gen(function* () { - const timeoutSeconds = options?.timeoutSeconds ?? STEP_TIMEOUT_SECONDS; - const start = Date.now(); - const exit = yield* Effect.exit( - effect.pipe(Effect.timeoutOption(Duration.seconds(timeoutSeconds))), - ); - const ms = Date.now() - start; - if (Exit.isSuccess(exit)) { - if (Option.isNone(exit.value)) { - results.push({ - name, - ok: false, - detail: `HANG — no response after ${timeoutSeconds}s`, - ms, - }); - return undefined; - } - const value = exit.value.value; - results.push({ - name, - ok: true, - detail: options?.describe ? options.describe(value) : "ok", - ms, - }); - return value; - } - const detail = Cause.pretty(exit.cause).split("\n").slice(0, 12).join("\n"); - results.push({ name, ok: false, detail, ms }); - return undefined; - }); - -const fetchJson = ( - url: string, - init?: RequestInit, -): Effect.Effect<{ status: number; body: any; setCookie: string | null }, Error> => - Effect.tryPromise({ - try: async () => { - const response = await fetch(url, { - signal: AbortSignal.timeout(5000), - ...init, - }); - const text = await response.text(); - let body: any = null; - try { - body = text.length > 0 ? JSON.parse(text) : null; - } catch { - body = text; - } - return { - status: response.status, - body, - setCookie: response.headers.get("set-cookie"), - }; - }, - catch: (cause) => new Error(`fetch ${url} failed: ${cause}`), - }); - -const id = (prefix: string) => `${prefix}-${Math.random().toString(36).slice(2, 10)}`; - -const shellRun = (cmd: string, cwd: string): Promise => - new Promise((resolve, reject) => { - child_process.exec(cmd, { cwd, maxBuffer: 10 * 1024 * 1024 }, (err, stdout, stderr) => { - if (err) reject(new Error(`${cmd} failed: ${stderr || err.message}`)); - else resolve(stdout.trim()); - }); - }); - -const wsProtocolLayer = (wsUrl: string, cookie: string | null) => { - const webSocketConstructorLayer = Layer.succeed( - Socket.WebSocketConstructor, - (socketUrl: string, protocols?: string | string[]) => - new NodeSocket.NodeWS.WebSocket( - socketUrl, - protocols, - cookie ? { headers: { cookie } } : undefined, - ) as unknown as globalThis.WebSocket, - ); - return RpcClient.layerProtocolSocket().pipe( - Layer.provide(Socket.layerWebSocket(wsUrl).pipe(Layer.provide(webSocketConstructorLayer))), - Layer.provide(RpcSerialization.layerJson), - ); -}; - -const takeUntil = ( - stream: Stream.Stream, - predicate: (a: A) => boolean, - timeoutSeconds: number, -): Effect.Effect => - Effect.gen(function* () { - const chunkRef = { value: [] as A[] }; - yield* stream.pipe( - Stream.takeUntil((a) => { - chunkRef.value.push(a); - return predicate(a); - }), - Stream.runDrain, - Effect.timeout(Duration.seconds(timeoutSeconds)), - ); - return chunkRef.value; - }); - -const program = Effect.gen(function* () { - const repo = process.env.T3_TEST_PR_REPO; - const prNumberStr = process.env.T3_TEST_PR_NUMBER; - if (!repo || !prNumberStr) { - yield* Effect.die( - new Error( - "Set T3_TEST_PR_REPO=owner/repo and T3_TEST_PR_NUMBER= environment variables.\n" + - "Example: T3_TEST_PR_REPO=harrryyd/h-code T3_TEST_PR_NUMBER=121 node scratchpad/pr-review-agent-e2e.ts", - ), - ); - } - const prNumber = parseInt(prNumberStr, 10); - if (isNaN(prNumber) || prNumber < 1) { - yield* Effect.die( - new Error(`T3_TEST_PR_NUMBER must be a positive integer, got: ${prNumberStr}`), - ); - } - - yield* step( - "prereq: gh auth status", - Effect.tryPromise(() => shellRun("gh auth status", process.cwd())), - ); - yield* step( - "prereq: opencode --version", - Effect.tryPromise(() => shellRun("opencode --version", process.cwd())), - ); - - // ——————— Step 1: clone repo ——————— - const tmpDir = yield* Effect.promise(() => - Fs.mkdtemp(PathMod.join(Os.tmpdir(), "t3-pr-review-agent-e2e-")), - ); - const cloneUrl = `https://github.com/${repo}.git`; - yield* step( - "clone: git clone", - Effect.tryPromise(() => shellRun(`git clone "${cloneUrl}" "${tmpDir}"`, Os.tmpdir())), - ); - - const tempBranch = `t3-e2e-agent-${id("pr")}`; - yield* step( - "clone: fetch PR head", - Effect.tryPromise(() => - shellRun(`git fetch origin pull/${prNumber}/head:${tempBranch}`, tmpDir), - ), - ); - - // ——————— Step 2: boot server ——————— - const port = yield* Effect.promise( - () => - new Promise((resolve, reject) => { - const srv = Net.createServer(); - srv.once("error", reject); - srv.listen(0, "127.0.0.1", () => { - const address = srv.address() as any; - srv.close(() => resolve(address.port)); - }); - }), - ); - const baseDir = yield* Effect.promise(() => - Fs.mkdtemp(PathMod.join(Os.tmpdir(), "t3-pr-review-agent-base-")), - ); - const derivedPaths = yield* deriveServerPaths(baseDir, undefined); - yield* ensureServerDirectories(derivedPaths); - - const config: ServerConfigShape = { - logLevel: "Warn", - traceMinLevel: "Warn", - traceTimingEnabled: false, - traceBatchWindowMs: 200, - traceMaxBytes: 10 * 1024 * 1024, - traceMaxFiles: 2, - otlpTracesUrl: undefined, - otlpMetricsUrl: undefined, - otlpExportIntervalMs: 10_000, - otlpServiceName: "t3-server-pr-review-agent-e2e", - mode: "desktop", - port, - host: "127.0.0.1", - cwd: process.cwd(), - baseDir, - ...derivedPaths, - staticDir: undefined, - devUrl: undefined, - noBrowser: true, - startupPresentation: "browser", - desktopBootstrapToken: BOOTSTRAP_TOKEN, - autoBootstrapProjectFromCwd: false, - logWebSocketEvents: false, - tailscaleServeEnabled: false, - tailscaleServePort: 443, - }; - - const serverFiber = yield* Effect.forkDetach( - runServer.pipe(Effect.provideService(ServerConfig, config)), - ); - - const httpUrl = (pathname: string) => `http://127.0.0.1:${port}${pathname}`; - - const pollUntilServing = Effect.gen(function* () { - for (;;) { - const result = yield* Effect.exit(fetchJson(httpUrl("/api/auth/session"))); - if (Exit.isSuccess(result) && result.value.status === 200) return "serving"; - yield* Effect.sleep(Duration.millis(250)); - } - }); - const bootBody = yield* step( - "boot: server serves /api/auth/session", - Effect.raceFirst( - pollUntilServing, - Fiber.await(serverFiber).pipe( - Effect.flatMap((exit) => - Effect.die( - new Error( - `server fiber exited during boot: ${Exit.isFailure(exit) ? Cause.pretty(exit.cause) : "success"}`, - ), - ), - ), - ), - ), - { timeoutSeconds: BOOT_TIMEOUT_SECONDS }, - ); - if (bootBody === undefined) return; - - // ——————— Step 3: auth ——————— - const authenticate = Effect.gen(function* () { - const result = yield* fetchJson(httpUrl("/api/auth/browser-session"), { - method: "POST", - headers: { "content-type": "application/json" }, - body: JSON.stringify({ credential: BOOTSTRAP_TOKEN }), - }); - if (result.status !== 200 || !result.setCookie) { - return yield* Effect.fail( - new StepFailure(`auth failed: ${result.status} ${JSON.stringify(result.body)}`), - ); - } - return result.setCookie.split(";")[0]!; - }); - const cookieFull = yield* step("auth: bootstrap credential -> session cookie", authenticate); - if (cookieFull === undefined) return; - - const issueWsCredential = Effect.gen(function* () { - const result = yield* fetchJson(httpUrl("/api/auth/websocket-ticket"), { - method: "POST", - headers: { "content-type": "application/json", cookie: cookieFull }, - body: JSON.stringify({}), - }); - const value = result.body?.ticket; - if (result.status !== 200 || typeof value !== "string") { - return yield* Effect.fail( - new StepFailure(`ws ticket failed: ${result.status} ${JSON.stringify(result.body)}`), - ); - } - return value; - }); - const wsTicket = yield* step("ws-ticket: issue WebSocket credential", issueWsCredential); - if (wsTicket === undefined) return; - - const wsUrl = `ws://127.0.0.1:${port}/ws?wsTicket=${encodeURIComponent(wsTicket)}`; - - // ——————— Steps 4-9: WS RPC setup ——————— - const wsSetupResult = yield* Effect.scoped( - RpcClient.make(WsRpcGroup).pipe( - Effect.flatMap((rpcClient) => - Effect.gen(function* () { - const client = rpcClient as any; - const now = () => new Date().toISOString(); - const projectId = id("project"); - const threadId = id("thread"); - - yield* step( - "project: dispatch project.create", - client["orchestration.dispatchCommand"]({ - type: "project.create", - commandId: id("cmd"), - projectId, - title: "e2e pr review agent project", - workspaceRoot: tmpDir, - createdAt: now(), - }), - { describe: (r: any) => `sequence=${r?.sequence}` }, - ); - - yield* step( - "thread: dispatch thread.create", - client["orchestration.dispatchCommand"]({ - type: "thread.create", - commandId: id("cmd"), - threadId, - projectId, - title: "e2e pr review agent thread", - modelSelection: { - instanceId: "opencode", - model: "anthropic/claude-sonnet-4-20250514", - }, - runtimeMode: "full-access", - interactionMode: "default", - branch: null, - worktreePath: null, - createdAt: now(), - }), - { describe: (r: any) => `sequence=${r?.sequence}` }, - ); - - const threadPrepResult = yield* step( - "worktree: preparePullRequestThread", - client["git.preparePullRequestThread"]({ - cwd: tmpDir, - reference: `#${prNumber}`, - mode: "worktree", - threadId, - }), - { describe: (r: any) => `worktree=${r?.worktreePath ?? r?.branch}` }, - ); - if (threadPrepResult === undefined) return undefined; - const worktreePath: string = - threadPrepResult.worktreePath ?? threadPrepResult.branch; - - const prDiff = yield* step( - "diff: changeRequest.getPrDiff", - client["changeRequest.getPrDiff"]({ threadId, prNumber }), - { - describe: (r: any) => - `prHeadSHA=${r?.prHeadSHA?.slice(0, 8)}... diff=${r?.diff?.length ?? 0} bytes`, - }, - ); - if (prDiff === undefined) return undefined; - - const diffStr: string = prDiff.diff; - const fileMatch = diffStr.match(/^\+\+\+ b\/(.+)$/m); - const hunkMatch = diffStr.match(/@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@/); - const commentFile = fileMatch ? fileMatch[1]! : "README.md"; - const commentLine = hunkMatch ? parseInt(hunkMatch[1]!, 10) : undefined; - const prHeadSHA: string = prDiff.prHeadSHA; - - const commentId = id("comment"); - const commentBody = `e2e-agent smoke test comment — please ignore.`; - const reviewComment = { - id: commentId, - file: commentFile, - ...(typeof commentLine === "number" ? { line: commentLine } : {}), - commitSHA: prHeadSHA, - body: commentBody, - author: { login: "local" }, - createdAt: now(), - }; - - yield* step( - "comment: upsertReviewComment", - client["changeRequest.upsertReviewComment"]({ - threadId, - prNumber, - prHeadSHA, - comment: reviewComment, - }), - { - describe: (r: any) => `comments=${r?.comments?.length}, state=${r?.state}`, - }, - ); - - return { threadId, commentId, commentBody, commentFile, worktreePath, tmpDir }; - }), - ), - Effect.provide(wsProtocolLayer(wsUrl, cookieFull)), - ), - ); - if (wsSetupResult === undefined) return; - const { threadId, commentId, commentBody, commentFile, worktreePath, tmpDir: _tmpDir } = wsSetupResult; - - // ——————— Step 10: run background agent ——————— - console.log("\n [agent] Running background agent via WS RPC (may take up to 10 min)...\n"); - const agentEvents = yield* step( - "agent: changeRequest.runBackgroundAgent", - Effect.scoped( - RpcClient.make(WsRpcGroup).pipe( - Effect.flatMap((agentClient) => - Effect.gen(function* () { - const ac = agentClient as any; - const stream = ac["changeRequest.runBackgroundAgent"]({ - threadId, - prNumber, - commentId, - }); - const events = yield* takeUntil( - stream, - (e: any) => e.type === "done" || e.type === "error", - AGENT_TIMEOUT_SECONDS, - ); - return events; - }), - ), - Effect.provide(wsProtocolLayer(wsUrl, cookieFull)), - ), - ), - { - timeoutSeconds: AGENT_TIMEOUT_SECONDS + 30, - describe: (events: any[]) => { - const types = events.map((e: any) => e.type).join(","); - const done = events.some((e: any) => e.type === "done"); - const error = events.find((e: any) => e.type === "error"); - const statusEvents = events.filter((e: any) => e.type === "status"); - return done - ? `done (${events.length} events, types=[${types}])` - : error - ? `error: ${error.message}` - : `${events.length} events, types=[${types}]`; - }, - }, - ); - - if (agentEvents === undefined) return; - - // Log every event for diagnostic purposes - for (const ev of agentEvents) { - const prefix = ` [agent event] type=${ev.type}`; - if (ev.type === "text") { - console.log(`${prefix} content=${ev.content?.slice(0, 100)}`); - } else if (ev.type === "status") { - console.log(`${prefix} agentStatus=${ev.agentStatus}`); - } else if (ev.type === "error") { - console.log(`${prefix} message=${ev.message}`); - } else if (ev.type === "detail") { - console.log(`${prefix} title=${ev.title} content=${ev.content?.slice(0, 100)}`); - } - } - - // ——————— Step 11: assert no "undefined" in error messages ——————— - const errorEvent = agentEvents.find((e: any) => e.type === "error"); - const hasUndefinedError = - errorEvent?.message?.includes("undefined"); - - yield* step( - "verify: no undefined in error message", - Effect.sync(() => { - if (hasUndefinedError) { - throw new StepFailure( - `BUG REPRODUCED: Agent error message contains "undefined": "${errorEvent.message}"`, - ); - } - if (errorEvent) { - console.log( - ` [verify] Agent produced error (but not the undefined bug): ${errorEvent.message}`, - ); - } else { - console.log(` [verify] No error event produced by agent.`); - } - }), - { - describe: () => - hasUndefinedError - ? `"undefined" in error message (BUG!)` - : errorEvent - ? `error present but no "undefined" in message` - : "no error event", - }, - ); - - // ——————— Step 12: verify agent produced changes ——————— - const gitStatus = yield* step( - "verify: agent file changes in worktree", - Effect.tryPromise(() => shellRun(`git status --porcelain`, worktreePath)), - { - describe: (status: string) => - status.length > 0 - ? `changes: ${status.split("\n").slice(0, 3).join("; ")}...` - : "NO CHANGES (agent may have skipped due to trivia or error)", - }, - ); - - // ——————— Cleanup ——————— - yield* step( - "cleanup: delete temp branch", - Effect.tryPromise(() => - shellRun( - `git push origin --delete ${tempBranch} 2>/dev/null || true`, - tmpDir, - ), - ), - { describe: () => "done" }, - ); - - yield* Fiber.interrupt(serverFiber); -}).pipe( - Effect.onExit((exit) => - Effect.sync(() => { - const failed = results.filter((r) => !r.ok); - console.log("\n========== PR REVIEW AGENT E2E RESULTS =========="); - for (const r of results) { - console.log(`${r.ok ? "PASS" : "FAIL"} ${r.name} (${r.ms}ms)`); - if (!r.ok || r.detail !== "ok") { - console.log(` ${r.detail.split("\n").join("\n ")}`); - } - } - if (Exit.isFailure(exit)) { - console.log("PROGRAM FAILURE:"); - console.log(Cause.pretty(exit.cause)); - } - console.log("=================================================="); - const pass = failed.length === 0 && results.length > 0 && Exit.isSuccess(exit); - console.log( - pass - ? "RESULT: PASS" - : `RESULT: FAIL (${failed.length} failed step(s), ${results.length} recorded)`, - ); - process.exit(pass ? 0 : 1); - }), - ), -); - -NodeRuntime.runMain( - program.pipe(Effect.provide(Layer.mergeAll(NodeServices.layer, NetService.layer))), -); \ No newline at end of file diff --git a/apps/server/scratchpad/pr-review-browser-e2e.ts b/apps/server/scratchpad/pr-review-browser-e2e.ts deleted file mode 100644 index 0f51757a91f4..000000000000 --- a/apps/server/scratchpad/pr-review-browser-e2e.ts +++ /dev/null @@ -1,925 +0,0 @@ -/** - * PR Review Browser E2E — boots the REAL server in-process, clones a real - * GitHub repo, fetches a PR, exercises the full review flow via WS RPC, then - * opens a headless browser to click "Request AI" on a comment and waits for - * the agent response to appear in the frontend. - * - * 1. clone — clones the repo from GitHub to a temp directory - * 2. boot — server starts and serves HTTP within 45s - * 3. auth — bootstrap credential -> session cookie - * 4. ws-ticket — short-lived WS credential issued - * 5. project — orchestration.dispatchCommand project.create - * 6. thread — orchestration.dispatchCommand thread.create - * 7. worktree — preparePullRequestThread (worktree mode) - * 8. diff — changeRequest.getPrDiff, parse file+line to comment on - * 9. comment — changeRequest.upsertReviewComment on a specific file:line - * 10. browser — open headless browser, navigate to thread+diff view - * 11. click — click "Request AI response" button on the comment - * 12. wait — wait for agent response to appear in the DOM - * 13. verify — capture response text and status - * 14. cleanup — interrupt server, delete temp dirs - * - * Usage: - * T3_TEST_PR_REPO=harrryyd/h-code-test T3_TEST_PR_NUMBER=1 node scratchpad/pr-review-browser-e2e.ts - * - * Requires: - * - gh CLI authenticated (`gh auth status`) - * - opencode installed and on PATH - * - playwright browsers installed (`npx playwright install chromium`) - * - web app pre-built (`cd apps/web && bun run build`) - * - * The web app must be built before running this test. The server serves the - * built static files from apps/web/dist/ to provide the frontend in the browser. - * - * Exit code 0 = all steps passed. 1 = a step failed or HUNG (timeout). - */ - -import * as NodeRuntime from "@effect/platform-node/NodeRuntime"; -import * as NodeServices from "@effect/platform-node/NodeServices"; -import * as NodeSocket from "@effect/platform-node/NodeSocket"; -import * as NetService from "@t3tools/shared/Net"; -import * as Cause from "effect/Cause"; -import * as Duration from "effect/Duration"; -import * as Effect from "effect/Effect"; -import * as Exit from "effect/Exit"; -import * as Fiber from "effect/Fiber"; -import * as Layer from "effect/Layer"; -import * as Option from "effect/Option"; -import * as Stream from "effect/Stream"; -import { RpcClient, RpcSerialization } from "effect/unstable/rpc"; -import * as Socket from "effect/unstable/socket/Socket"; -import { WsRpcGroup } from "@t3tools/contracts"; -import { chromium } from "playwright"; -import * as child_process from "node:child_process"; -import * as Fs from "node:fs/promises"; -import * as Net from "node:net"; -import * as Os from "node:os"; -import * as PathMod from "node:path"; -import { fileURLToPath } from "node:url"; - -import { - deriveServerPaths, - ensureServerDirectories, - ServerConfig, - type ServerConfigShape, -} from "../src/config.ts"; -import { runServer } from "../src/server.ts"; - -const BOOTSTRAP_TOKEN = "e2e-pr-review-browser-bootstrap-token"; -const STEP_TIMEOUT_SECONDS = 30; -const BOOT_TIMEOUT_SECONDS = 45; -const AGENT_TIMEOUT_SECONDS = 600; // 10 minutes for real agent run -const BROWSER_NAV_TIMEOUT_SECONDS = 60; -const BROWSER_ELEMENT_TIMEOUT_SECONDS = 15; -const BROWSER_AGENT_WAIT_SECONDS = 610; - -// Pre-compute the web app dist directory at module load time so Node resolves -// it relative to this file's location before we enter the Effect runtime. -const WEB_DIST_DIR = PathMod.resolve( - PathMod.dirname(fileURLToPath(import.meta.url)), - "../../web/dist", -); - -const results: Array<{ - name: string; - ok: boolean; - detail: string; - ms: number; -}> = []; -class StepFailure extends Error {} - -const step = ( - name: string, - effect: Effect.Effect, - options?: { timeoutSeconds?: number; describe?: (value: A) => string }, -): Effect.Effect => - Effect.gen(function* () { - const timeoutSeconds = options?.timeoutSeconds ?? STEP_TIMEOUT_SECONDS; - const start = Date.now(); - const exit = yield* Effect.exit( - effect.pipe(Effect.timeoutOption(Duration.seconds(timeoutSeconds))), - ); - const ms = Date.now() - start; - if (Exit.isSuccess(exit)) { - if (Option.isNone(exit.value)) { - results.push({ - name, - ok: false, - detail: `HANG — no response after ${timeoutSeconds}s`, - ms, - }); - return undefined; - } - const value = exit.value.value; - results.push({ - name, - ok: true, - detail: options?.describe ? options.describe(value) : "ok", - ms, - }); - return value; - } - const detail = Cause.pretty(exit.cause).split("\n").slice(0, 12).join("\n"); - results.push({ name, ok: false, detail, ms }); - return undefined; - }); - -const fetchJson = ( - url: string, - init?: RequestInit, -): Effect.Effect<{ status: number; body: any; setCookie: string | null }, Error> => - Effect.tryPromise({ - try: async () => { - const response = await fetch(url, { - signal: AbortSignal.timeout(5000), - ...init, - }); - const text = await response.text(); - let body: any = null; - try { - body = text.length > 0 ? JSON.parse(text) : null; - } catch { - body = text; - } - return { - status: response.status, - body, - setCookie: response.headers.get("set-cookie"), - }; - }, - catch: (cause) => new Error(`fetch ${url} failed: ${cause}`), - }); - -const id = (prefix: string) => `${prefix}-${Math.random().toString(36).slice(2, 10)}`; - -const shellRun = (cmd: string, cwd: string): Promise => - new Promise((resolve, reject) => { - child_process.exec(cmd, { cwd, maxBuffer: 10 * 1024 * 1024 }, (err, stdout, stderr) => { - if (err) reject(new Error(`${cmd} failed: ${stderr || err.message}`)); - else resolve(stdout.trim()); - }); - }); - -const wsProtocolLayer = (wsUrl: string, cookie: string | null) => { - const webSocketConstructorLayer = Layer.succeed( - Socket.WebSocketConstructor, - (socketUrl: string, protocols?: string | string[]) => - new NodeSocket.NodeWS.WebSocket( - socketUrl, - protocols, - cookie ? { headers: { cookie } } : undefined, - ) as unknown as globalThis.WebSocket, - ); - return RpcClient.layerProtocolSocket().pipe( - Layer.provide(Socket.layerWebSocket(wsUrl).pipe(Layer.provide(webSocketConstructorLayer))), - Layer.provide(RpcSerialization.layerJson), - ); -}; - -/** - * Take from a stream until we see an event matching the predicate, then - * return all collected events. Times out after `timeoutSeconds`. - */ -const takeUntil = ( - stream: Stream.Stream, - predicate: (a: A) => boolean, - timeoutSeconds: number, -): Effect.Effect => - Effect.gen(function* () { - const chunkRef = { value: [] as A[] }; - yield* stream.pipe( - Stream.takeUntil((a) => { - chunkRef.value.push(a); - return predicate(a); - }), - Stream.runDrain, - Effect.timeout(Duration.seconds(timeoutSeconds)), - ); - return chunkRef.value; - }); - -function parseCookieNameValue( - cookieStr: string, -): { name: string; value: string } { - const eqIdx = cookieStr.indexOf("="); - return { - name: cookieStr.slice(0, eqIdx), - value: cookieStr.slice(eqIdx + 1), - }; -} - -const program = Effect.gen(function* () { - // ——————— Validate env vars ——————— - const repo = process.env.T3_TEST_PR_REPO; - const prNumberStr = process.env.T3_TEST_PR_NUMBER; - if (!repo || !prNumberStr) { - yield* Effect.die( - new Error( - "Set T3_TEST_PR_REPO=owner/repo and T3_TEST_PR_NUMBER= environment variables.\n" + - "Example: T3_TEST_PR_REPO=harrryyd/h-code-test T3_TEST_PR_NUMBER=1 node scratchpad/pr-review-browser-e2e.ts", - ), - ); - } - const prNumber = parseInt(prNumberStr, 10); - if (isNaN(prNumber) || prNumber < 1) { - yield* Effect.die( - new Error(`T3_TEST_PR_NUMBER must be a positive integer, got: ${prNumberStr}`), - ); - } - - // ——————— Check prerequisites ——————— - yield* step( - "prereq: gh auth status", - Effect.tryPromise(() => shellRun("gh auth status", process.cwd())), - ); - yield* step( - "prereq: opencode --version", - Effect.tryPromise(() => shellRun("opencode --version", process.cwd())), - ); - - // ——————— Step 1: clone repo ——————— - const tmpDir = yield* Effect.promise(() => - Fs.mkdtemp(PathMod.join(Os.tmpdir(), "t3-pr-review-browser-e2e-")), - ); - const cloneUrl = `https://github.com/${repo}.git`; - yield* step( - "clone: git clone", - Effect.tryPromise(() => shellRun(`git clone "${cloneUrl}" "${tmpDir}"`, Os.tmpdir())), - ); - - // Push a temp branch so we can interact with it as a PR head - const tempBranch = `t3-e2e-browser-${id("pr")}`; - yield* step( - "clone: fetch PR head", - Effect.tryPromise(() => - shellRun(`git fetch origin pull/${prNumber}/head:${tempBranch}`, tmpDir), - ), - ); - - // ——————— Step 2: boot server ——————— - const port = yield* Effect.promise( - () => - new Promise((resolve, reject) => { - const srv = Net.createServer(); - srv.once("error", reject); - srv.listen(0, "127.0.0.1", () => { - const address = srv.address() as any; - srv.close(() => resolve(address.port)); - }); - }), - ); - const baseDir = yield* Effect.promise(() => - Fs.mkdtemp(PathMod.join(Os.tmpdir(), "t3-pr-review-browser-base-")), - ); - const derivedPaths = yield* deriveServerPaths(baseDir, undefined); - yield* ensureServerDirectories(derivedPaths); - - // Resolve the web app dist directory relative to this script - // Pre-computed at module load time - const webDistDir = WEB_DIST_DIR; - - const config: ServerConfigShape = { - logLevel: "Warn", - traceMinLevel: "Warn", - traceTimingEnabled: false, - traceBatchWindowMs: 200, - traceMaxBytes: 10 * 1024 * 1024, - traceMaxFiles: 2, - otlpTracesUrl: undefined, - otlpMetricsUrl: undefined, - otlpExportIntervalMs: 10_000, - otlpServiceName: "t3-server-pr-review-browser-e2e", - mode: "desktop", - port, - host: "127.0.0.1", - cwd: process.cwd(), - baseDir, - ...derivedPaths, - staticDir: webDistDir, - devUrl: undefined, - noBrowser: true, - startupPresentation: "browser", - desktopBootstrapToken: BOOTSTRAP_TOKEN, - autoBootstrapProjectFromCwd: false, - logWebSocketEvents: false, - tailscaleServeEnabled: false, - tailscaleServePort: 443, - }; - - const serverFiber = yield* Effect.forkDetach( - runServer.pipe(Effect.provideService(ServerConfig, config)), - ); - - const httpUrl = (pathname: string) => `http://127.0.0.1:${port}${pathname}`; - - // Poll until /api/auth/session returns 200 - const pollUntilServing = Effect.gen(function* () { - for (;;) { - const result = yield* Effect.exit(fetchJson(httpUrl("/api/auth/session"))); - if (Exit.isSuccess(result) && result.value.status === 200) return "serving"; - yield* Effect.sleep(Duration.millis(250)); - } - }); - const bootBody = yield* step( - "boot: server serves /api/auth/session", - Effect.raceFirst( - pollUntilServing, - Fiber.await(serverFiber).pipe( - Effect.flatMap((exit) => - Effect.die( - new Error( - `server fiber exited during boot: ${Exit.isFailure(exit) ? Cause.pretty(exit.cause) : "success"}`, - ), - ), - ), - ), - ), - { timeoutSeconds: BOOT_TIMEOUT_SECONDS }, - ); - if (bootBody === undefined) return; - - // ——————— Step 3: auth ——————— - const authenticate = Effect.gen(function* () { - const result = yield* fetchJson(httpUrl("/api/auth/browser-session"), { - method: "POST", - headers: { "content-type": "application/json" }, - body: JSON.stringify({ credential: BOOTSTRAP_TOKEN }), - }); - if (result.status !== 200 || !result.setCookie) { - return yield* Effect.fail( - new StepFailure(`auth failed: ${result.status} ${JSON.stringify(result.body)}`), - ); - } - return result.setCookie.split(";")[0]!; - }); - const cookieFull = yield* step("auth: bootstrap credential -> session cookie", authenticate); - if (cookieFull === undefined) return; - const cookie = parseCookieNameValue(cookieFull); - - const issueWsCredential = Effect.gen(function* () { - const result = yield* fetchJson(httpUrl("/api/auth/websocket-ticket"), { - method: "POST", - headers: { "content-type": "application/json", cookie: cookieFull }, - body: JSON.stringify({}), - }); - const value = result.body?.ticket; - if (result.status !== 200 || typeof value !== "string") { - return yield* Effect.fail( - new StepFailure(`ws ticket failed: ${result.status} ${JSON.stringify(result.body)}`), - ); - } - return value; - }); - const wsTicket = yield* step("ws-ticket: issue WebSocket credential", issueWsCredential); - if (wsTicket === undefined) return; - - const wsUrl = `ws://127.0.0.1:${port}/ws?wsTicket=${encodeURIComponent(wsTicket)}`; - - // ——————— Steps 4-9: WS RPC setup ——————— - const wsSetupResult = yield* Effect.scoped( - RpcClient.make(WsRpcGroup).pipe( - Effect.flatMap((rpcClient) => - Effect.gen(function* () { - const client = rpcClient as any; - const now = () => new Date().toISOString(); - const projectId = id("project"); - const threadId = id("thread"); - - // Step 4: create project - yield* step( - "project: dispatch project.create", - client["orchestration.dispatchCommand"]({ - type: "project.create", - commandId: id("cmd"), - projectId, - title: "e2e pr review browser project", - workspaceRoot: tmpDir, - createdAt: now(), - }), - { describe: (r: any) => `sequence=${r?.sequence}` }, - ); - - // Step 5: create thread with worktree mode - yield* step( - "thread: dispatch thread.create", - client["orchestration.dispatchCommand"]({ - type: "thread.create", - commandId: id("cmd"), - threadId, - projectId, - title: "e2e pr review browser thread", - modelSelection: { - instanceId: "opencode", - model: "anthropic/claude-sonnet-4-20250514", - }, - runtimeMode: "full-access", - interactionMode: "default", - branch: null, - worktreePath: null, - createdAt: now(), - }), - { describe: (r: any) => `sequence=${r?.sequence}` }, - ); - - // Step 6: resolve PR and prepare worktree - const threadPrepResult = yield* step( - "worktree: preparePullRequestThread", - client["git.preparePullRequestThread"]({ - cwd: tmpDir, - reference: `#${prNumber}`, - mode: "worktree", - threadId, - }), - { describe: (r: any) => `worktree=${r?.worktreePath ?? r?.branch}` }, - ); - if (threadPrepResult === undefined) return undefined; - const worktreePath: string = - threadPrepResult.worktreePath ?? threadPrepResult.branch; - - // Step 7: get PR diff and pick a file+line to comment on - const prDiff = yield* step( - "diff: changeRequest.getPrDiff", - client["changeRequest.getPrDiff"]({ threadId, prNumber }), - { - describe: (r: any) => - `prHeadSHA=${r?.prHeadSHA?.slice(0, 8)}... diff=${r?.diff?.length ?? 0} bytes`, - }, - ); - if (prDiff === undefined) return undefined; - - const diffStr: string = prDiff.diff; - const fileMatch = diffStr.match(/^\+\+\+ b\/(.+)$/m); - const hunkMatch = diffStr.match(/@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@/); - const commentFile = fileMatch ? fileMatch[1]! : "README.md"; - const commentLine = hunkMatch ? parseInt(hunkMatch[1]!, 10) : undefined; - const prHeadSHA: string = prDiff.prHeadSHA; - - // Step 8: create a review comment - const commentId = id("comment"); - const commentBody = `e2e-browser smoke test comment — please ignore.`; - const reviewComment = { - id: commentId, - file: commentFile, - ...(typeof commentLine === "number" ? { line: commentLine } : {}), - commitSHA: prHeadSHA, - body: commentBody, - author: { login: "local" }, - createdAt: now(), - }; - - yield* step( - "comment: upsertReviewComment", - client["changeRequest.upsertReviewComment"]({ - threadId, - prNumber, - prHeadSHA, - comment: reviewComment, - }), - { - describe: (r: any) => `comments=${r?.comments?.length}, state=${r?.state}`, - }, - ); - - return { threadId, commentId, commentBody, commentFile, worktreePath, tmpDir, port }; - }), - ), - Effect.provide(wsProtocolLayer(wsUrl, cookieFull)), - ), - ); - if (wsSetupResult === undefined) return; - const { - threadId, - commentId, - commentBody, - commentFile, - worktreePath, - tmpDir: _tmpDir2, - port: _port2, - } = wsSetupResult; - - // ——————— Read environmentId ——————— - const readEnvironmentId = Effect.promise(() => - Fs.readFile(derivedPaths.environmentIdPath, "utf-8"), - ).pipe(Effect.map((s) => s.trim())); - const environmentId = yield* step( - "env: read environment-id", - readEnvironmentId, - { describe: (envId: string) => `${envId.slice(0, 8)}...` }, - ); - if (environmentId === undefined) return; - - // ——————— Step 10-12: Browser interaction ——————— - const browserUrl = `http://127.0.0.1:${port}/${environmentId}/${threadId}?diff=1`; - console.log(`\n [browser] Navigating to: ${browserUrl}\n`); - - const browserResult = yield* step( - "browser: click Request AI and wait for response", - Effect.gen(function* () { - // Launch browser inside the Effect generator via promise bridge - const result = yield* Effect.promise(async () => { - const browser = await chromium.launch({ headless: true }); - const context = await browser.newContext(); - await context.addCookies([ - { - name: cookie.name, - value: cookie.value, - domain: "127.0.0.1", - path: "/", - }, - ]); - - const page = await context.newPage(); - const consoleMsgs: string[] = []; - const wsEvents: string[] = []; - page.on("console", (msg) => { - consoleMsgs.push(`[${msg.type()}] ${msg.text().slice(0, 200)}`); - }); - page.on("pageerror", (err) => { - consoleMsgs.push(`[pageerror] ${err.message}`); - }); - page.on("websocket", (ws) => { - wsEvents.push(`[ws open] ${ws.url()}`); - ws.on("close", () => wsEvents.push(`[ws close] ${ws.url()}`)); - ws.on("socketerror", (err) => wsEvents.push(`[ws error] ${ws.url()} ${err}`)); - ws.on("framereceived", (payload) => { - const text = typeof payload.payload === "string" ? payload.payload : "binary"; - wsEvents.push(`[ws recv] ${text.slice(0, 200)}`); - }); - ws.on("framesent", (payload) => { - const text = typeof payload.payload === "string" ? payload.payload : "binary"; - wsEvents.push(`[ws send] ${text.slice(0, 200)}`); - }); - }); - - try { - // Navigate with ?diff=1. TanStack Router may re-encode, but the - // first parse should succeed and open the panel. - console.log(" [browser] Navigating..."); - await page.goto(browserUrl, { - waitUntil: "domcontentloaded", - timeout: BROWSER_NAV_TIMEOUT_SECONDS * 1000, - }); - console.log(` [browser] URL: ${page.url()}`); - - await page.screenshot({ - path: "/tmp/pr-review-browser-e2e-after-nav.png", - fullPage: true, - }); - - // Wait for the app shell to render - await page.waitForSelector("#root > *", { timeout: 15000 }); - console.log(" [browser] App shell rendered"); - - // Give WS time to connect and data to load - await page.waitForTimeout(8000); - console.log(` [browser] URL after wait: ${page.url()}`); - - // Take another screenshot - await page.screenshot({ - path: "/tmp/pr-review-browser-e2e-after-load.png", - fullPage: true, - }); - - // Dump full body text for debugging - const bodyTextAfterWait = await page.evaluate(() => - document.body.innerText.slice(0, 3000), - ); - console.log(` [browser] Body text after wait:\n${bodyTextAfterWait}`); -// Try multiple selectors for the diff panel content - console.log(" [browser] Looking for diff panel..."); - - // First check if the DiffPanel shell is present - const diffSelectors = [ - '[aria-label="PR diff"]', - '[aria-label="Checkpoint diff"]', - ".diff-comment-panel", - ]; - let panelFound = false; - for (const sel of diffSelectors) { - try { - await page.waitForSelector(sel, { timeout: 5000 }); - console.log(` [browser] Found selector: ${sel}`); - panelFound = true; - break; - } catch { - // try next - } - } - - if (!panelFound) { - const bodyText = await page.evaluate(() => - document.body.innerText.slice(0, 5000), - ); - const url = page.url(); - console.log(` [browser] Page URL: ${url}`); - console.log(` [browser] Console messages: ${consoleMsgs.slice(0, 10).join(" | ")}`); - console.log(` [browser] Body text:\n${bodyText}`); - await page.screenshot({ - path: "/tmp/pr-review-browser-e2e-no-panel.png", - fullPage: true, - }); - return { - ok: false, - detail: `Diff panel not found (no PR diff or Checkpoint diff toggle). Console: ${consoleMsgs.slice(0, 5).join("; ")}`, - agentResponse: null, - }; - } - - // Switch to PR review mode - console.log(" [browser] Switching to PR review mode..."); - try { - await page.click('[aria-label="PR diff"]', { timeout: 5000 }); - console.log(" [browser] Clicked PR diff toggle"); - await page.waitForTimeout(1000); - } catch { - console.log(" [browser] PR diff toggle not found or not clickable"); - } - - // Enter PR number - try { - const prInput = page.locator('[aria-label="PR number"]'); - await prInput.waitFor({ timeout: 5000 }); - await prInput.fill(String(prNumber)); - console.log(` [browser] Entered PR number: ${prNumber}`); - await page.waitForTimeout(2000); - } catch { - console.log(" [browser] Could not enter PR number"); - } - - // Wait for the diff comment panel to render - console.log(" [browser] Waiting for diff comment panel..."); - try { - await page.waitForSelector(".diff-comment-panel", { - timeout: 30000, - }); - console.log(" [browser] Diff comment panel found!"); - } catch { - // Dump full page state for debugging - const bodyText = await page.evaluate(() => - document.body.innerText.slice(0, 5000), - ); - const url = page.url(); - console.log(` [browser] Page URL: ${url}`); - console.log(` [browser] Console messages: ${consoleMsgs.slice(0, 10).join(" | ")}`); - console.log(` [browser] Body text:\n${bodyText}`); - await page.screenshot({ - path: "/tmp/pr-review-browser-e2e-no-panel.png", - fullPage: true, - }); - return { - ok: false, - detail: `Diff comment panel not found after switching to PR mode. Console: ${consoleMsgs.slice(0, 5).join("; ")}`, - agentResponse: null, - }; - } - - // Give React a moment to finish hydration / WS connection - await page.waitForTimeout(3000); - - // Take a pre-click screenshot - await page.screenshot({ - path: "/tmp/pr-review-browser-e2e-pre-click.png", - fullPage: true, - }); - -// Look for the "Request AI" button on the comment - console.log(" [browser] Looking for 'Request AI' button..."); - // Try both the file-level comment button and the inline annotation button - const requestAiBtn = page.locator( - 'button[title="Request AI response"], button[title="Request AI"]', - ); - - let btnCount = 0; - try { - btnCount = await requestAiBtn.count(); - } catch { - btnCount = 0; - } - console.log(` [browser] Found ${btnCount} 'Request AI' button(s)`); - - if (btnCount === 0) { - const bodyText = await page.evaluate(() => - document.body.innerText.slice(0, 3000), - ); - console.log(` [browser] Page body text (first 3k chars):\n${bodyText}`); - console.log(` [browser] Console: ${consoleMsgs.slice(-10).join(" | ")}`); - await page.screenshot({ - path: "/tmp/pr-review-browser-e2e-no-button.png", - fullPage: true, - }); - return { - ok: false, - detail: `Request AI button not found. Console: ${consoleMsgs.slice(0, 5).join("; ")}`, - agentResponse: null, - }; - } - - // Try dismissing any toast notifications that might block interaction - try { - const dismissBtn = page.locator('[data-slot="toast-close"]'); - const dismissCount = await dismissBtn.count(); - if (dismissCount > 0) { - await dismissBtn.first().click({ timeout: 3000 }); - console.log(" [browser] Dismissed toast notification"); - await page.waitForTimeout(500); - } - } catch { - // No dismiss button found, continue - } - - // Click the first "Request AI" button - console.log(" [browser] Clicking 'Request AI' button..."); - await requestAiBtn.first().click({ timeout: 5000 }); - console.log(" [browser] Clicked. Waiting for agent response..."); - - // Take a screenshot right after clicking - await page.screenshot({ - path: "/tmp/pr-review-browser-e2e-post-click.png", - fullPage: true, - }); - - // Wait for the agent to respond — look for "Done" status, error, or any agent response - let agentResult = "unknown"; - let responseText = ""; - const start = Date.now(); - - try { - // First, wait briefly for the button to disappear (agent starting) - await page.waitForFunction( - () => { - const text = document.body.innerText; - return ( - !text.includes("Request AI") || - text.includes("Done") || - text.includes("Failed") || - text.includes("AI Response") || - text.includes("Agent is working") || - text.includes("loader") // spinner icon - ); - }, - null as any, - { timeout: 30000 }, - ); - - // Now wait for the final result with a long timeout - console.log(" [browser] Agent started, waiting for completion..."); - page.setDefaultTimeout(45000); - await page.waitForFunction( - () => { - const text = document.body.innerText; - return ( - text.includes("Done") || - text.includes("Failed") || - /Agent process failed or timed out/i.test(text) || - /AI Response/.test(text) || - /Background agent error/i.test(text) - ); - }, - ); - page.setDefaultTimeout(30000); - - const bodyText = await page.evaluate(() => document.body.innerText); - - if (bodyText.includes("Done")) { - agentResult = "completed"; - } else if (/Agent process failed or timed out/i.test(bodyText)) { - agentResult = "error"; - } else if (/Background agent error/i.test(bodyText)) { - agentResult = "error"; - } else if (bodyText.includes("Failed")) { - agentResult = "failed"; - } else if (bodyText.includes("AI Response")) { - agentResult = "has_response"; - } - - // Extract the AI response portion - const aiResponseIdx = bodyText.indexOf("AI Response"); - if (aiResponseIdx >= 0) { - responseText = bodyText.slice(aiResponseIdx, aiResponseIdx + 2000); - } else { - const commentIdx = bodyText.indexOf(commentBody); - if (commentIdx >= 0) { - responseText = bodyText.slice(commentIdx, commentIdx + 2000); - } else { - responseText = bodyText.slice(0, 2000); - } - } - } catch (waitErr: any) { - const elapsed = Date.now() - start; - agentResult = "timeout"; - - try { - const bodyText = await page.evaluate(() => - document.body.innerText.slice(0, 5000), - ); - responseText = bodyText; - - if (bodyText.includes("Agent is working")) { - agentResult = "still_running"; - } else if (bodyText.includes("Done")) { - agentResult = "completed"; - } else if (bodyText.includes("Failed")) { - agentResult = "failed"; - } else if (bodyText.includes("AI Response")) { - agentResult = "has_response"; - } - } catch { - responseText = `Failed to read page: ${waitErr.message}`; - } - - console.log( - ` [browser] Wait error after ${elapsed}ms: ${waitErr.message?.slice(0, 200)}`, - ); - console.log( - ` [browser] Status: ${agentResult}, Console msgs: ${consoleMsgs.slice(-5).join(" | ") || "(none)"}`, - ); - console.log( - ` [browser] WS events (last 5): ${wsEvents.slice(-5).join(" | ") || "(none)"}`, - ); - console.log( - ` [browser] Body (first 1k):\n${responseText.slice(0, 1000)}`, - ); - } - - // Take final screenshot - const screenshotPath = - agentResult === "completed" || agentResult === "still_running" - ? "/tmp/pr-review-browser-e2e-success.png" - : "/tmp/pr-review-browser-e2e-failure.png"; - await page.screenshot({ path: screenshotPath, fullPage: true }); - - const ok = agentResult === "completed" || agentResult === "still_running"; - - return { - ok, - detail: `status=${agentResult}, responseLength=${responseText.length}, screenshots at /tmp/pr-review-browser-e2e-*.png`, - agentResponse: responseText, - agentResult, - }; - } finally { - await browser.close(); - } - }); - - if (!result.ok) { - yield* Effect.fail( - new StepFailure( - `Browser test failed: ${result.detail}\nResponse: ${result.agentResponse?.slice(0, 500) ?? "none"}`, - ), - ); - } - return result; - }), - { - timeoutSeconds: 90, // debug: short timeout - describe: (r: any) => r.detail, - }, - ); - - console.log( - `\n [browser] Agent response:\n ${(browserResult?.agentResponse ?? "N/A").slice(0, 500)}`, - ); - - // ——————— Cleanup ——————— - yield* step( - "cleanup: delete temp branch", - Effect.tryPromise(() => - shellRun( - `git push origin --delete ${tempBranch} 2>/dev/null || true`, - wsSetupResult.tmpDir, - ), - ), - { describe: () => "done" }, - ); - - yield* Fiber.interrupt(serverFiber); -}).pipe( - Effect.onExit((exit) => - Effect.sync(() => { - const failed = results.filter((r) => !r.ok); - console.log("\n========== PR REVIEW BROWSER E2E RESULTS =========="); - for (const r of results) { - console.log(`${r.ok ? "PASS" : "FAIL"} ${r.name} (${r.ms}ms)`); - if (!r.ok || r.detail !== "ok") { - console.log(` ${r.detail.split("\n").join("\n ")}`); - } - } - if (Exit.isFailure(exit)) { - console.log("PROGRAM FAILURE:"); - console.log(Cause.pretty(exit.cause)); - } - console.log("==================================================="); - const pass = failed.length === 0 && results.length > 0 && Exit.isSuccess(exit); - console.log( - pass - ? "RESULT: PASS" - : `RESULT: FAIL (${failed.length} failed step(s), ${results.length} recorded)`, - ); - process.exit(pass ? 0 : 1); - }), - ), -); - -NodeRuntime.runMain( - program.pipe(Effect.provide(Layer.mergeAll(NodeServices.layer, NetService.layer))), -); diff --git a/apps/server/scratchpad/pr-review-e2e.ts b/apps/server/scratchpad/pr-review-e2e.ts deleted file mode 100644 index 83331ffeb178..000000000000 --- a/apps/server/scratchpad/pr-review-e2e.ts +++ /dev/null @@ -1,574 +0,0 @@ -/** - * PR Review E2E smoke harness — boots the REAL server in-process, clones a - * real GitHub repo, fetches a PR, and exercises the full review flow: - * - * 1. clone — clones the repo from GitHub to a temp directory - * 2. boot — server starts and serves HTTP within 45s - * 3. auth — bootstrap credential -> session cookie - * 4. ws-ticket — short-lived WS credential issued - * 5. project — orchestration.dispatchCommand project.create - * 6. thread — orchestration.dispatchCommand thread.create - * 7. worktree — preparePullRequestThread (worktree mode) - * 8. diff — changeRequest.getPrDiff, parse file+line to comment on - * 9. comment — changeRequest.upsertReviewComment on a specific file:line - * 10. submit — changeRequest.submitReview (gh api inline comments) - * 11. agent — changeRequest.runBackgroundAgent (real opencode run) - * 12. verify — check agent produced file changes in worktree - * 13. cleanup — interrupt server, delete temp dirs - * - * Usage: - * T3_TEST_PR_REPO=harrryyd/h-code-test T3_TEST_PR_NUMBER=1 node scratchpad/pr-review-e2e.ts - * - * Requires: - * - gh CLI authenticated (`gh auth status`) - * - opencode installed and on PATH - * - A real GitHub PR with at least one file changed - * - * Exit code 0 = all steps passed. 1 = a step failed or HUNG (timeout). - */ - -import * as NodeRuntime from "@effect/platform-node/NodeRuntime"; -import * as NodeServices from "@effect/platform-node/NodeServices"; -import * as NodeSocket from "@effect/platform-node/NodeSocket"; -import * as NetService from "@t3tools/shared/Net"; -import * as Cause from "effect/Cause"; -import * as Duration from "effect/Duration"; -import * as Effect from "effect/Effect"; -import * as Exit from "effect/Exit"; -import * as Fiber from "effect/Fiber"; -import * as Layer from "effect/Layer"; -import * as Option from "effect/Option"; -import * as Stream from "effect/Stream"; -import { RpcClient, RpcSerialization } from "effect/unstable/rpc"; -import * as Socket from "effect/unstable/socket/Socket"; -import { WsRpcGroup } from "@t3tools/contracts"; -import * as child_process from "node:child_process"; -import * as Fs from "node:fs/promises"; -import * as Os from "node:os"; -import * as PathMod from "node:path"; - -import { - deriveServerPaths, - ensureServerDirectories, - ServerConfig, - type ServerConfigShape, -} from "../src/config.ts"; -import { runServer } from "../src/server.ts"; - -const BOOTSTRAP_TOKEN = "e2e-pr-review-bootstrap-token"; -const STEP_TIMEOUT_SECONDS = 30; -const BOOT_TIMEOUT_SECONDS = 45; -const AGENT_TIMEOUT_SECONDS = 600; // 10 minutes for real agent run - -const results: Array<{ - name: string; - ok: boolean; - detail: string; - ms: number; -}> = []; -class StepFailure extends Error {} - -const step = ( - name: string, - effect: Effect.Effect, - options?: { timeoutSeconds?: number; describe?: (value: A) => string }, -): Effect.Effect => - Effect.gen(function* () { - const timeoutSeconds = options?.timeoutSeconds ?? STEP_TIMEOUT_SECONDS; - const start = Date.now(); - const exit = yield* Effect.exit( - effect.pipe(Effect.timeoutOption(Duration.seconds(timeoutSeconds))), - ); - const ms = Date.now() - start; - if (Exit.isSuccess(exit)) { - if (Option.isNone(exit.value)) { - results.push({ - name, - ok: false, - detail: `HANG — no response after ${timeoutSeconds}s`, - ms, - }); - return undefined; - } - const value = exit.value.value; - results.push({ - name, - ok: true, - detail: options?.describe ? options.describe(value) : "ok", - ms, - }); - return value; - } - const detail = Cause.pretty(exit.cause).split("\n").slice(0, 12).join("\n"); - results.push({ name, ok: false, detail, ms }); - return undefined; - }); - -const fetchJson = ( - url: string, - init?: RequestInit, -): Effect.Effect<{ status: number; body: any; setCookie: string | null }, Error> => - Effect.tryPromise({ - try: async () => { - const response = await fetch(url, { - signal: AbortSignal.timeout(5000), - ...init, - }); - const text = await response.text(); - let body: any = null; - try { - body = text.length > 0 ? JSON.parse(text) : null; - } catch { - body = text; - } - return { - status: response.status, - body, - setCookie: response.headers.get("set-cookie"), - }; - }, - catch: (cause) => new Error(`fetch ${url} failed: ${cause}`), - }); - -const id = (prefix: string) => `${prefix}-${Math.random().toString(36).slice(2, 10)}`; - -const shellRun = (cmd: string, cwd: string): Promise => - new Promise((resolve, reject) => { - child_process.exec(cmd, { cwd, maxBuffer: 10 * 1024 * 1024 }, (err, stdout, stderr) => { - if (err) reject(new Error(`${cmd} failed: ${stderr || err.message}`)); - else resolve(stdout.trim()); - }); - }); - -const wsProtocolLayer = (wsUrl: string, cookie: string | null) => { - const webSocketConstructorLayer = Layer.succeed( - Socket.WebSocketConstructor, - (socketUrl: string, protocols?: string | string[]) => - new NodeSocket.NodeWS.WebSocket( - socketUrl, - protocols, - cookie ? { headers: { cookie } } : undefined, - ) as unknown as globalThis.WebSocket, - ); - return RpcClient.layerProtocolSocket().pipe( - Layer.provide(Socket.layerWebSocket(wsUrl).pipe(Layer.provide(webSocketConstructorLayer))), - Layer.provide(RpcSerialization.layerJson), - ); -}; - -/** - * Take from a stream until we see an event matching the predicate, then - * return all collected events. Times out after `timeoutSeconds`. - */ -const takeUntil = ( - stream: Stream.Stream, - predicate: (a: A) => boolean, - timeoutSeconds: number, -): Effect.Effect => - Effect.gen(function* () { - const chunkRef = { value: [] as A[] }; - yield* stream.pipe( - Stream.takeUntil((a) => { - chunkRef.value.push(a); - return predicate(a); - }), - Stream.runDrain, - Effect.timeout(Duration.seconds(timeoutSeconds)), - ); - return chunkRef.value; - }); - -const program = Effect.gen(function* () { - // ——————— Validate env vars ——————— - const repo = process.env.T3_TEST_PR_REPO; - const prNumberStr = process.env.T3_TEST_PR_NUMBER; - if (!repo || !prNumberStr) { - yield* Effect.die( - new Error( - "Set T3_TEST_PR_REPO=owner/repo and T3_TEST_PR_NUMBER= environment variables.\n" + - "Example: T3_TEST_PR_REPO=harrryyd/h-code-test T3_TEST_PR_NUMBER=1 node scratchpad/pr-review-e2e.ts", - ), - ); - } - const prNumber = parseInt(prNumberStr, 10); - if (isNaN(prNumber) || prNumber < 1) { - yield* Effect.die( - new Error(`T3_TEST_PR_NUMBER must be a positive integer, got: ${prNumberStr}`), - ); - } - - // ——————— Check prerequisites ——————— - yield* step( - "prereq: gh auth status", - Effect.tryPromise(() => shellRun("gh auth status", process.cwd())), - ); - yield* step( - "prereq: opencode --version", - Effect.tryPromise(() => shellRun("opencode --version", process.cwd())), - ); - - // ——————— Step 1: clone repo ——————— - const tmpDir = yield* Effect.promise(() => - Fs.mkdtemp(PathMod.join(Os.tmpdir(), "t3-pr-review-e2e-")), - ); - const cloneUrl = `https://github.com/${repo}.git`; - yield* step( - "clone: git clone", - Effect.tryPromise(() => shellRun(`git clone --depth 1 "${cloneUrl}" "${tmpDir}"`, Os.tmpdir())), - ); - - // Push a temp branch so we can interact with it as a PR head - const tempBranch = `t3-e2e-${id("pr")}`; - yield* step( - "clone: fetch PR head", - Effect.tryPromise(() => - shellRun(`git fetch origin pull/${prNumber}/head:${tempBranch}`, tmpDir), - ), - ); - - // ——————— Step 2: boot server ——————— - const port = yield* Effect.promise( - () => - new Promise((resolve, reject) => { - const srv = require("node:net").createServer(); - srv.once("error", reject); - srv.listen(0, "127.0.0.1", () => { - const address = srv.address() as any; - srv.close(() => resolve(address.port)); - }); - }), - ); - const baseDir = yield* Effect.promise(() => - Fs.mkdtemp(PathMod.join(Os.tmpdir(), "t3-pr-review-base-")), - ); - const derivedPaths = yield* deriveServerPaths(baseDir, undefined); - yield* ensureServerDirectories(derivedPaths); - const config: ServerConfigShape = { - logLevel: "Warn", - traceMinLevel: "Warn", - traceTimingEnabled: false, - traceBatchWindowMs: 200, - traceMaxBytes: 10 * 1024 * 1024, - traceMaxFiles: 2, - otlpTracesUrl: undefined, - otlpMetricsUrl: undefined, - otlpExportIntervalMs: 10_000, - otlpServiceName: "t3-server-pr-review-e2e", - mode: "desktop", - port, - host: "127.0.0.1", - cwd: process.cwd(), - baseDir, - ...derivedPaths, - staticDir: undefined, - devUrl: undefined, - noBrowser: true, - startupPresentation: "browser", - desktopBootstrapToken: BOOTSTRAP_TOKEN, - autoBootstrapProjectFromCwd: false, - logWebSocketEvents: false, - tailscaleServeEnabled: false, - tailscaleServePort: 443, - }; - - const serverFiber = yield* Effect.forkDetach( - runServer.pipe(Effect.provideService(ServerConfig, config)), - ); - - const httpUrl = (pathname: string) => `http://127.0.0.1:${port}${pathname}`; - - // Poll until /api/auth/session returns 200 - const pollUntilServing = Effect.gen(function* () { - for (;;) { - const result = yield* Effect.exit(fetchJson(httpUrl("/api/auth/session"))); - if (Exit.isSuccess(result) && result.value.status === 200) return; - yield* Effect.sleep(Duration.millis(250)); - } - }); - const bootBody = yield* step( - "boot: server serves /api/auth/session", - Effect.raceFirst( - pollUntilServing, - Fiber.await(serverFiber).pipe( - Effect.flatMap((exit) => - Effect.die( - new Error( - `server fiber exited during boot: ${Exit.isFailure(exit) ? Cause.pretty(exit.cause) : "success"}`, - ), - ), - ), - ), - ), - { timeoutSeconds: BOOT_TIMEOUT_SECONDS }, - ); - if (bootBody === undefined) return; - - // ——————— Step 3: auth ——————— - const authenticate = Effect.gen(function* () { - const result = yield* fetchJson(httpUrl("/api/auth/browser-session"), { - method: "POST", - headers: { "content-type": "application/json" }, - body: JSON.stringify({ credential: BOOTSTRAP_TOKEN }), - }); - if (result.status !== 200 || !result.setCookie) { - return yield* Effect.fail( - new StepFailure(`auth failed: ${result.status} ${JSON.stringify(result.body)}`), - ); - } - return result.setCookie.split(";")[0]!; - }); - const cookie = yield* step("auth: bootstrap credential -> session cookie", authenticate); - if (cookie === undefined) return; - - const issueWsCredential = Effect.gen(function* () { - const result = yield* fetchJson(httpUrl("/api/auth/websocket-ticket"), { - method: "POST", - headers: { "content-type": "application/json", cookie }, - body: JSON.stringify({}), - }); - const value = result.body?.ticket; - if (result.status !== 200 || typeof value !== "string") { - return yield* Effect.fail( - new StepFailure(`ws ticket failed: ${result.status} ${JSON.stringify(result.body)}`), - ); - } - return value; - }); - const wsTicket = yield* step("ws-ticket: issue WebSocket credential", issueWsCredential); - if (wsTicket === undefined) return; - - const wsUrl = `ws://127.0.0.1:${port}/ws?wsTicket=${encodeURIComponent(wsTicket)}`; - - // ——————— Steps 4-12: WS RPC ——————— - yield* Effect.scoped( - RpcClient.make(WsRpcGroup).pipe( - Effect.flatMap((rpcClient) => - Effect.gen(function* () { - const client = rpcClient as any; - const now = () => new Date().toISOString(); - const projectId = id("project"); - const threadId = id("thread"); - - // Step 4: create project - yield* step( - "project: dispatch project.create", - client["orchestration.dispatchCommand"]({ - type: "project.create", - commandId: id("cmd"), - projectId, - title: "e2e pr review project", - workspaceRoot: tmpDir, - createdAt: now(), - }), - { describe: (r: any) => `sequence=${r?.sequence}` }, - ); - - // Step 5: create thread with worktree mode - yield* step( - "thread: dispatch thread.create", - client["orchestration.dispatchCommand"]({ - type: "thread.create", - commandId: id("cmd"), - threadId, - projectId, - title: "e2e pr review thread", - modelSelection: { - instanceId: "opencode", - model: "anthropic/claude-sonnet-4-20250514", - }, - runtimeMode: "full-access", - interactionMode: "default", - branch: null, - worktreePath: null, - createdAt: now(), - }), - { describe: (r: any) => `sequence=${r?.sequence}` }, - ); - - // Step 6: resolve PR and prepare worktree - const threadPrepResult = yield* step( - "worktree: preparePullRequestThread", - client["git.preparePullRequestThread"]({ - cwd: tmpDir, - reference: `#${prNumber}`, - mode: "worktree", - threadId, - }), - { describe: (r: any) => `worktree=${r?.worktreePath ?? r?.branch}` }, - ); - if (threadPrepResult === undefined) return; - const worktreePath: string = threadPrepResult.worktreePath ?? threadPrepResult.branch; - - // Step 7: get PR diff and pick a file+line to comment on - const prDiff = yield* step( - "diff: changeRequest.getPrDiff", - client["changeRequest.getPrDiff"]({ threadId, prNumber }), - { - describe: (r: any) => - `prHeadSHA=${r?.prHeadSHA?.slice(0, 8)}... diff=${r?.diff?.length ?? 0} bytes`, - }, - ); - if (prDiff === undefined) return; - - // Parse the diff to find a changed file and an added line number. - // Git diff format: "@@ -oldStart,oldLines +newStart,newLines @@" - const diffStr: string = prDiff.diff; - const fileMatch = diffStr.match(/^\+\+\+ b\/(.+)$/m); - const hunkMatch = diffStr.match(/@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@/); - const commentFile = fileMatch ? fileMatch[1]! : "README.md"; - let commentLine: number | undefined = hunkMatch ? parseInt(hunkMatch[1]!, 10) : undefined; - const prHeadSHA: string = prDiff.prHeadSHA; - - // Step 8: create a review comment - const commentId = id("comment"); - const commentBody = `e2e-smoke test comment — please ignore.`; - const reviewComment = { - id: commentId, - file: commentFile, - ...(typeof commentLine === "number" ? { line: commentLine } : {}), - commitSHA: prHeadSHA, - body: commentBody, - author: { login: "local" }, - createdAt: now(), - }; - - yield* step( - "comment: upsertReviewComment", - client["changeRequest.upsertReviewComment"]({ - threadId, - prNumber, - prHeadSHA, - comment: reviewComment, - }), - { - describe: (r: any) => `comments=${r?.comments?.length}, state=${r?.state}`, - }, - ); - - // Step 9: submit review - const submittedDraft = yield* step( - "submit: changeRequest.submitReview", - client["changeRequest.submitReview"]({ threadId, prNumber }), - { - describe: (r: any) => `state=${r?.state}, comments=${r?.comments?.length}`, - }, - ); - if (submittedDraft === undefined) return; - - // Verify review appears on GitHub - yield* step( - "verify: review visible on GitHub", - Effect.tryPromise(() => - shellRun(`gh api repos/${repo}/pulls/${prNumber}/reviews --jq '.[0].body'`, tmpDir), - ), - { - describe: (body: string) => `review body length=${body.length}...`, - }, - ); - - // Step 10: run background agent (real opencode, ~2-5 min) - console.log("\n [agent] Running real background agent (may take up to 10 min)...\n"); - const [agentEvents] = yield* step( - "agent: changeRequest.runBackgroundAgent", - Effect.scoped( - RpcClient.make(WsRpcGroup).pipe( - Effect.flatMap((agentClient) => - Effect.gen(function* () { - const ac = agentClient as any; - const stream = ac["changeRequest.runBackgroundAgent"]({ - threadId, - prNumber, - commentId, - }); - const events = yield* takeUntil( - stream, - (e: any) => e.type === "done" || e.type === "error", - AGENT_TIMEOUT_SECONDS, - ); - return events; - }), - ), - Effect.provide(wsProtocolLayer(wsUrl, cookie)), - ), - ), - { - timeoutSeconds: AGENT_TIMEOUT_SECONDS + 30, - describe: (events: any[]) => { - const types = events.map((e: any) => e.type).join(","); - const done = events.some((e: any) => e.type === "done"); - const error = events.find((e: any) => e.type === "error"); - return done - ? `events=done (${events.length} total)` - : error - ? `error: ${error.message}` - : `events=${types} (${events.length} total)`; - }, - }, - ); - if (agentEvents === undefined) return; - - // Step 11: verify agent produced changes - const gitStatus = yield* step( - "verify: agent file changes", - Effect.tryPromise(() => shellRun(`git status --porcelain`, worktreePath)), - { - describe: (status: string) => - status.length > 0 - ? `changes: ${status.split("\n").slice(0, 3).join("; ")}...` - : "NO CHANGES", - }, - ); - if (gitStatus === undefined) return; - - if (gitStatus.length === 0) { - console.log( - "\n WARNING: Agent produced no file changes. The PR diff may be too large or the comment is trivially resolved.\n", - ); - } - - // Step 10b: clean up agent worktree branch on remote - yield* step( - "cleanup: delete temp branch", - Effect.tryPromise(() => - shellRun(`git push origin --delete ${tempBranch} 2>/dev/null || true`, tmpDir), - ), - { describe: () => "done" }, - ); - }), - ), - Effect.provide(wsProtocolLayer(wsUrl, cookie)), - ), - ); - - // ——————— Step 12: teardown ——————— - yield* Fiber.interrupt(serverFiber); -}).pipe( - Effect.onExit((exit) => - Effect.sync(() => { - const failed = results.filter((r) => !r.ok); - console.log("\n========== PR REVIEW E2E RESULTS =========="); - for (const r of results) { - console.log(`${r.ok ? "PASS" : "FAIL"} ${r.name} (${r.ms}ms)`); - if (!r.ok || r.detail !== "ok") { - console.log(` ${r.detail.split("\n").join("\n ")}`); - } - } - if (Exit.isFailure(exit)) { - console.log("PROGRAM FAILURE:"); - console.log(Cause.pretty(exit.cause)); - } - console.log("============================================"); - const pass = failed.length === 0 && results.length > 0 && Exit.isSuccess(exit); - console.log( - pass - ? "RESULT: PASS" - : `RESULT: FAIL (${failed.length} failed step(s), ${results.length} recorded)`, - ); - process.exit(pass ? 0 : 1); - }), - ), -); - -NodeRuntime.runMain( - program.pipe(Effect.provide(Layer.mergeAll(NodeServices.layer, NetService.layer))), -); diff --git a/apps/server/scratchpad/ws-rpc-context-debug.ts b/apps/server/scratchpad/ws-rpc-context-debug.ts deleted file mode 100644 index 85d8bbf7a0ad..000000000000 --- a/apps/server/scratchpad/ws-rpc-context-debug.ts +++ /dev/null @@ -1,84 +0,0 @@ -import * as NodeRuntime from "@effect/platform-node/NodeRuntime"; -import * as NodeServices from "@effect/platform-node/NodeServices"; -import * as NetService from "@t3tools/shared/Net"; -import * as Duration from "effect/Duration"; -import * as Effect from "effect/Effect"; -import * as Layer from "effect/Layer"; -import * as LogLevel from "effect/LogLevel"; -import * as Option from "effect/Option"; - -import { ServerConfig } from "../src/config.ts"; -import { resolveServerConfig, type CliServerFlags } from "../src/cli/config.ts"; -import { SeededWorkItemWritebackLive } from "../src/orchestration/Layers/SeededWorkItemWriteback.ts"; -import { debugWsRuntimeLayer } from "../src/server.ts"; -import { debugBuildWsRpcContext } from "../src/ws.ts"; - -const cliRuntimeLayer = Layer.mergeAll( - NodeServices.layer, - NetService.layer, - SeededWorkItemWritebackLive, -); - -const flags: CliServerFlags = { - mode: Option.none(), - port: Option.none(), - host: Option.none(), - baseDir: Option.none(), - cwd: Option.some(process.cwd()), - devUrl: Option.none(), - noBrowser: Option.some(true), - bootstrapFd: Option.none(), - autoBootstrapProjectFromCwd: Option.some(false), - logWebSocketEvents: Option.some(true), - tailscaleServeEnabled: Option.none(), - tailscaleServePort: Option.none(), -}; - -const session = { - sessionId: "debug-session", - subject: "debug-subject", - method: "browser-session-cookie", - scopes: [], -} as const; - -const program = Effect.gen(function* () { - const config = yield* resolveServerConfig(flags, Option.some(LogLevel.Debug)); - yield* Effect.logDebug("[DEBUG-ws-rpc-harness] config resolved", { - cwd: config.cwd, - baseDir: config.baseDir, - port: config.port, - }); - - const runtimeContext = yield* Layer.build( - debugWsRuntimeLayer.pipe(Layer.provide(Layer.succeed(ServerConfig, config))), - ).pipe(Effect.scoped, Effect.timeoutOption(Duration.seconds(3))); - - if (Option.isNone(runtimeContext)) { - yield* Effect.logError("[DEBUG-ws-rpc-harness] runtime layer build timed out", { - sessionId: session.sessionId, - }); - return; - } - - yield* Effect.logInfo("[DEBUG-ws-rpc-harness] runtime layer built", { - sessionId: session.sessionId, - }); - - const result = yield* debugBuildWsRpcContext(session).pipe( - Effect.provide(runtimeContext.value), - Effect.timeoutOption(Duration.seconds(3)), - ); - - if (Option.isNone(result)) { - yield* Effect.logError("[DEBUG-ws-rpc-harness] ws rpc context build timed out", { - sessionId: session.sessionId, - }); - return; - } - - yield* Effect.logInfo("[DEBUG-ws-rpc-harness] ws rpc context built", { - sessionId: session.sessionId, - }); -}).pipe(Effect.provide(cliRuntimeLayer)); - -NodeRuntime.runMain(program); diff --git a/apps/server/scripts/acp-mock-agent.ts b/apps/server/scripts/acp-mock-agent.ts index 20b12ef20dc0..1a38e489fb2a 100644 --- a/apps/server/scripts/acp-mock-agent.ts +++ b/apps/server/scripts/acp-mock-agent.ts @@ -18,9 +18,15 @@ const emitInterleavedAssistantToolCalls = process.env.T3_ACP_EMIT_INTERLEAVED_ASSISTANT_TOOL_CALLS === "1"; const emitGenericToolPlaceholders = process.env.T3_ACP_EMIT_GENERIC_TOOL_PLACEHOLDERS === "1"; const emitAskQuestion = process.env.T3_ACP_EMIT_ASK_QUESTION === "1"; +const emitXAiAskUserQuestion = process.env.T3_ACP_EMIT_XAI_ASK_USER_QUESTION === "1"; const failSetConfigOption = process.env.T3_ACP_FAIL_SET_CONFIG_OPTION === "1"; const exitOnSetConfigOption = process.env.T3_ACP_EXIT_ON_SET_CONFIG_OPTION === "1"; const promptResponseText = process.env.T3_ACP_PROMPT_RESPONSE_TEXT; +const permissionOptionIds = { + allowOnce: process.env.T3_ACP_ALLOW_ONCE_OPTION_ID ?? "allow-once", + allowAlways: process.env.T3_ACP_ALLOW_ALWAYS_OPTION_ID ?? "allow-always", + rejectOnce: process.env.T3_ACP_REJECT_ONCE_OPTION_ID ?? "reject-once", +}; const sessionId = "mock-session-1"; let currentModeId = "ask"; @@ -237,6 +243,21 @@ function modeState(): AcpSchema.SessionModeState { }; } +const grokAcpModels: ReadonlyArray = [ + { modelId: "grok-build", name: "Grok Build" }, + { modelId: "grok-mock-alt", name: "Grok Mock Alt" }, +]; + +function modelState(): AcpSchema.SessionModelState { + const modelId = grokAcpModels.some((model) => model.modelId === currentModelId) + ? currentModelId + : "grok-build"; + return { + currentModelId: modelId, + availableModels: grokAcpModels, + }; +} + const program = Effect.gen(function* () { const agent = yield* EffectAcpAgent.AcpAgent; @@ -257,6 +278,7 @@ const program = Effect.gen(function* () { Effect.succeed({ sessionId, modes: modeState(), + models: modelState(), configOptions: configOptions(), }), ); @@ -273,11 +295,28 @@ const program = Effect.gen(function* () { .pipe( Effect.as({ modes: modeState(), + models: modelState(), configOptions: configOptions(), }), ), ); + yield* agent.handleSetSessionModel((request) => + Effect.gen(function* () { + if (!grokAcpModels.some((model) => model.modelId === request.modelId)) { + return yield* AcpError.AcpRequestError.invalidParams( + `Unknown mock model id: ${request.modelId}`, + { + method: "session/set_model", + params: request, + }, + ); + } + currentModelId = request.modelId; + return {}; + }), + ); + yield* agent.handleSetSessionConfigOption((request) => Effect.gen(function* () { if (exitOnSetConfigOption) { @@ -419,9 +458,13 @@ const program = Effect.gen(function* () { ], }, options: [ - { optionId: "allow-once", name: "Allow once", kind: "allow_once" }, - { optionId: "allow-always", name: "Allow always", kind: "allow_always" }, - { optionId: "reject-once", name: "Reject", kind: "reject_once" }, + { optionId: permissionOptionIds.allowOnce, name: "Allow once", kind: "allow_once" }, + { + optionId: permissionOptionIds.allowAlways, + name: "Allow always", + kind: "allow_always", + }, + { optionId: permissionOptionIds.rejectOnce, name: "Reject", kind: "reject_once" }, ], }); @@ -514,6 +557,43 @@ const program = Effect.gen(function* () { return { stopReason: "end_turn" }; } + if (emitXAiAskUserQuestion) { + const result = yield* agent.client.extRequest("_x.ai/ask_user_question", { + method: "x.ai/ask_user_question", + params: { + sessionId: requestedSessionId, + toolCallId: "ask-user-question-tool-call-1", + questions: [ + { + question: "Which scope should Grok use?", + multiSelect: null, + options: [ + { label: "Workspace", description: "Use the current workspace" }, + { label: "Session", description: "Only use this session" }, + ], + }, + ], + mode: "default", + }, + }); + if (typeof result !== "object" || result === null || !("outcome" in result)) { + throw new Error("Expected _x.ai/ask_user_question response outcome."); + } + if (result.outcome === "cancelled") { + return { stopReason: "end_turn" }; + } + if ( + result.outcome !== "accepted" || + !("answers" in result) || + typeof result.answers !== "object" || + result.answers === null + ) { + throw new Error("Expected accepted _x.ai/ask_user_question response answers."); + } + + return { stopReason: "end_turn" }; + } + yield* agent.client.sessionUpdate({ sessionId: requestedSessionId, update: { diff --git a/apps/server/src/auth/EnvironmentAuth.ts b/apps/server/src/auth/EnvironmentAuth.ts index 5534ff5ae75e..d8c0079089fc 100644 --- a/apps/server/src/auth/EnvironmentAuth.ts +++ b/apps/server/src/auth/EnvironmentAuth.ts @@ -174,9 +174,7 @@ export interface EnvironmentAuthShape { ServerAuthInvalidCredentialError | ServerAuthInternalError >; readonly issueWebSocketTicket: ( - session: Pick & { - readonly scopes: ReadonlyArray | ReadonlySet; - }, + session: Pick, ) => Effect.Effect; readonly issueStartupPairingUrl: ( baseUrl: string, @@ -196,27 +194,6 @@ const AUTHORIZATION_PREFIX = "Bearer "; const DPOP_AUTHORIZATION_PREFIX = "DPoP "; const WEBSOCKET_TICKET_QUERY_PARAM = "wsTicket"; -function describePresentedCredentials( - request: HttpServerRequest.HttpServerRequest, - sessionCookieName: string, -) { - const hasSessionCookie = typeof request.cookies[sessionCookieName] === "string"; - const hasBearerToken = parseBearerToken(request) !== null; - const hasDpopToken = parseDpopToken(request) !== null; - return { - hasSessionCookie, - hasBearerToken, - hasDpopToken, - credentialSource: hasSessionCookie - ? "cookie" - : hasBearerToken - ? "bearer" - : hasDpopToken - ? "dpop" - : "none", - } as const; -} - const bySessionPriority = (left: AuthClientSession, right: AuthClientSession) => { const leftCanManage = left.scopes.includes(AuthAccessWriteScope); const rightCanManage = right.scopes.includes(AuthAccessWriteScope); @@ -323,27 +300,10 @@ export const make = Effect.fn("makeEnvironmentAuth")(function* () { const bearerToken = parseBearerToken(request); const dpopToken = parseDpopToken(request); const credential = cookieToken ?? bearerToken ?? dpopToken; - const presentedCredentials = describePresentedCredentials(request, sessions.cookieName); if (!credential) { - return Effect.logDebug("auth.request missing credential", { - path: request.originalUrl, - ...presentedCredentials, - }).pipe( - Effect.andThen( - Effect.fail(new ServerAuthInvalidCredentialError({ reason: "missing_credential" })), - ), - ); + return Effect.fail(new ServerAuthInvalidCredentialError({ reason: "missing_credential" })); } return authenticateToken(credential).pipe( - Effect.tap((session) => - Effect.logDebug("auth.request authenticated", { - path: request.originalUrl, - ...presentedCredentials, - sessionId: session.sessionId, - sessionMethod: session.method, - scopeCount: session.scopes.length, - }), - ), Effect.flatMap((session) => { if (session.proofKeyThumbprint) { if (!dpopToken || dpopToken !== credential) { @@ -437,13 +397,6 @@ export const make = Effect.fn("makeEnvironmentAuth")(function* () { sessionToken: session.token, }) satisfies BootstrapExchangeResult, ), - Effect.tap((result) => - Effect.logDebug("auth.browserSession issued", { - sessionMethod: result.response.sessionMethod, - scopeCount: result.response.scopes.length, - expiresAt: DateTime.formatIso(result.response.expiresAt), - }), - ), Effect.withSpan("EnvironmentAuth.createBrowserSession"), ); @@ -704,14 +657,6 @@ export const make = Effect.fn("makeEnvironmentAuth")(function* () { expiresAt: DateTime.toUtc(issued.expiresAt), }) satisfies AuthWebSocketTicketResult, ), - Effect.tap((issued) => - Effect.logDebug("auth.webSocketTicket issued", { - sessionId: session.sessionId, - sessionMethod: session.method, - scopeCount: "size" in session.scopes ? session.scopes.size : session.scopes.length, - expiresAt: DateTime.formatIso(issued.expiresAt), - }), - ), Effect.withSpan("EnvironmentAuth.issueWebSocketTicket"), ); @@ -724,9 +669,6 @@ export const make = Effect.fn("makeEnvironmentAuth")(function* () { if (Option.isSome(requestUrl)) { const websocketTicket = requestUrl.value.searchParams.get(WEBSOCKET_TICKET_QUERY_PARAM); if (websocketTicket && websocketTicket.trim().length > 0) { - yield* Effect.logDebug("auth.websocket upgrade using ticket", { - path: request.originalUrl, - }); return yield* sessions.verifyWebSocketToken(websocketTicket).pipe( Effect.map((session) => ({ sessionId: session.sessionId, @@ -735,23 +677,11 @@ export const make = Effect.fn("makeEnvironmentAuth")(function* () { scopes: session.scopes, ...(session.expiresAt ? { expiresAt: session.expiresAt } : {}), })), - Effect.tap((session) => - Effect.logDebug("auth.websocket ticket authenticated", { - path: request.originalUrl, - sessionId: session.sessionId, - sessionMethod: session.method, - scopeCount: session.scopes.length, - }), - ), mapSessionVerificationErrors, ); } } - yield* Effect.logDebug("auth.websocket upgrade falling back to request auth", { - path: request.originalUrl, - ...describePresentedCredentials(request, sessions.cookieName), - }); return yield* authenticateRequest(request); }); diff --git a/apps/server/src/auth/SessionStore.ts b/apps/server/src/auth/SessionStore.ts index 96c73e34f1dd..8de145ca338b 100644 --- a/apps/server/src/auth/SessionStore.ts +++ b/apps/server/src/auth/SessionStore.ts @@ -240,94 +240,64 @@ export const make = Effect.fn("makeSessionStore")(function* () { }); const markConnected: SessionStoreShape["markConnected"] = (sessionId) => - Effect.logDebug("session.markConnected start", { sessionId }) - .pipe( - Effect.andThen( - Ref.modify(connectedSessionsRef, (current) => { - const next = new Map(current); - const wasDisconnected = !next.has(sessionId); - next.set(sessionId, (next.get(sessionId) ?? 0) + 1); - return [wasDisconnected, next] as const; - }), - ), - ) - .pipe( - Effect.tap((wasDisconnected) => - Effect.logDebug("session.markConnected state updated", { - sessionId, - wasDisconnected, - }), - ), - Effect.flatMap((wasDisconnected) => - wasDisconnected - ? DateTime.now.pipe( - Effect.flatMap((lastConnectedAt) => - authSessions.setLastConnectedAt({ - sessionId, - lastConnectedAt, - }), - ), - ) - : Effect.void, - ), - Effect.flatMap(() => loadActiveSession(sessionId)), - Effect.tap((session) => - Effect.logDebug("session.markConnected loaded active session", { + Ref.modify(connectedSessionsRef, (current) => { + const next = new Map(current); + const wasDisconnected = !next.has(sessionId); + next.set(sessionId, (next.get(sessionId) ?? 0) + 1); + return [wasDisconnected, next] as const; + }).pipe( + Effect.flatMap((wasDisconnected) => + wasDisconnected + ? DateTime.now.pipe( + Effect.flatMap((lastConnectedAt) => + authSessions.setLastConnectedAt({ + sessionId, + lastConnectedAt, + }), + ), + ) + : Effect.void, + ), + Effect.flatMap(() => loadActiveSession(sessionId)), + Effect.flatMap((session) => + Option.isSome(session) ? emitUpsert(session.value) : Effect.void, + ), + Effect.catchCause((cause) => + Effect.logError("Failed to publish connected-session auth update.").pipe( + Effect.annotateLogs({ sessionId, - hasActiveSession: Option.isSome(session), + cause, }), ), - Effect.flatMap((session) => - Option.isSome(session) ? emitUpsert(session.value) : Effect.void, - ), - Effect.catchCause((cause) => - Effect.logError("Failed to publish connected-session auth update.").pipe( - Effect.annotateLogs({ - sessionId, - cause, - }), - ), - ), - Effect.withSpan("SessionStore.markConnected"), - ); + ), + Effect.withSpan("SessionStore.markConnected"), + ); const markDisconnected: SessionStoreShape["markDisconnected"] = (sessionId) => - Effect.logDebug("session.markDisconnected start", { sessionId }) - .pipe( - Effect.andThen( - Ref.update(connectedSessionsRef, (current) => { - const next = new Map(current); - const remaining = (next.get(sessionId) ?? 0) - 1; - if (remaining > 0) { - next.set(sessionId, remaining); - } else { - next.delete(sessionId); - } - return next; - }), - ), - ) - .pipe( - Effect.flatMap(() => loadActiveSession(sessionId)), - Effect.tap((session) => - Effect.logDebug("session.markDisconnected loaded active session", { + Ref.update(connectedSessionsRef, (current) => { + const next = new Map(current); + const remaining = (next.get(sessionId) ?? 0) - 1; + if (remaining > 0) { + next.set(sessionId, remaining); + } else { + next.delete(sessionId); + } + return next; + }).pipe( + Effect.flatMap(() => loadActiveSession(sessionId)), + Effect.flatMap((session) => + Option.isSome(session) ? emitUpsert(session.value) : Effect.void, + ), + Effect.catchCause((cause) => + Effect.logError("Failed to publish disconnected-session auth update.").pipe( + Effect.annotateLogs({ sessionId, - hasActiveSession: Option.isSome(session), + cause, }), ), - Effect.flatMap((session) => - Option.isSome(session) ? emitUpsert(session.value) : Effect.void, - ), - Effect.catchCause((cause) => - Effect.logError("Failed to publish disconnected-session auth update.").pipe( - Effect.annotateLogs({ - sessionId, - cause, - }), - ), - ), - Effect.withSpan("SessionStore.markDisconnected"), - ); + ), + Effect.withSpan("SessionStore.markDisconnected"), + ); const encodeClaims = Schema.encodeEffect(Schema.fromJsonString(SessionClaims)); const issue: SessionStoreShape["issue"] = Effect.fn("SessionStore.issue")( diff --git a/apps/server/src/auth/http.ts b/apps/server/src/auth/http.ts index 9bce758dedd2..ed640863d21f 100644 --- a/apps/server/src/auth/http.ts +++ b/apps/server/src/auth/http.ts @@ -196,15 +196,7 @@ export const authHttpApiLayer = HttpApiBuilder.group( function* (args) { yield* annotateEnvironmentRequest(args.endpoint.name); const request = yield* HttpServerRequest.HttpServerRequest; - const sessionState = yield* serverAuth.getSessionState(request); - yield* Effect.logDebug("auth.session resolved", { - authenticated: sessionState.authenticated, - hasSessionCookie: - typeof request.cookies[sessionState.auth.sessionCookieName] === "string", - hasAuthorizationHeader: request.headers.authorization !== undefined, - sessionMethods: sessionState.auth.sessionMethods.join(","), - }); - return sessionState; + return yield* serverAuth.getSessionState(request); }, Effect.catchTag("ServerAuthInternalError", (error) => failEnvironmentInternal("internal_error", error), @@ -234,12 +226,6 @@ export const authHttpApiLayer = HttpApiBuilder.group( Effect.succeed(HttpServerResponse.mergeCookies(response, sessionCookies)), ); yield* appendCredentialResponseHeaders; - yield* Effect.logDebug("auth.browserSession response prepared", { - sessionCookieName: sessions.cookieName, - authenticated: result.response.authenticated, - sessionMethod: result.response.sessionMethod, - scopeCount: result.response.scopes.length, - }); return result.response; }, Effect.catchTags({ @@ -318,14 +304,7 @@ export const authHttpApiLayer = HttpApiBuilder.group( yield* annotateEnvironmentRequest(args.endpoint.name); const session = yield* EnvironmentAuthenticatedPrincipal; yield* appendCredentialResponseHeaders; - const issued = yield* serverAuth.issueWebSocketTicket(session); - yield* Effect.logDebug("auth.webSocketTicket response prepared", { - sessionId: session.sessionId, - sessionMethod: session.method, - scopeCount: session.scopes.size, - expiresAt: DateTime.formatIso(issued.expiresAt), - }); - return issued; + return yield* serverAuth.issueWebSocketTicket(session); }, Effect.catchTag("ServerAuthInternalError", (error) => failEnvironmentInternal("websocket_ticket_issuance_failed", error), diff --git a/apps/server/src/bin.test.ts b/apps/server/src/bin.test.ts index df4f090bc287..27a1d55e90d5 100644 --- a/apps/server/src/bin.test.ts +++ b/apps/server/src/bin.test.ts @@ -34,24 +34,15 @@ import { WorkspacePathsLive } from "./workspace/Layers/WorkspacePaths.ts"; import * as ServerSecretStore from "./auth/ServerSecretStore.ts"; import * as EnvironmentAuth from "./auth/EnvironmentAuth.ts"; import { environmentAuthenticatedAuthLayer } from "./auth/http.ts"; -import { ServerRuntimeStartup } from "./serverRuntimeStartup.ts"; - -const CliRuntimeLayer = Layer.mergeAll( - NodeServices.layer, - NetService.layer, - Layer.succeed(ServerRuntimeStartup, { - awaitCommandReady: Effect.void, - markHttpListening: Effect.void, - enqueueCommand: (effect: Effect.Effect) => effect, - }), -); + +const CliRuntimeLayer = Layer.mergeAll(NodeServices.layer, NetService.layer); class ProjectCliHttpApi extends HttpApi.make("environment").add(EnvironmentOrchestrationHttpApi) {} -const cloudCli = makeCli({ cloudEnabled: true }); -const noCloudCli = makeCli({ cloudEnabled: false }); +const connectCli = makeCli({ cloudEnabled: true }); +const noConnectCli = makeCli({ cloudEnabled: false }); const runCli = (args: ReadonlyArray, command = cli) => Command.runWith(command, { version: "0.0.0" })(args); -const runCloudCli = (args: ReadonlyArray) => runCli(args, cloudCli); +const runConnectCli = (args: ReadonlyArray) => runCli(args, connectCli); const runCliWithRuntime = (args: ReadonlyArray) => runCli(args).pipe(Effect.provide(CliRuntimeLayer)); @@ -188,9 +179,9 @@ it.layer(NodeServices.layer)("bin cli parsing", (it) => { }), ); - it.effect("rejects cloud commands when public cloud configuration is missing", () => + it.effect("rejects connect commands when public configuration is missing", () => Effect.gen(function* () { - const error = yield* runCli(["cloud", "status"], noCloudCli).pipe(Effect.flip); + const error = yield* runCli(["connect", "status"], noConnectCli).pipe(Effect.flip); if (!CliError.isCliError(error)) { assert.fail(`Expected CliError, got ${String(error)}`); @@ -198,20 +189,20 @@ it.layer(NodeServices.layer)("bin cli parsing", (it) => { if (error._tag !== "ShowHelp") { assert.fail(`Expected ShowHelp, got ${error._tag}`); } - assert.deepEqual(error.commandPath, ["t3", "cloud"]); - assert.include(error.errors[0]?.message ?? "", "missing T3 Cloud public configuration"); + assert.deepEqual(error.commandPath, ["t3", "connect"]); + assert.include(error.errors[0]?.message ?? "", "missing T3 Connect public configuration"); const output = (yield* TestConsole.errorLines).join("\n"); assert.include(output, "ERROR"); - assert.include(output, "missing T3 Cloud public configuration"); + assert.include(output, "missing T3 Connect public configuration"); }).pipe(Effect.provide(Layer.mergeAll(CliRuntimeLayer, TestConsole.layer))), ); - it.effect("reports fresh headless cloud state without requiring local configuration", () => + it.effect("reports fresh headless connect state without requiring local configuration", () => Effect.gen(function* () { const baseDir = mkdtempSync(join(tmpdir(), "t3-cli-cloud-status-test-")); const { output } = yield* captureStdout( - runCloudCli(["cloud", "status", "--base-dir", baseDir, "--json"]), + runConnectCli(["connect", "status", "--base-dir", baseDir, "--json"]), ); // @effect-diagnostics-next-line preferSchemaOverJson:off - CLI JSON output is decoded as a presentation DTO. const status = JSON.parse(output) as { @@ -230,21 +221,21 @@ it.layer(NodeServices.layer)("bin cli parsing", (it) => { }), ); - it.effect("reports actionable human-readable headless cloud state", () => + it.effect("reports actionable human-readable headless connect state", () => Effect.gen(function* () { const baseDir = mkdtempSync(join(tmpdir(), "t3-cli-cloud-status-human-test-")); const { output } = yield* captureStdout( - runCloudCli(["cloud", "status", "--base-dir", baseDir]), + runConnectCli(["connect", "status", "--base-dir", baseDir]), ); - assert.include(output, "T3 Cloud\n Exposure: disabled"); + assert.include(output, "T3 Connect\n Exposure: disabled"); assert.include(output, " Authorization: missing"); assert.include(output, " Environment link: not provisioned"); - assert.include(output, "Next: Run `t3 cloud link` to authorize and enable cloud exposure."); + assert.include(output, "Next: Run `t3 connect link` to authorize and enable T3 Connect."); }), ); - it.effect("logs in to headless cloud without enabling exposure", () => + it.effect("logs in to headless connect without enabling access", () => Effect.gen(function* () { const baseDir = mkdtempSync(join(tmpdir(), "t3-cli-cloud-login-test-")); const { secretsDir } = yield* deriveServerPaths(baseDir, undefined); @@ -259,9 +250,11 @@ it.layer(NodeServices.layer)("bin cli parsing", (it) => { }), ); - const login = yield* captureStdout(runCloudCli(["cloud", "login", "--base-dir", baseDir])); + const login = yield* captureStdout( + runConnectCli(["connect", "login", "--base-dir", baseDir]), + ); const status = yield* captureStdout( - runCloudCli(["cloud", "status", "--base-dir", baseDir, "--json"]), + runConnectCli(["connect", "status", "--base-dir", baseDir, "--json"]), ); // @effect-diagnostics-next-line preferSchemaOverJson:off - CLI JSON output is decoded as a presentation DTO. const decoded = JSON.parse(status.output) as { @@ -269,24 +262,24 @@ it.layer(NodeServices.layer)("bin cli parsing", (it) => { readonly authenticated: boolean; }; - assert.equal(login.output, "Signed in to T3 Cloud."); + assert.equal(login.output, "Signed in to T3 Connect."); assert.isFalse(decoded.desired); assert.isTrue(decoded.authenticated); }), ); - it.effect("disables headless cloud exposure without a running server", () => + it.effect("disables headless connect without a running server", () => Effect.gen(function* () { const baseDir = mkdtempSync(join(tmpdir(), "t3-cli-cloud-unlink-test-")); const { output } = yield* captureStdout( - runCloudCli(["cloud", "unlink", "--base-dir", baseDir]), + runConnectCli(["connect", "unlink", "--base-dir", baseDir]), ); - assert.equal(output, "T3 Cloud exposure is disabled locally."); + assert.equal(output, "T3 Connect is disabled locally."); }), ); - it.effect("logs out of headless cloud and removes the stored CLI authorization", () => + it.effect("logs out of headless connect and removes the stored CLI authorization", () => Effect.gen(function* () { const baseDir = mkdtempSync(join(tmpdir(), "t3-cli-cloud-logout-test-")); const { secretsDir } = yield* deriveServerPaths(baseDir, undefined); @@ -295,10 +288,10 @@ it.layer(NodeServices.layer)("bin cli parsing", (it) => { writeFileSync(tokenPath, "invalid persisted token"); const { output } = yield* captureStdout( - runCloudCli(["cloud", "logout", "--base-dir", baseDir]), + runConnectCli(["connect", "logout", "--base-dir", baseDir]), ); - assert.equal(output, "Signed out of T3 Cloud locally."); + assert.equal(output, "Signed out of T3 Connect locally."); assert.isFalse(existsSync(tokenPath)); }), ); @@ -333,61 +326,6 @@ it.layer(NodeServices.layer)("bin cli parsing", (it) => { }), ); - it.effect("includes stateDir in JSON pairing output and warns on mismatch", () => - Effect.gen(function* () { - const baseDir = mkdtempSync(join(tmpdir(), "t3-cli-auth-pairing-stateDir-test-")); - - const createdOutput = yield* captureStdout( - runCli(["auth", "pairing", "create", "--base-dir", baseDir, "--json"]), - ); - // @effect-diagnostics-next-line preferSchemaOverJson:off - const created = JSON.parse(createdOutput.output) as { - readonly id: string; - readonly credential: string; - readonly stateDir: string; - }; - - assert.equal(typeof created.stateDir, "string"); - assert.equal(created.stateDir!.includes("userdata"), true); - assert.equal(created.stateDir, join(baseDir, "userdata")); - }), - ); - - it.effect("prints advisory mismatch warning in text mode when dev-url is absent", () => - Effect.gen(function* () { - const baseDir = mkdtempSync(join(tmpdir(), "t3-cli-auth-pairing-warn-test-")); - - const createdOutput = yield* captureStdout( - runCli(["auth", "pairing", "create", "--base-dir", baseDir]), - ); - - assert.equal(createdOutput.output.includes("State directory:"), true); - assert.equal(createdOutput.output.includes("Token was written to the"), true); - assert.equal(createdOutput.output.includes("pass --dev-url to match"), true); - }), - ); - - it.effect("omits advisory warning when dev-url is passed", () => - Effect.gen(function* () { - const baseDir = mkdtempSync(join(tmpdir(), "t3-cli-auth-pairing-devurl-test-")); - - const createdOutput = yield* captureStdout( - runCli([ - "auth", - "pairing", - "create", - "--base-dir", - baseDir, - "--dev-url", - "http://localhost:5734", - ]), - ); - - assert.equal(createdOutput.output.includes("dev"), true); - assert.equal(createdOutput.output.includes("Token was written to the"), false); - }), - ); - it.effect("executes auth session subcommands and redacts secrets from list output", () => Effect.gen(function* () { const baseDir = mkdtempSync(join(tmpdir(), "t3-cli-auth-session-test-")); diff --git a/apps/server/src/bin.ts b/apps/server/src/bin.ts index 243d2814ddbb..ddfbf5e3ecce 100644 --- a/apps/server/src/bin.ts +++ b/apps/server/src/bin.ts @@ -8,42 +8,31 @@ import * as CliError from "effect/unstable/cli/CliError"; import * as NetService from "@t3tools/shared/Net"; import packageJson from "../package.json" with { type: "json" }; import { authCommand } from "./cli/auth.ts"; -import { cloudCommand } from "./cli/cloud.ts"; +import { connectCommand } from "./cli/connect.ts"; import { hasCloudPublicConfig } from "./cloud/publicConfig.ts"; import { sharedServerCommandFlags } from "./cli/config.ts"; import { projectCommand } from "./cli/project.ts"; import { runServerCommand, serveCommand, startCommand } from "./cli/server.ts"; -import { SeededWorkItemWritebackLive } from "./orchestration/Layers/SeededWorkItemWriteback.ts"; -import { ServerRuntimeStartup } from "./serverRuntimeStartup.ts"; -const CliRuntimeLayer = Layer.mergeAll( - NodeServices.layer, - NetService.layer, - SeededWorkItemWritebackLive, - Layer.succeed(ServerRuntimeStartup, { - awaitCommandReady: Effect.void, - markHttpListening: Effect.void, - enqueueCommand: (effect: Effect.Effect) => effect, - }), -); +const CliRuntimeLayer = Layer.mergeAll(NodeServices.layer, NetService.layer); -const cloudPublicConfigMissingMessage = - "T3 Cloud commands are unavailable: this build is missing T3 Cloud public configuration."; +const connectPublicConfigMissingMessage = + "T3 Connect commands are unavailable: this build is missing T3 Connect public configuration."; -class CloudPublicConfigMissingError extends CliError.UserError { +class ConnectPublicConfigMissingError extends CliError.UserError { override get message() { - return cloudPublicConfigMissingMessage; + return connectPublicConfigMissingMessage; } } -const cloudUnavailableCommand = Command.make("cloud").pipe( - Command.withDescription("T3 Cloud is unavailable in builds without public cloud configuration."), +const connectUnavailableCommand = Command.make("connect").pipe( + Command.withDescription("T3 Connect is unavailable in builds without public configuration."), Command.withHidden, Command.withHandler(() => Effect.fail( new CliError.ShowHelp({ - commandPath: ["t3", "cloud"], - errors: [new CloudPublicConfigMissingError({ cause: cloudPublicConfigMissingMessage })], + commandPath: ["t3", "connect"], + errors: [new ConnectPublicConfigMissingError({ cause: connectPublicConfigMissingMessage })], }), ), ), @@ -58,7 +47,7 @@ export const makeCli = ({ cloudEnabled = hasCloudPublicConfig } = {}) => serveCommand, authCommand, projectCommand, - cloudEnabled ? cloudCommand : cloudUnavailableCommand, + cloudEnabled ? connectCommand : connectUnavailableCommand, ]), ); diff --git a/apps/server/src/cli/cloud.test.ts b/apps/server/src/cli/connect.test.ts similarity index 98% rename from apps/server/src/cli/cloud.test.ts rename to apps/server/src/cli/connect.test.ts index 4dda50c0ce3f..5fce3bc1cd7d 100644 --- a/apps/server/src/cli/cloud.test.ts +++ b/apps/server/src/cli/connect.test.ts @@ -3,7 +3,7 @@ import { assert, it } from "@effect/vitest"; import * as Effect from "effect/Effect"; import * as Option from "effect/Option"; -import { acquireRelayClientForLink } from "./cloud.ts"; +import { acquireRelayClientForLink } from "./connect.ts"; const managedExecutable = { status: "available", diff --git a/apps/server/src/cli/cloud.ts b/apps/server/src/cli/connect.ts similarity index 87% rename from apps/server/src/cli/cloud.ts rename to apps/server/src/cli/connect.ts index 78027d1e8027..167fb75a37cc 100644 --- a/apps/server/src/cli/cloud.ts +++ b/apps/server/src/cli/connect.ts @@ -89,15 +89,15 @@ function formatCloudStatus(status: CloudCliStatus, options?: { readonly json?: b ? "pending server startup" : "not provisioned"; const nextStep = !status.authenticated - ? "Run `t3 cloud link` to authorize and enable cloud exposure." + ? "Run `t3 connect link` to authorize and enable T3 Connect." : !status.desired - ? "Run `t3 cloud link` to enable cloud exposure." + ? "Run `t3 connect link` to enable T3 Connect." : !status.linked ? "Start T3 to provision the environment link and launch its managed tunnel." : undefined; return [ - "T3 Cloud", + "T3 Connect", ` Exposure: ${status.desired ? "enabled" : "disabled"}`, ` Authorization: ${status.authenticated ? "stored credential" : "missing"}`, ` Environment link: ${provisioned}`, @@ -112,7 +112,7 @@ const CLOUD_CLI_LIVE_SERVER_TIMEOUT = Duration.seconds(5); const confirmRelayClientInstall = (version: string) => Prompt.run( Prompt.confirm({ - message: `The T3 relay client is required for T3 Cloud exposure. Download and install version ${version}?`, + message: `The T3 relay client is required for T3 Connect. Download and install version ${version}?`, initial: false, }), ); @@ -169,7 +169,7 @@ const withCloudCliSessionToken = ( environmentAuth.issueSession({ scopes: [AuthRelayWriteScope], subject: "cloud-cli", - label: "t3 cloud cli", + label: "t3 connect cli", }), (issued) => run(issued.token), (issued) => environmentAuth.revokeSession(issued.sessionId).pipe(Effect.ignore({ log: true })), @@ -194,7 +194,7 @@ const runLiveCloudUnlink = Effect.fn("cloud.cli.run_live_unlink")(function* () { baseUrl: runtimeState.value.origin, }).pipe( Effect.flatMap((client) => - client.cloud.unlink({ headers: { authorization: `Bearer ${token}` } }), + client.connect.unlink({ headers: { authorization: `Bearer ${token}` } }), ), Effect.timeout(CLOUD_CLI_LIVE_SERVER_TIMEOUT), ), @@ -249,24 +249,24 @@ const disconnectCloud = Effect.fn("cloud.cli.disconnect")(function* (options: { if (liveResult.status === "failed") { yield* Console.warn( - `T3 Cloud exposure is disabled, but the running server could not stop its tunnel: ${String(liveResult.cause)}\nRestart that server to stop the connector.`, + `T3 Connect is disabled, but the running server could not stop its tunnel: ${String(liveResult.cause)}\nRestart that server to stop the connector.`, ); } else { - yield* Console.log("T3 Cloud exposure is disabled locally."); + yield* Console.log("T3 Connect is disabled locally."); } if (Exit.isFailure(relayResult)) { yield* Console.warn( options.clearAuthorization ? `Could not revoke the relay-side environment record before signing out: ${String(relayResult.cause)}\nThe stored CLI authorization was still removed locally.` - : `Could not revoke the relay-side environment record yet: ${String(relayResult.cause)}\nRun \`t3 cloud unlink\` again when the relay is reachable.`, + : `Could not revoke the relay-side environment record yet: ${String(relayResult.cause)}\nRun \`t3 connect unlink\` again when the relay is reachable.`, ); } else if (relayResult.value.status === "revoked") { yield* Console.log("Revoked the relay-side environment record."); } if (options.clearAuthorization) { - yield* Console.log("Signed out of T3 Cloud locally."); + yield* Console.log("Signed out of T3 Connect locally."); } }); @@ -307,26 +307,26 @@ const runCloudCommand = ( return yield* run.pipe(Effect.provide(runtimeLayer)); }); -const cloudLoginCommand = Command.make("login", { +const connectLoginCommand = Command.make("login", { ...projectLocationFlags, }).pipe( - Command.withDescription("Authorize the T3 Cloud CLI without enabling cloud exposure."), + Command.withDescription("Authorize the T3 Connect CLI without enabling remote access."), Command.withHandler((flags) => runCloudCommand( flags, Effect.gen(function* () { const tokens = yield* CliTokenManager.CloudCliTokenManager; yield* tokens.get; - yield* Console.log("Signed in to T3 Cloud."); + yield* Console.log("Signed in to T3 Connect."); }), ), ), ); -const cloudLinkCommand = Command.make("link", { +const connectLinkCommand = Command.make("link", { ...projectLocationFlags, }).pipe( - Command.withDescription("Authorize this environment for T3 Cloud and expose it on next start."), + Command.withDescription("Authorize this environment for T3 Connect on next start."), Command.withHandler((flags) => runCloudCommand( flags, @@ -338,7 +338,7 @@ const cloudLinkCommand = Command.make("link", { reportRelayClientInstallProgress, ); if (Option.isNone(installed)) { - yield* Console.log("T3 Cloud link cancelled. The relay client was not installed."); + yield* Console.log("T3 Connect setup cancelled. The relay client was not installed."); return; } yield* Console.log( @@ -349,18 +349,18 @@ const cloudLinkCommand = Command.make("link", { yield* tokens.get; yield* CliState.setCliDesiredCloudLink(true); yield* Console.log( - "This T3 environment will be available over T3 Cloud the next time T3 starts.", + "This T3 environment will be available through T3 Connect the next time T3 starts.", ); }), ), ), ); -const cloudStatusCommand = Command.make("status", { +const connectStatusCommand = Command.make("status", { ...projectLocationFlags, json: jsonFlag, }).pipe( - Command.withDescription("Show persisted T3 Cloud and relay client state."), + Command.withDescription("Show persisted T3 Connect and relay client state."), Command.withHandler((flags) => runCloudCommand( flags, @@ -395,31 +395,31 @@ const cloudStatusCommand = Command.make("status", { ), ); -const cloudUnlinkCommand = Command.make("unlink", { +const connectUnlinkCommand = Command.make("unlink", { ...projectLocationFlags, }).pipe( - Command.withDescription("Disable T3 Cloud exposure while retaining the stored authorization."), + Command.withDescription("Disable T3 Connect while retaining the stored authorization."), Command.withHandler((flags) => runCloudCommand(flags, disconnectCloud({ clearAuthorization: false })), ), ); -const cloudLogoutCommand = Command.make("logout", { +const connectLogoutCommand = Command.make("logout", { ...projectLocationFlags, }).pipe( - Command.withDescription("Disable T3 Cloud exposure and clear the stored CLI authorization."), + Command.withDescription("Disable T3 Connect and clear the stored CLI authorization."), Command.withHandler((flags) => runCloudCommand(flags, disconnectCloud({ clearAuthorization: true })), ), ); -export const cloudCommand = Command.make("cloud").pipe( - Command.withDescription("Manage headless T3 Cloud exposure."), +export const connectCommand = Command.make("connect").pipe( + Command.withDescription("Manage headless T3 Connect access."), Command.withSubcommands([ - cloudLoginCommand, - cloudLinkCommand, - cloudStatusCommand, - cloudUnlinkCommand, - cloudLogoutCommand, + connectLoginCommand, + connectLinkCommand, + connectStatusCommand, + connectUnlinkCommand, + connectLogoutCommand, ]), ); diff --git a/apps/server/src/cloud/CliTokenManager.ts b/apps/server/src/cloud/CliTokenManager.ts index c10b89229306..765ef0583322 100644 --- a/apps/server/src/cloud/CliTokenManager.ts +++ b/apps/server/src/cloud/CliTokenManager.ts @@ -96,7 +96,7 @@ const make = Effect.gen(function* () { const clear = secrets .remove(CLOUD_CLI_OAUTH_TOKEN_SECRET) - .pipe(wrapError("Could not remove the stored T3 Cloud CLI credential.")); + .pipe(wrapError("Could not remove the stored T3 Connect CLI credential.")); const read = Effect.fn("cloud.cli_token.read")(function* () { const encoded = yield* secrets.get(CLOUD_CLI_OAUTH_TOKEN_SECRET); @@ -146,7 +146,7 @@ const make = Effect.gen(function* () { const url = new URL(request.originalUrl, metadata.redirectUri); const code = url.searchParams.get("code"); if (url.searchParams.get("state") !== state || !code) { - return HttpServerResponse.text("Invalid T3 Cloud authorization callback.", { + return HttpServerResponse.text("Invalid T3 Connect authorization callback.", { status: 400, }); } @@ -154,7 +154,7 @@ const make = Effect.gen(function* () { return yield* HttpServerResponse.html` -

T3 Cloud authorization complete

+

T3 Connect authorization complete

You can close this window and return to your terminal.

@@ -182,13 +182,13 @@ const make = Effect.gen(function* () { authorizationUrl.searchParams.set("state", state); authorizationUrl.searchParams.set("code_challenge", challenge); authorizationUrl.searchParams.set("code_challenge_method", "S256"); - yield* Console.log(`Open this URL to authorize T3 Cloud:\n${authorizationUrl.toString()}\n`); + yield* Console.log(`Open this URL to authorize T3 Connect:\n${authorizationUrl.toString()}\n`); const code = yield* Deferred.await(callback).pipe( Effect.timeout(CLOUD_CLI_OAUTH_CALLBACK_TIMEOUT), Effect.catchTag("TimeoutError", () => Effect.fail( new CloudCliTokenManagerError({ - message: "Timed out waiting for T3 Cloud authorization.", + message: "Timed out waiting for T3 Connect authorization.", }), ), ), @@ -213,12 +213,12 @@ const make = Effect.gen(function* () { }); const getExisting = semaphore.withPermits(1)( - getExistingNoLock().pipe(wrapError("Could not refresh the T3 Cloud CLI credential.")), + getExistingNoLock().pipe(wrapError("Could not refresh the T3 Connect CLI credential.")), ); const hasCredential = semaphore.withPermits(1)( read().pipe( Effect.map(Option.isSome), - wrapError("Could not read the stored T3 Cloud CLI credential."), + wrapError("Could not read the stored T3 Connect CLI credential."), ), ); const get = semaphore.withPermits(1)( @@ -227,7 +227,7 @@ const make = Effect.gen(function* () { return Option.isSome(token) ? token.value : yield* Effect.scoped(login()).pipe(Effect.flatMap(persist)); - }).pipe(wrapError("Could not authorize the T3 Cloud CLI.")), + }).pipe(wrapError("Could not authorize the T3 Connect CLI.")), ); return CloudCliTokenManager.of({ get, getExisting, hasCredential, clear }); diff --git a/apps/server/src/cloud/http.test.ts b/apps/server/src/cloud/http.test.ts index 2b7e7d249ef0..799ab609f433 100644 --- a/apps/server/src/cloud/http.test.ts +++ b/apps/server/src/cloud/http.test.ts @@ -76,7 +76,7 @@ describe("reconcileDesiredCloudLink", () => { expect(error).toMatchObject({ _tag: "EnvironmentHttpUnauthorizedError", - message: "Run `t3 cloud link` to authorize this environment.", + message: "Run `t3 connect link` to authorize this environment.", }); }).pipe( Effect.provideService( diff --git a/apps/server/src/cloud/http.ts b/apps/server/src/cloud/http.ts index 38203dae37ef..896990849b6c 100644 --- a/apps/server/src/cloud/http.ts +++ b/apps/server/src/cloud/http.ts @@ -509,7 +509,7 @@ const relayClientRequest =
( Effect.mapError( (cause) => new EnvironmentHttpInternalServerError({ - message: `T3 Cloud relay request failed: ${String(cause)}`, + message: `T3 Connect relay request failed: ${String(cause)}`, }), ), ); @@ -535,7 +535,7 @@ const reconcileDesiredCloudLinkWith = Effect.fn("environment.cloud.reconcileDesi onNone: () => Effect.fail( new EnvironmentHttpUnauthorizedError({ - message: "Run `t3 cloud link` to authorize this environment.", + message: "Run `t3 connect link` to authorize this environment.", }), ), onSome: Effect.succeed, @@ -595,7 +595,7 @@ const reconcileDesiredCloudLinkWith = Effect.fn("environment.cloud.reconcileDesi CloudCliTokenManagerError: (error) => failEnvironmentCloudInternalError(error.message)(error.cause), SecretStoreError: failEnvironmentCloudInternalError( - "Could not persist desired T3 Cloud link state.", + "Could not persist desired T3 Connect link state.", ), }), ); @@ -874,7 +874,7 @@ const cloudMintCredentialHandler = Effect.fn("environment.cloud.mintCredential") scopes: AuthStandardClientScopes, subject: "cloud-connect", ttl: Duration.minutes(2), - label: "T3 Cloud connect", + label: "T3 Connect connect", proofKeyThumbprint: proof.clientProofKeyThumbprint, }); const responsePayload = { @@ -924,9 +924,9 @@ const cloudMintCredentialHandler = Effect.fn("environment.cloud.mintCredential") }), ); -export const cloudHttpApiLayer = HttpApiBuilder.group( +export const connectHttpApiLayer = HttpApiBuilder.group( EnvironmentHttpApi, - "cloud", + "connect", Effect.fnUntraced(function* (handlers) { const dependencies = yield* cloudHttpDependencies; return handlers diff --git a/apps/server/src/git/GitManager.test.ts b/apps/server/src/git/GitManager.test.ts index 861781589fa9..2b7d34bb1707 100644 --- a/apps/server/src/git/GitManager.test.ts +++ b/apps/server/src/git/GitManager.test.ts @@ -632,27 +632,6 @@ function createGitHubCliWithFakeGh(scenario: FakeGhScenario = {}): { cwd: input.cwd, args: ["pr", "checkout", input.reference, ...(input.force ? ["--force"] : [])], }).pipe(Effect.asVoid), - getPullRequestReviews: (input) => - Effect.fail( - new GitHubCliError({ - operation: "getPullRequestReviews", - detail: `Unexpected pull request reviews lookup: ${input.reference}`, - }), - ), - createPullRequestReview: (input) => - Effect.fail( - new GitHubCliError({ - operation: "createPullRequestReview", - detail: `Unexpected pull request review create: ${input.reference}`, - }), - ), - createPullRequestReviewWithComments: (input) => - Effect.fail( - new GitHubCliError({ - operation: "createPullRequestReviewWithComments", - detail: `Unexpected pull request review with comments create: ${input.reference}`, - }), - ), }, ghCalls, }; diff --git a/apps/server/src/git/GitManager.ts b/apps/server/src/git/GitManager.ts index ff82aea9b453..5c9049ce6e03 100644 --- a/apps/server/src/git/GitManager.ts +++ b/apps/server/src/git/GitManager.ts @@ -151,34 +151,6 @@ interface BranchHeadContext { isCrossRepository: boolean; } -interface PullRequestLabelInfo { - name: string; - color?: string; -} - -function clonePullRequestLabels( - labels: - | ReadonlyArray<{ - readonly name: string; - readonly color?: string | undefined; - }> - | undefined, -): - | ReadonlyArray<{ - name: string; - color?: string; - }> - | undefined { - if (!labels || labels.length === 0) { - return undefined; - } - - return labels.map((label) => ({ - name: label.name, - ...(label.color !== undefined ? { color: label.color } : {}), - })); -} - function parseRepositoryNameFromPullRequestUrl(url: string): string | null { const trimmed = url.trim(); const match = /^https:\/\/github\.com\/[^/]+\/([^/]+)\/pull\/\d+(?:\/.*)?$/i.exec(trimmed); @@ -332,7 +304,6 @@ function matchesBranchHeadContext( } function toPullRequestInfo(summary: ChangeRequest): PullRequestInfo { - const labels = clonePullRequestLabels(summary.labels); return { number: summary.number, title: summary.title, @@ -340,7 +311,14 @@ function toPullRequestInfo(summary: ChangeRequest): PullRequestInfo { baseRefName: summary.baseRefName, headRefName: summary.headRefName, state: summary.state ?? "open", - ...(labels ? { labels } : {}), + ...(summary.labels + ? { + labels: summary.labels.map((label) => ({ + name: label.name, + ...(label.color === undefined ? {} : { color: label.color }), + })), + } + : {}), updatedAt: summary.updatedAt, ...(summary.isCrossRepository !== undefined ? { isCrossRepository: summary.isCrossRepository } @@ -503,9 +481,11 @@ function toStatusPr(pr: PullRequestInfo): { baseRef: string; headRef: string; state: "open" | "closed" | "merged"; - labels?: ReadonlyArray; + labels?: ReadonlyArray<{ + name: string; + color?: string; + }>; } { - const labels = clonePullRequestLabels(pr.labels); return { number: pr.number, title: pr.title, @@ -513,7 +493,7 @@ function toStatusPr(pr: PullRequestInfo): { baseRef: pr.baseRefName, headRef: pr.headRefName, state: pr.state, - ...(labels ? { labels } : {}), + ...(pr.labels ? { labels: [...pr.labels] } : {}), }; } @@ -956,7 +936,6 @@ export const makeGitManager = Effect.fn("makeGitManager")(function* () { matchesBranchHeadContext(pullRequest, headContext), ); if (firstPullRequest) { - const labels = clonePullRequestLabels(firstPullRequest.labels); return { number: firstPullRequest.number, title: firstPullRequest.title, @@ -964,7 +943,7 @@ export const makeGitManager = Effect.fn("makeGitManager")(function* () { baseRefName: firstPullRequest.baseRefName, headRefName: firstPullRequest.headRefName, state: "open", - ...(labels ? { labels } : {}), + ...(firstPullRequest.labels ? { labels: [...firstPullRequest.labels] } : {}), updatedAt: Option.none(), } satisfies PullRequestInfo; } diff --git a/apps/server/src/keybindings.test.ts b/apps/server/src/keybindings.test.ts index 6a42e82cd0fe..8a33d54b0558 100644 --- a/apps/server/src/keybindings.test.ts +++ b/apps/server/src/keybindings.test.ts @@ -200,8 +200,6 @@ it.layer(NodeServices.layer)("keybindings", (it) => { DEFAULT_KEYBINDINGS.map((binding) => [binding.command, binding.key] as const), ); - assert.equal(defaultsByCommand.get("chat.focus"), "mod+i"); - assert.equal(defaultsByCommand.get("chat.newInProject"), "mod+alt+n"); assert.equal(defaultsByCommand.get("thread.renameCurrent"), "mod+shift+e"); assert.equal(defaultsByCommand.get("thread.previous"), "mod+shift+["); assert.equal(defaultsByCommand.get("thread.next"), "mod+shift+]"); @@ -308,6 +306,31 @@ it.layer(NodeServices.layer)("keybindings", (it) => { }).pipe(Effect.provide(makeKeybindingsLayer())), ); + it.effect("removes retired fork commands from persisted keybindings on startup", () => + Effect.gen(function* () { + const fs = yield* FileSystem.FileSystem; + const { keybindingsConfigPath } = yield* ServerConfig; + yield* fs.writeFileString( + keybindingsConfigPath, + // @effect-diagnostics-next-line preferSchemaOverJson:off + JSON.stringify([ + { key: "mod+i", command: "chat.focus", when: "!terminalFocus" }, + { key: "mod+alt+n", command: "chat.newInProject", when: "!terminalFocus" }, + { key: "mod+shift+r", command: "script.run-tests.run" }, + ]), + ); + + const keybindings = yield* Keybindings; + yield* keybindings.syncDefaultKeybindingsOnStartup; + + const persisted = yield* readKeybindingsConfig(keybindingsConfigPath); + assert.isFalse(persisted.some((entry) => String(entry.command) === "chat.focus")); + assert.isFalse(persisted.some((entry) => String(entry.command) === "chat.newInProject")); + assert.isTrue(persisted.some((entry) => entry.command === "script.run-tests.run")); + assert.deepEqual((yield* keybindings.loadConfigState).issues, []); + }).pipe(Effect.provide(makeKeybindingsLayer())), + ); + it.effect("skips conflicting default keybindings on startup and logs a detailed warning", () => { const messages: string[] = []; const logger = Logger.make(({ message }) => { diff --git a/apps/server/src/keybindings.ts b/apps/server/src/keybindings.ts index 80b522eee719..7a9950e9a195 100644 --- a/apps/server/src/keybindings.ts +++ b/apps/server/src/keybindings.ts @@ -186,6 +186,18 @@ export interface KeybindingsChangeEvent { readonly issues: readonly ServerConfigIssue[]; } +const REMOVED_FORK_KEYBINDING_COMMANDS = new Set(["chat.focus", "chat.newInProject"]); + +function isRemovedForkKeybindingEntry(entry: unknown): boolean { + return ( + typeof entry === "object" && + entry !== null && + "command" in entry && + typeof entry.command === "string" && + REMOVED_FORK_KEYBINDING_COMMANDS.has(entry.command) + ); +} + function trimIssueMessage(message: string): string { const trimmed = message.trim(); return trimmed.length > 0 ? trimmed : "Invalid keybindings configuration."; @@ -376,11 +388,12 @@ const makeKeybindings = Effect.gen(function* () { { readonly keybindings: readonly KeybindingRule[]; readonly issues: readonly ServerConfigIssue[]; + readonly removedForkEntries: number; }, KeybindingsConfigError > { if (!(yield* readConfigExists)) { - return { keybindings: [], issues: [] }; + return { keybindings: [], issues: [], removedForkEntries: 0 }; } const rawConfig = yield* readRawConfig; @@ -390,12 +403,18 @@ const makeKeybindings = Effect.gen(function* () { return { keybindings: [], issues: [malformedConfigIssue(detail)], + removedForkEntries: 0, }; } const keybindings: KeybindingRule[] = []; const issues: ServerConfigIssue[] = []; + let removedForkEntries = 0; for (const [index, entry] of decodedEntries.value.entries()) { + if (isRemovedForkKeybindingEntry(entry)) { + removedForkEntries++; + continue; + } const decodedRule = decodeKeybindingRuleExit(entry); if (decodedRule._tag === "Failure") { const detail = Cause.pretty(decodedRule.cause); @@ -424,7 +443,7 @@ const makeKeybindings = Effect.gen(function* () { keybindings.push(decodedRule.value); } - return { keybindings, issues }; + return { keybindings, issues, removedForkEntries }; }); const writeConfigAtomically = (rules: readonly KeybindingRule[]) => { @@ -534,7 +553,7 @@ const makeKeybindings = Effect.gen(function* () { reason: "shortcut context already used by existing rule", }); } - if (missingDefaults.length === 0) { + if (missingDefaults.length === 0 && runtimeConfig.removedForkEntries === 0) { yield* Cache.invalidate(resolvedConfigCache, resolvedConfigCacheKey); return; } diff --git a/apps/server/src/observability/Layers/Observability.ts b/apps/server/src/observability/Layers/Observability.ts index 94368a45296c..95263866d809 100644 --- a/apps/server/src/observability/Layers/Observability.ts +++ b/apps/server/src/observability/Layers/Observability.ts @@ -1,3 +1,4 @@ +import { httpHeaderRedactionLayer } from "@t3tools/shared/httpObservability"; import { makeLocalFileTracer, makeTraceSink } from "@t3tools/shared/observability"; import * as Effect from "effect/Effect"; import * as Layer from "effect/Layer"; @@ -18,6 +19,7 @@ export const ObservabilityLive = Layer.unwrap( const traceReferencesLayer = Layer.mergeAll( Layer.succeed(Tracer.MinimumTraceLevel, config.traceMinLevel), Layer.succeed(References.TracerTimingEnabled, config.traceTimingEnabled), + httpHeaderRedactionLayer, ); const tracerLayer = Layer.unwrap( diff --git a/apps/server/src/orchestration/Layers/OrchestrationEngine.test.ts b/apps/server/src/orchestration/Layers/OrchestrationEngine.test.ts index f84bbd64edef..85c827f39d5c 100644 --- a/apps/server/src/orchestration/Layers/OrchestrationEngine.test.ts +++ b/apps/server/src/orchestration/Layers/OrchestrationEngine.test.ts @@ -38,20 +38,16 @@ import { } from "../Services/ProjectionPipeline.ts"; import { ProjectionSnapshotQuery } from "../Services/ProjectionSnapshotQuery.ts"; import { ServerConfig } from "../../config.ts"; -import { makeSqlitePersistenceLive } from "../../persistence/Layers/Sqlite.ts"; const asProjectId = (value: string): ProjectId => ProjectId.make(value); const asMessageId = (value: string): MessageId => MessageId.make(value); const asTurnId = (value: string): TurnId => TurnId.make(value); const asCheckpointRef = (value: string): CheckpointRef => CheckpointRef.make(value); -async function createOrchestrationSystem(options?: { readonly dbPath?: string }) { +async function createOrchestrationSystem() { const ServerConfigLayer = ServerConfig.layerTest(process.cwd(), { prefix: "t3-orchestration-engine-test-", }); - const persistenceLayer = options?.dbPath - ? makeSqlitePersistenceLive(options.dbPath) - : SqlitePersistenceMemory; const orchestrationLayer = Layer.mergeAll( OrchestrationEngineLive.pipe( Layer.provide(OrchestrationProjectionSnapshotQueryLive), @@ -62,7 +58,7 @@ async function createOrchestrationSystem(options?: { readonly dbPath?: string }) Layer.provide(OrchestrationEventStoreLive), Layer.provide(OrchestrationCommandReceiptRepositoryLive), Layer.provide(RepositoryIdentityResolverLive), - Layer.provide(persistenceLayer), + Layer.provide(SqlitePersistenceMemory), Layer.provideMerge(ServerConfigLayer), Layer.provideMerge(NodeServices.layer), ); @@ -72,9 +68,6 @@ async function createOrchestrationSystem(options?: { readonly dbPath?: string }) return { engine, readModel: () => runtime.runPromise(snapshotQuery.getSnapshot()), - shellSnapshot: () => runtime.runPromise(snapshotQuery.getShellSnapshot()), - threadDetail: (threadId: ThreadId) => - runtime.runPromise(snapshotQuery.getThreadDetailById(threadId)), run: (effect: Effect.Effect) => runtime.runPromise(effect), dispose: () => runtime.dispose(), }; @@ -300,792 +293,6 @@ describe("OrchestrationEngine", () => { await system.dispose(); }); - it("bootstraps exactly one manager workspace and manager console through persisted projections", async () => { - // @effect-diagnostics-next-line cryptoRandomUUID:off - const dbPath = `/tmp/t3-manager-bootstrap-${crypto.randomUUID()}.sqlite`; - const firstSystem = await createOrchestrationSystem({ dbPath }); - - await firstSystem.run( - firstSystem.engine.dispatch({ - type: "manager.bootstrap", - commandId: CommandId.make("cmd-manager-bootstrap"), - projectId: asProjectId("manager-workspace"), - threadId: ThreadId.make("manager-console"), - workspaceRoot: "/tmp/manager-workspace", - modelSelection: { - instanceId: ProviderInstanceId.make("codex"), - model: "gpt-5-codex", - }, - runtimeMode: "full-access", - interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, - createdAt: now(), - }), - ); - - const firstShellSnapshot = await firstSystem.shellSnapshot(); - expect(firstShellSnapshot.projects).toEqual([ - expect.objectContaining({ - id: asProjectId("manager-workspace"), - managerMetadata: { - role: "workspace", - }, - }), - ]); - expect(firstShellSnapshot.threads).toEqual([ - expect.objectContaining({ - id: ThreadId.make("manager-console"), - projectId: asProjectId("manager-workspace"), - managerMetadata: { - role: "console", - }, - }), - ]); - - await expect( - firstSystem.run( - firstSystem.engine.dispatch({ - type: "manager.bootstrap", - commandId: CommandId.make("cmd-manager-bootstrap-duplicate"), - projectId: asProjectId("manager-workspace-2"), - threadId: ThreadId.make("manager-console-2"), - workspaceRoot: "/tmp/manager-workspace-2", - modelSelection: { - instanceId: ProviderInstanceId.make("codex"), - model: "gpt-5-codex", - }, - runtimeMode: "full-access", - interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, - createdAt: now(), - }), - ), - ).rejects.toThrow("already exists"); - - await firstSystem.dispose(); - - const secondSystem = await createOrchestrationSystem({ dbPath }); - const reloadedShellSnapshot = await secondSystem.shellSnapshot(); - const reloadedThreadDetail = await secondSystem.threadDetail(ThreadId.make("manager-console")); - - expect(reloadedShellSnapshot.projects).toEqual([ - expect.objectContaining({ - id: asProjectId("manager-workspace"), - managerMetadata: { - role: "workspace", - }, - }), - ]); - expect(reloadedShellSnapshot.threads).toEqual([ - expect.objectContaining({ - id: ThreadId.make("manager-console"), - managerMetadata: { - role: "console", - }, - }), - ]); - expect(Option.isSome(reloadedThreadDetail)).toBe(true); - expect(Option.getOrNull(reloadedThreadDetail)?.managerMetadata).toEqual({ - role: "console", - }); - - await secondSystem.dispose(); - }); - - it("stores seeded manager work items with readiness classifications through persisted projections", async () => { - // @effect-diagnostics-next-line cryptoRandomUUID:off - const dbPath = `/tmp/t3-manager-seeded-work-${crypto.randomUUID()}.sqlite`; - const firstSystem = await createOrchestrationSystem({ dbPath }); - const createdAt = now(); - - await firstSystem.run( - firstSystem.engine.dispatch({ - type: "manager.bootstrap", - commandId: CommandId.make("cmd-manager-bootstrap"), - projectId: asProjectId("manager-workspace"), - threadId: ThreadId.make("manager-console"), - workspaceRoot: "/tmp/manager-workspace", - modelSelection: { - instanceId: ProviderInstanceId.make("codex"), - model: "gpt-5-codex", - }, - runtimeMode: "full-access", - interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, - createdAt, - }), - ); - - await firstSystem.run( - firstSystem.engine.dispatch({ - type: "project.create", - commandId: CommandId.make("cmd-project-app"), - projectId: asProjectId("app-project"), - title: "App Project", - workspaceRoot: "/tmp/app-project", - defaultModelSelection: { - instanceId: ProviderInstanceId.make("codex"), - model: "gpt-5-codex", - }, - createdAt, - }), - ); - - await firstSystem.run( - firstSystem.engine.dispatch({ - type: "manager.seed-work-items", - commandId: CommandId.make("cmd-manager-seed-work"), - threadId: ThreadId.make("manager-console"), - sourceKind: "todo-list", - sourceLabel: "Sprint Backlog", - items: [ - { - itemId: "work-ready", - title: "Ship settings page", - body: "Implement the settings route.", - delegationIntent: "delegate", - targetProjectId: asProjectId("app-project"), - acceptanceCriteria: ["Route loads", "Form saves"], - }, - { - itemId: "work-refine", - title: "Clarify billing export", - body: "The export flow is underspecified.", - delegationIntent: "delegate", - targetProjectId: asProjectId("app-project"), - acceptanceCriteria: [], - }, - { - itemId: "work-human", - title: "Handle vendor negotiation", - body: "Keep this with the human operator.", - delegationIntent: "human-owned", - targetProjectId: asProjectId("app-project"), - acceptanceCriteria: ["Vendor contacted"], - }, - { - itemId: "work-blocked", - title: "Investigate analytics mismatch", - body: "Need the owning project before delegation.", - delegationIntent: "delegate", - targetProjectId: null, - acceptanceCriteria: ["Mismatch reproduced"], - }, - ], - createdAt, - }), - ); - - const firstDetail = Option.getOrNull( - await firstSystem.threadDetail(ThreadId.make("manager-console")), - ); - expect(firstDetail?.seededWorkItems).toEqual([ - expect.objectContaining({ - itemId: "work-ready", - sourceKind: "todo-list", - sourceLabel: "Sprint Backlog", - readiness: "ready-for-worker", - }), - expect.objectContaining({ - itemId: "work-refine", - readiness: "needs-refinement", - }), - expect.objectContaining({ - itemId: "work-human", - readiness: "human-owned", - }), - expect.objectContaining({ - itemId: "work-blocked", - readiness: "blocked-on-context", - }), - ]); - - await firstSystem.dispose(); - - const secondSystem = await createOrchestrationSystem({ dbPath }); - const reloadedDetail = Option.getOrNull( - await secondSystem.threadDetail(ThreadId.make("manager-console")), - ); - - expect((reloadedDetail?.seededWorkItems ?? []).map((item) => item.readiness)).toEqual([ - "ready-for-worker", - "needs-refinement", - "human-owned", - "blocked-on-context", - ]); - - await secondSystem.dispose(); - }); - - it("keeps seeded work item descriptions unchanged when writeback requests are recorded", async () => { - const system = await createOrchestrationSystem(); - const createdAt = now(); - const managerThreadId = ThreadId.make("manager-console"); - - await system.run( - system.engine.dispatch({ - type: "manager.bootstrap", - commandId: CommandId.make("cmd-manager-bootstrap"), - projectId: asProjectId("manager-workspace"), - threadId: managerThreadId, - workspaceRoot: "/tmp/manager-workspace", - modelSelection: { - instanceId: ProviderInstanceId.make("codex"), - model: "gpt-5-codex", - }, - runtimeMode: "full-access", - interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, - createdAt, - }), - ); - - await system.run( - system.engine.dispatch({ - type: "manager.seed-work-items", - commandId: CommandId.make("cmd-manager-seed-work"), - threadId: managerThreadId, - sourceKind: "jira-set", - sourceLabel: "Jira", - items: [ - { - itemId: "JIRA-21", - title: "Refine manager writeback", - body: "Original Jira description", - delegationIntent: "delegate", - targetProjectId: null, - acceptanceCriteria: [], - }, - ], - createdAt, - }), - ); - - await system.run( - system.engine.dispatch({ - type: "thread.seeded-work-item-writeback.request", - commandId: CommandId.make("cmd-writeback-request"), - threadId: managerThreadId, - itemId: "JIRA-21", - writebackKind: "refinement-context", - body: "Refined problem statement and acceptance criteria.", - createdAt, - }), - ); - - const detail = Option.getOrNull(await system.threadDetail(managerThreadId)); - expect(detail?.seededWorkItems).toEqual([ - expect.objectContaining({ - itemId: "JIRA-21", - body: "Original Jira description", - }), - ]); - expect(detail?.activities).toEqual([]); - - await system.dispose(); - }); - - it("creates project-bound refiner threads for needs-refinement work items and persists their projection", async () => { - // @effect-diagnostics-next-line cryptoRandomUUID:off - const dbPath = `/tmp/t3-manager-refiner-thread-${crypto.randomUUID()}.sqlite`; - const firstSystem = await createOrchestrationSystem({ dbPath }); - const createdAt = now(); - - await firstSystem.run( - firstSystem.engine.dispatch({ - type: "manager.bootstrap", - commandId: CommandId.make("cmd-manager-bootstrap-refiner"), - projectId: asProjectId("manager-workspace"), - threadId: ThreadId.make("manager-console"), - workspaceRoot: "/tmp/manager-workspace", - modelSelection: { - instanceId: ProviderInstanceId.make("codex"), - model: "gpt-5-codex", - }, - runtimeMode: "full-access", - interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, - createdAt, - }), - ); - await firstSystem.run( - firstSystem.engine.dispatch({ - type: "project.create", - commandId: CommandId.make("cmd-project-refiner"), - projectId: asProjectId("app-project"), - title: "App Project", - workspaceRoot: "/tmp/app-project", - defaultModelSelection: { - instanceId: ProviderInstanceId.make("codex"), - model: "gpt-5-codex", - }, - createdAt, - }), - ); - await firstSystem.run( - firstSystem.engine.dispatch({ - type: "manager.seed-work-items", - commandId: CommandId.make("cmd-manager-seed-work-refiner"), - threadId: ThreadId.make("manager-console"), - sourceKind: "todo-list", - sourceLabel: "Sprint Backlog", - items: [ - { - itemId: "work-refine", - title: "Clarify billing export", - body: "The export flow is underspecified.", - delegationIntent: "delegate", - targetProjectId: asProjectId("app-project"), - acceptanceCriteria: [], - }, - ], - createdAt, - }), - ); - await firstSystem.run( - firstSystem.engine.dispatch({ - type: "manager.refiner-thread.create", - commandId: CommandId.make("cmd-manager-create-refiner-thread"), - threadId: ThreadId.make("refiner-thread-1"), - managerThreadId: ThreadId.make("manager-console"), - seededWorkItemId: "work-refine", - modelSelection: { - instanceId: ProviderInstanceId.make("codex"), - model: "gpt-5-codex", - }, - runtimeMode: "full-access", - interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, - branch: null, - worktreePath: null, - createdAt, - }), - ); - - const detail = Option.getOrNull( - await firstSystem.threadDetail(ThreadId.make("refiner-thread-1")), - ); - expect(detail?.projectId).toBe("app-project"); - expect(detail?.title).toBe("Refine: Clarify billing export"); - expect(detail?.managerMetadata).toEqual({ - role: "refiner", - managerThreadId: "manager-console", - seededWorkItemId: "work-refine", - }); - - await firstSystem.dispose(); - - const secondSystem = await createOrchestrationSystem({ dbPath }); - const reloadedDetail = Option.getOrNull( - await secondSystem.threadDetail(ThreadId.make("refiner-thread-1")), - ); - expect(reloadedDetail?.managerMetadata).toEqual({ - role: "refiner", - managerThreadId: "manager-console", - seededWorkItemId: "work-refine", - }); - await secondSystem.dispose(); - }); - - it("rejects a second active refiner thread for the same seeded work item", async () => { - const system = await createOrchestrationSystem(); - const createdAt = now(); - - await system.run( - system.engine.dispatch({ - type: "manager.bootstrap", - commandId: CommandId.make("cmd-manager-bootstrap-refiner-dup"), - projectId: asProjectId("manager-workspace"), - threadId: ThreadId.make("manager-console"), - workspaceRoot: "/tmp/manager-workspace", - modelSelection: { - instanceId: ProviderInstanceId.make("codex"), - model: "gpt-5-codex", - }, - runtimeMode: "full-access", - interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, - createdAt, - }), - ); - await system.run( - system.engine.dispatch({ - type: "project.create", - commandId: CommandId.make("cmd-project-refiner-dup"), - projectId: asProjectId("app-project"), - title: "App Project", - workspaceRoot: "/tmp/app-project", - defaultModelSelection: { - instanceId: ProviderInstanceId.make("codex"), - model: "gpt-5-codex", - }, - createdAt, - }), - ); - await system.run( - system.engine.dispatch({ - type: "manager.seed-work-items", - commandId: CommandId.make("cmd-manager-seed-work-refiner-dup"), - threadId: ThreadId.make("manager-console"), - sourceKind: "todo-list", - sourceLabel: "Sprint Backlog", - items: [ - { - itemId: "work-refine", - title: "Clarify billing export", - body: "The export flow is underspecified.", - delegationIntent: "delegate", - targetProjectId: asProjectId("app-project"), - acceptanceCriteria: [], - }, - ], - createdAt, - }), - ); - await system.run( - system.engine.dispatch({ - type: "manager.refiner-thread.create", - commandId: CommandId.make("cmd-manager-create-refiner-thread-first"), - threadId: ThreadId.make("refiner-thread-1"), - managerThreadId: ThreadId.make("manager-console"), - seededWorkItemId: "work-refine", - modelSelection: { - instanceId: ProviderInstanceId.make("codex"), - model: "gpt-5-codex", - }, - runtimeMode: "full-access", - interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, - branch: null, - worktreePath: null, - createdAt, - }), - ); - - await expect( - system.run( - system.engine.dispatch({ - type: "manager.refiner-thread.create", - commandId: CommandId.make("cmd-manager-create-refiner-thread-second"), - threadId: ThreadId.make("refiner-thread-2"), - managerThreadId: ThreadId.make("manager-console"), - seededWorkItemId: "work-refine", - modelSelection: { - instanceId: ProviderInstanceId.make("codex"), - model: "gpt-5-codex", - }, - runtimeMode: "full-access", - interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, - branch: null, - worktreePath: null, - createdAt, - }), - ), - ).rejects.toThrow("already has active Refiner Thread"); - - await system.dispose(); - }); - - it("records a refinement handoff on the originating work item and auto-requests delegation when it becomes ready", async () => { - // @effect-diagnostics-next-line cryptoRandomUUID:off - const dbPath = `/tmp/t3-manager-refinement-handoff-${crypto.randomUUID()}.sqlite`; - const firstSystem = await createOrchestrationSystem({ dbPath }); - const createdAt = now(); - const handoffAt = "2026-01-01T00:00:05.000Z"; - - await firstSystem.run( - firstSystem.engine.dispatch({ - type: "manager.bootstrap", - commandId: CommandId.make("cmd-manager-bootstrap-handoff"), - projectId: asProjectId("manager-workspace"), - threadId: ThreadId.make("manager-console"), - workspaceRoot: "/tmp/manager-workspace", - modelSelection: { - instanceId: ProviderInstanceId.make("codex"), - model: "gpt-5-codex", - }, - runtimeMode: "full-access", - interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, - createdAt, - }), - ); - await firstSystem.run( - firstSystem.engine.dispatch({ - type: "project.create", - commandId: CommandId.make("cmd-project-handoff"), - projectId: asProjectId("app-project"), - title: "App Project", - workspaceRoot: "/tmp/app-project", - defaultModelSelection: { - instanceId: ProviderInstanceId.make("codex"), - model: "gpt-5-codex", - }, - createdAt, - }), - ); - await firstSystem.run( - firstSystem.engine.dispatch({ - type: "manager.seed-work-items", - commandId: CommandId.make("cmd-manager-seed-work-handoff"), - threadId: ThreadId.make("manager-console"), - sourceKind: "todo-list", - sourceLabel: "Sprint Backlog", - items: [ - { - itemId: "work-refine", - title: "Clarify billing export", - body: "The export flow is underspecified.", - delegationIntent: "delegate", - targetProjectId: asProjectId("app-project"), - acceptanceCriteria: [], - }, - ], - createdAt, - }), - ); - await firstSystem.run( - firstSystem.engine.dispatch({ - type: "manager.refiner-thread.create", - commandId: CommandId.make("cmd-manager-create-refiner-thread-handoff"), - threadId: ThreadId.make("refiner-thread-1"), - managerThreadId: ThreadId.make("manager-console"), - seededWorkItemId: "work-refine", - modelSelection: { - instanceId: ProviderInstanceId.make("codex"), - model: "gpt-5-codex", - }, - runtimeMode: "full-access", - interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, - branch: null, - worktreePath: null, - createdAt, - }), - ); - await firstSystem.run( - firstSystem.engine.dispatch({ - type: "manager.refinement-handoff.record", - commandId: CommandId.make("cmd-manager-record-refinement-handoff"), - refinerThreadId: ThreadId.make("refiner-thread-1"), - refinedProblemStatement: "Users can export billing data as CSV from the invoices screen.", - acceptanceCriteria: [ - "Invoices screen shows an export action", - "Export downloads a CSV with invoice rows", - ], - targetProjectId: asProjectId("app-project"), - createdAt: handoffAt, - }), - ); - - const detail = Option.getOrNull( - await firstSystem.threadDetail(ThreadId.make("manager-console")), - ); - expect(detail?.seededWorkItems).toEqual([ - expect.objectContaining({ - itemId: "work-refine", - body: "Users can export billing data as CSV from the invoices screen.", - targetProjectId: "app-project", - acceptanceCriteria: [ - "Invoices screen shows an export action", - "Export downloads a CSV with invoice rows", - ], - readiness: "ready-for-worker", - delegationStatus: "requested", - delegationRequestedAt: handoffAt, - refinementHandoff: { - refinerThreadId: "refiner-thread-1", - sourceBody: "The export flow is underspecified.", - refinedProblemStatement: "Users can export billing data as CSV from the invoices screen.", - acceptanceCriteria: [ - "Invoices screen shows an export action", - "Export downloads a CSV with invoice rows", - ], - targetProjectId: "app-project", - recordedAt: handoffAt, - }, - }), - ]); - expect(detail?.activities).toContainEqual( - expect.objectContaining({ - kind: "manager.delegation.requested", - summary: "Auto-requested worker delegation for 'Clarify billing export'.", - payload: { - seededWorkItemId: "work-refine", - refinerThreadId: "refiner-thread-1", - targetProjectId: "app-project", - }, - createdAt: handoffAt, - }), - ); - - await firstSystem.dispose(); - - const secondSystem = await createOrchestrationSystem({ dbPath }); - const reloadedDetail = Option.getOrNull( - await secondSystem.threadDetail(ThreadId.make("manager-console")), - ); - expect(reloadedDetail?.seededWorkItems?.[0]).toEqual( - expect.objectContaining({ - readiness: "ready-for-worker", - delegationStatus: "requested", - delegationRequestedAt: handoffAt, - refinementHandoff: expect.objectContaining({ - refinerThreadId: "refiner-thread-1", - recordedAt: handoffAt, - }), - }), - ); - expect(reloadedDetail?.activities).toContainEqual( - expect.objectContaining({ - kind: "manager.delegation.requested", - createdAt: handoffAt, - }), - ); - - await secondSystem.dispose(); - }); - it("creates a delegated Worker Thread with project-local metadata through the full delegation flow", async () => { - // @effect-diagnostics-next-line cryptoRandomUUID:off - const dbPath = `/tmp/t3-worker-delegate-${crypto.randomUUID()}.sqlite`; - const firstSystem = await createOrchestrationSystem({ dbPath }); - const createdAt = now(); - const handoffAt = "2026-01-01T00:00:05.000Z"; - const delegateAt = "2026-01-01T00:00:10.000Z"; - - await firstSystem.run( - firstSystem.engine.dispatch({ - type: "manager.bootstrap", - commandId: CommandId.make("cmd-manager-bootstrap-delegate"), - projectId: asProjectId("manager-workspace"), - threadId: ThreadId.make("manager-console"), - workspaceRoot: "/tmp/manager-workspace", - modelSelection: { - instanceId: ProviderInstanceId.make("codex"), - model: "gpt-5-codex", - }, - runtimeMode: "full-access", - interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, - createdAt, - }), - ); - await firstSystem.run( - firstSystem.engine.dispatch({ - type: "project.create", - commandId: CommandId.make("cmd-project-delegate"), - projectId: asProjectId("app-project"), - title: "App Project", - workspaceRoot: "/tmp/app-project", - defaultModelSelection: { - instanceId: ProviderInstanceId.make("codex"), - model: "gpt-5-codex", - }, - createdAt, - }), - ); - await firstSystem.run( - firstSystem.engine.dispatch({ - type: "manager.seed-work-items", - commandId: CommandId.make("cmd-manager-seed-work-delegate"), - threadId: ThreadId.make("manager-console"), - sourceKind: "jira-set", - sourceLabel: "Jira Backlog", - items: [ - { - itemId: "work-1", - title: "Add CSV billing export", - body: "Original Jira issue description for billing export feature.", - delegationIntent: "delegate", - targetProjectId: asProjectId("app-project"), - acceptanceCriteria: [], - }, - ], - createdAt, - }), - ); - await firstSystem.run( - firstSystem.engine.dispatch({ - type: "manager.refiner-thread.create", - commandId: CommandId.make("cmd-manager-create-refiner-delegate"), - threadId: ThreadId.make("refiner-thread-1"), - managerThreadId: ThreadId.make("manager-console"), - seededWorkItemId: "work-1", - modelSelection: { - instanceId: ProviderInstanceId.make("codex"), - model: "gpt-5-codex", - }, - runtimeMode: "full-access", - interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, - branch: null, - worktreePath: null, - createdAt, - }), - ); - await firstSystem.run( - firstSystem.engine.dispatch({ - type: "manager.refinement-handoff.record", - commandId: CommandId.make("cmd-manager-record-handoff-delegate"), - refinerThreadId: ThreadId.make("refiner-thread-1"), - refinedProblemStatement: "Users can export billing history as CSV from the invoices page.", - acceptanceCriteria: [ - "CSV export button visible on invoices page", - "Downloaded CSV contains invoice rows with correct columns", - ], - targetProjectId: asProjectId("app-project"), - createdAt: handoffAt, - }), - ); - - await firstSystem.run( - firstSystem.engine.dispatch({ - type: "worker.delegate", - commandId: CommandId.make("cmd-worker-delegate"), - workerThreadId: ThreadId.make("worker-thread-1"), - refinerThreadId: ThreadId.make("refiner-thread-1"), - modelSelection: { - instanceId: ProviderInstanceId.make("codex"), - model: "gpt-5-codex", - }, - runtimeMode: "auto-accept-edits", - interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, - branch: null, - worktreePath: null, - createdAt: delegateAt, - }), - ); - - const workerDetail = Option.getOrNull( - await firstSystem.threadDetail(ThreadId.make("worker-thread-1")), - ); - expect(workerDetail).toEqual( - expect.objectContaining({ - id: ThreadId.make("worker-thread-1"), - projectId: asProjectId("app-project"), - title: "Add CSV billing export", - managerMetadata: { - role: "worker", - managerThreadId: ThreadId.make("manager-console"), - seededWorkItemId: "work-1", - sourceBody: "Original Jira issue description for billing export feature.", - refinedBrief: "Users can export billing history as CSV from the invoices page.", - acceptanceCriteria: [ - "CSV export button visible on invoices page", - "Downloaded CSV contains invoice rows with correct columns", - ], - }, - }), - ); - - await firstSystem.dispose(); - - const secondSystem = await createOrchestrationSystem({ dbPath }); - const reloadedWorker = Option.getOrNull( - await secondSystem.threadDetail(ThreadId.make("worker-thread-1")), - ); - expect(reloadedWorker?.managerMetadata).toEqual({ - role: "worker", - managerThreadId: ThreadId.make("manager-console"), - seededWorkItemId: "work-1", - sourceBody: "Original Jira issue description for billing export feature.", - refinedBrief: "Users can export billing history as CSV from the invoices page.", - acceptanceCriteria: [ - "CSV export button visible on invoices page", - "Downloaded CSV contains invoice rows with correct columns", - ], - }); - - await secondSystem.dispose(); - }); it("archives and unarchives threads through orchestration commands", async () => { const system = await createOrchestrationSystem(); const { engine } = system; diff --git a/apps/server/src/orchestration/Layers/OrchestrationEngine.ts b/apps/server/src/orchestration/Layers/OrchestrationEngine.ts index 91f9948f92f0..7277663e9485 100644 --- a/apps/server/src/orchestration/Layers/OrchestrationEngine.ts +++ b/apps/server/src/orchestration/Layers/OrchestrationEngine.ts @@ -62,23 +62,12 @@ function commandToAggregateRef(command: OrchestrationCommand): { } { switch (command.type) { case "project.create": - case "manager.bootstrap": case "project.meta.update": case "project.delete": return { aggregateKind: "project", aggregateId: command.projectId, }; - case "manager.refinement-handoff.record": - return { - aggregateKind: "thread", - aggregateId: command.refinerThreadId, - }; - case "worker.delegate": - return { - aggregateKind: "thread", - aggregateId: command.workerThreadId, - }; default: return { aggregateKind: "thread", diff --git a/apps/server/src/orchestration/Layers/OrchestrationReactor.test.ts b/apps/server/src/orchestration/Layers/OrchestrationReactor.test.ts index db2029740367..300d1526bb9a 100644 --- a/apps/server/src/orchestration/Layers/OrchestrationReactor.test.ts +++ b/apps/server/src/orchestration/Layers/OrchestrationReactor.test.ts @@ -8,7 +8,6 @@ import { afterEach, describe, expect, it } from "vite-plus/test"; import { CheckpointReactor } from "../Services/CheckpointReactor.ts"; import { ProviderCommandReactor } from "../Services/ProviderCommandReactor.ts"; import { ProviderRuntimeIngestionService } from "../Services/ProviderRuntimeIngestion.ts"; -import { SeededWorkItemWritebackReactor } from "../Services/SeededWorkItemWritebackReactor.ts"; import { ThreadDeletionReactor } from "../Services/ThreadDeletionReactor.ts"; import { OrchestrationReactor } from "../Services/OrchestrationReactor.ts"; import { makeOrchestrationReactor } from "./OrchestrationReactor.ts"; @@ -24,7 +23,7 @@ describe("OrchestrationReactor", () => { runtime = null; }); - it("starts provider ingestion, provider command, checkpoint, writeback, and thread deletion reactors", async () => { + it("starts provider ingestion, provider command, checkpoint, and thread deletion reactors", async () => { const started: string[] = []; runtime = ManagedRuntime.make( @@ -56,15 +55,6 @@ describe("OrchestrationReactor", () => { drain: Effect.void, }), ), - Layer.provideMerge( - Layer.succeed(SeededWorkItemWritebackReactor, { - start: () => { - started.push("seeded-work-item-writeback-reactor"); - return Effect.void; - }, - drain: Effect.void, - }), - ), Layer.provideMerge( Layer.succeed(ThreadDeletionReactor, { start: () => { @@ -94,7 +84,6 @@ describe("OrchestrationReactor", () => { "provider-runtime-ingestion", "provider-command-reactor", "checkpoint-reactor", - "seeded-work-item-writeback-reactor", "thread-deletion-reactor", "agent-awareness-relay", ]); diff --git a/apps/server/src/orchestration/Layers/OrchestrationReactor.ts b/apps/server/src/orchestration/Layers/OrchestrationReactor.ts index 5fc976f0bd14..fb7543e31af0 100644 --- a/apps/server/src/orchestration/Layers/OrchestrationReactor.ts +++ b/apps/server/src/orchestration/Layers/OrchestrationReactor.ts @@ -8,7 +8,6 @@ import { import { CheckpointReactor } from "../Services/CheckpointReactor.ts"; import { ProviderCommandReactor } from "../Services/ProviderCommandReactor.ts"; import { ProviderRuntimeIngestionService } from "../Services/ProviderRuntimeIngestion.ts"; -import { SeededWorkItemWritebackReactor } from "../Services/SeededWorkItemWritebackReactor.ts"; import { ThreadDeletionReactor } from "../Services/ThreadDeletionReactor.ts"; import * as AgentAwarenessRelay from "../../relay/AgentAwarenessRelay.ts"; @@ -16,7 +15,6 @@ export const makeOrchestrationReactor = Effect.gen(function* () { const providerRuntimeIngestion = yield* ProviderRuntimeIngestionService; const providerCommandReactor = yield* ProviderCommandReactor; const checkpointReactor = yield* CheckpointReactor; - const seededWorkItemWritebackReactor = yield* SeededWorkItemWritebackReactor; const threadDeletionReactor = yield* ThreadDeletionReactor; const agentAwarenessRelay = yield* AgentAwarenessRelay.AgentAwarenessRelay; @@ -24,7 +22,6 @@ export const makeOrchestrationReactor = Effect.gen(function* () { yield* providerRuntimeIngestion.start(); yield* providerCommandReactor.start(); yield* checkpointReactor.start(); - yield* seededWorkItemWritebackReactor.start(); yield* threadDeletionReactor.start(); yield* agentAwarenessRelay.start(); }); diff --git a/apps/server/src/orchestration/Layers/ProjectionPipeline.ts b/apps/server/src/orchestration/Layers/ProjectionPipeline.ts index 4ffe605dd93d..4a48de19d39c 100644 --- a/apps/server/src/orchestration/Layers/ProjectionPipeline.ts +++ b/apps/server/src/orchestration/Layers/ProjectionPipeline.ts @@ -468,9 +468,6 @@ const makeOrchestrationProjectionPipeline = Effect.fn("makeOrchestrationProjecti projectId: event.payload.projectId, title: event.payload.title, workspaceRoot: event.payload.workspaceRoot, - ...(event.payload.managerMetadata !== undefined - ? { managerMetadata: event.payload.managerMetadata } - : {}), defaultModelSelection: event.payload.defaultModelSelection, scripts: event.payload.scripts, createdAt: event.payload.createdAt, @@ -575,9 +572,6 @@ const makeOrchestrationProjectionPipeline = Effect.fn("makeOrchestrationProjecti threadId: event.payload.threadId, projectId: event.payload.projectId, title: event.payload.title, - ...(event.payload.managerMetadata !== undefined - ? { managerMetadata: event.payload.managerMetadata } - : {}), modelSelection: event.payload.modelSelection, runtimeMode: event.payload.runtimeMode, interactionMode: event.payload.interactionMode, @@ -587,7 +581,6 @@ const makeOrchestrationProjectionPipeline = Effect.fn("makeOrchestrationProjecti createdAt: event.payload.createdAt, updatedAt: event.payload.updatedAt, archivedAt: null, - seededWorkItems: [], latestUserMessageAt: null, pendingApprovalCount: 0, pendingUserInputCount: 0, @@ -648,21 +641,6 @@ const makeOrchestrationProjectionPipeline = Effect.fn("makeOrchestrationProjecti return; } - case "thread.seeded-work-items-upserted": { - const existingRow = yield* projectionThreadRepository.getById({ - threadId: event.payload.threadId, - }); - if (Option.isNone(existingRow)) { - return; - } - yield* projectionThreadRepository.upsert({ - ...existingRow.value, - seededWorkItems: event.payload.seededWorkItems, - updatedAt: event.payload.updatedAt, - }); - return; - } - case "thread.runtime-mode-set": { const existingRow = yield* projectionThreadRepository.getById({ threadId: event.payload.threadId, diff --git a/apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.test.ts b/apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.test.ts index 12b621b851fc..f478b11c81da 100644 --- a/apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.test.ts +++ b/apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.test.ts @@ -310,7 +310,6 @@ projectionSnapshotLayer("ProjectionSnapshotQuery", (it) => { updatedAt: "2026-02-24T00:00:03.000Z", archivedAt: null, deletedAt: null, - seededWorkItems: [], messages: [ { id: asMessageId("message-1"), diff --git a/apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts b/apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts index 160fa99765b0..5a1ee183167e 100644 --- a/apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts +++ b/apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts @@ -1,23 +1,16 @@ import { ChatAttachment, + ContextTrimPoint, CheckpointRef, - DEFAULT_RUNTIME_MODE, IsoDateTime, - ManagerProjectMetadata, - ManagerSeededWorkItem, - ManagerThreadMetadata, MessageId, - ModelSelection, NonNegativeInt, OrchestrationCheckpointFile, OrchestrationProposedPlanId, OrchestrationReadModel, OrchestrationShellSnapshot, OrchestrationThread, - ProjectId, ProjectScript, - RuntimeMode, - ThreadId, TurnId, type OrchestrationCheckpointSummary, type OrchestrationLatestTurn, @@ -28,6 +21,10 @@ import { type OrchestrationSession, type OrchestrationThreadActivity, type OrchestrationThreadShell, + ModelSelection, + ProjectId, + ThreadId, + ThreadTrimPointCreatedPayload, } from "@t3tools/contracts"; import * as Arr from "effect/Array"; import * as Effect from "effect/Effect"; @@ -66,17 +63,12 @@ import { const decodeReadModel = Schema.decodeUnknownEffect(OrchestrationReadModel); const decodeShellSnapshot = Schema.decodeUnknownEffect(OrchestrationShellSnapshot); const decodeThread = Schema.decodeUnknownEffect(OrchestrationThread); -const ProjectionProjectDbRowSchema = Schema.Struct({ - projectId: ProjectionProject.fields.projectId, - title: ProjectionProject.fields.title, - workspaceRoot: ProjectionProject.fields.workspaceRoot, - managerMetadata: Schema.NullOr(Schema.fromJsonString(ManagerProjectMetadata)), - defaultModelSelection: Schema.NullOr(Schema.fromJsonString(ModelSelection)), - scripts: Schema.fromJsonString(Schema.Array(ProjectScript)), - createdAt: ProjectionProject.fields.createdAt, - updatedAt: ProjectionProject.fields.updatedAt, - deletedAt: ProjectionProject.fields.deletedAt, -}); +const ProjectionProjectDbRowSchema = ProjectionProject.mapFields( + Struct.assign({ + defaultModelSelection: Schema.NullOr(Schema.fromJsonString(ModelSelection)), + scripts: Schema.fromJsonString(Schema.Array(ProjectScript)), + }), +); const ProjectionThreadMessageDbRowSchema = ProjectionThreadMessage.mapFields( Struct.assign({ isStreaming: Schema.Number, @@ -84,27 +76,11 @@ const ProjectionThreadMessageDbRowSchema = ProjectionThreadMessage.mapFields( }), ); const ProjectionThreadProposedPlanDbRowSchema = ProjectionThreadProposedPlan; -const ProjectionThreadDbRowSchema = Schema.Struct({ - threadId: ProjectionThread.fields.threadId, - projectId: ProjectionThread.fields.projectId, - title: ProjectionThread.fields.title, - managerMetadata: Schema.NullOr(Schema.fromJsonString(ManagerThreadMetadata)), - modelSelection: Schema.fromJsonString(ModelSelection), - runtimeMode: RuntimeMode.pipe(Schema.withDecodingDefault(Effect.succeed(DEFAULT_RUNTIME_MODE))), - interactionMode: ProjectionThread.fields.interactionMode, - branch: ProjectionThread.fields.branch, - worktreePath: ProjectionThread.fields.worktreePath, - latestTurnId: ProjectionThread.fields.latestTurnId, - createdAt: ProjectionThread.fields.createdAt, - updatedAt: ProjectionThread.fields.updatedAt, - archivedAt: ProjectionThread.fields.archivedAt, - seededWorkItems: Schema.fromJsonString(Schema.Array(ManagerSeededWorkItem)), - latestUserMessageAt: ProjectionThread.fields.latestUserMessageAt, - pendingApprovalCount: ProjectionThread.fields.pendingApprovalCount, - pendingUserInputCount: ProjectionThread.fields.pendingUserInputCount, - hasActionableProposedPlan: ProjectionThread.fields.hasActionableProposedPlan, - deletedAt: ProjectionThread.fields.deletedAt, -}); +const ProjectionThreadDbRowSchema = ProjectionThread.mapFields( + Struct.assign({ + modelSelection: Schema.fromJsonString(ModelSelection), + }), +); const ProjectionThreadActivityDbRowSchema = ProjectionThreadActivity.mapFields( Struct.assign({ payload: Schema.fromJsonString(Schema.Unknown), @@ -133,6 +109,11 @@ const ProjectionCountsRowSchema = Schema.Struct({ projectCount: Schema.Number, threadCount: Schema.Number, }); +const ContextTrimPointEventRowSchema = Schema.Struct({ + threadId: ThreadId, + sequence: NonNegativeInt, + payload: Schema.fromJsonString(ThreadTrimPointCreatedPayload), +}); const WorkspaceRootLookupInput = Schema.Struct({ workspaceRoot: Schema.String, }); @@ -257,7 +238,6 @@ function mapProjectShellRow( id: row.projectId, title: row.title, workspaceRoot: row.workspaceRoot, - ...(row.managerMetadata !== null ? { managerMetadata: row.managerMetadata } : {}), repositoryIdentity, defaultModelSelection: row.defaultModelSelection, scripts: row.scripts, @@ -332,7 +312,6 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () { project_id AS "projectId", title, workspace_root AS "workspaceRoot", - manager_metadata_json AS "managerMetadata", default_model_selection_json AS "defaultModelSelection", scripts_json AS "scripts", created_at AS "createdAt", @@ -352,7 +331,6 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () { thread_id AS "threadId", project_id AS "projectId", title, - manager_metadata_json AS "managerMetadata", model_selection_json AS "modelSelection", runtime_mode AS "runtimeMode", interaction_mode AS "interactionMode", @@ -362,7 +340,6 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () { created_at AS "createdAt", updated_at AS "updatedAt", archived_at AS "archivedAt", - seeded_work_items_json AS "seededWorkItems", latest_user_message_at AS "latestUserMessageAt", pending_approval_count AS "pendingApprovalCount", pending_user_input_count AS "pendingUserInputCount", @@ -373,6 +350,30 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () { `, }); + const listContextTrimPointRows = SqlSchema.findAll({ + Request: Schema.Void, + Result: ContextTrimPointEventRowSchema, + execute: () => sql` + SELECT stream_id AS "threadId", sequence, payload_json AS "payload" + FROM orchestration_events + WHERE aggregate_kind = 'thread' AND event_type = 'thread.trim-point-created' + ORDER BY sequence ASC + `, + }); + + const listContextTrimPointRowsByThread = SqlSchema.findAll({ + Request: ThreadIdLookupInput, + Result: ContextTrimPointEventRowSchema, + execute: ({ threadId }) => sql` + SELECT stream_id AS "threadId", sequence, payload_json AS "payload" + FROM orchestration_events + WHERE aggregate_kind = 'thread' + AND event_type = 'thread.trim-point-created' + AND stream_id = ${threadId} + ORDER BY sequence ASC + `, + }); + const listActiveThreadRows = SqlSchema.findAll({ Request: Schema.Void, Result: ProjectionThreadDbRowSchema, @@ -382,7 +383,6 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () { thread_id AS "threadId", project_id AS "projectId", title, - manager_metadata_json AS "managerMetadata", model_selection_json AS "modelSelection", runtime_mode AS "runtimeMode", interaction_mode AS "interactionMode", @@ -392,7 +392,6 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () { created_at AS "createdAt", updated_at AS "updatedAt", archived_at AS "archivedAt", - seeded_work_items_json AS "seededWorkItems", latest_user_message_at AS "latestUserMessageAt", pending_approval_count AS "pendingApprovalCount", pending_user_input_count AS "pendingUserInputCount", @@ -414,7 +413,6 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () { thread_id AS "threadId", project_id AS "projectId", title, - manager_metadata_json AS "managerMetadata", model_selection_json AS "modelSelection", runtime_mode AS "runtimeMode", interaction_mode AS "interactionMode", @@ -424,7 +422,6 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () { created_at AS "createdAt", updated_at AS "updatedAt", archived_at AS "archivedAt", - seeded_work_items_json AS "seededWorkItems", latest_user_message_at AS "latestUserMessageAt", pending_approval_count AS "pendingApprovalCount", pending_user_input_count AS "pendingUserInputCount", @@ -700,7 +697,6 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () { project_id AS "projectId", title, workspace_root AS "workspaceRoot", - manager_metadata_json AS "managerMetadata", default_model_selection_json AS "defaultModelSelection", scripts_json AS "scripts", created_at AS "createdAt", @@ -723,7 +719,6 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () { project_id AS "projectId", title, workspace_root AS "workspaceRoot", - manager_metadata_json AS "managerMetadata", default_model_selection_json AS "defaultModelSelection", scripts_json AS "scripts", created_at AS "createdAt", @@ -780,7 +775,6 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () { thread_id AS "threadId", project_id AS "projectId", title, - manager_metadata_json AS "managerMetadata", model_selection_json AS "modelSelection", runtime_mode AS "runtimeMode", interaction_mode AS "interactionMode", @@ -790,7 +784,6 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () { created_at AS "createdAt", updated_at AS "updatedAt", archived_at AS "archivedAt", - seeded_work_items_json AS "seededWorkItems", latest_user_message_at AS "latestUserMessageAt", pending_approval_count AS "pendingApprovalCount", pending_user_input_count AS "pendingUserInputCount", @@ -1036,6 +1029,14 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () { ), ), ), + listContextTrimPointRows(undefined).pipe( + Effect.mapError( + toPersistenceSqlOrDecodeError( + "ProjectionSnapshotQuery.getSnapshot:listContextTrimPoints:query", + "ProjectionSnapshotQuery.getSnapshot:listContextTrimPoints:decodeRows", + ), + ), + ), listProjectionStateRows(undefined).pipe( Effect.mapError( toPersistenceSqlOrDecodeError( @@ -1057,6 +1058,7 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () { sessionRows, checkpointRows, latestTurnRows, + contextTrimPointRows, stateRows, ]) => Effect.gen(function* () { @@ -1066,6 +1068,7 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () { const checkpointsByThread = new Map>(); const sessionsByThread = new Map(); const latestTurnByThread = new Map(); + const contextTrimPointsByThread = new Map(); let updatedAt: string | null = null; @@ -1095,6 +1098,12 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () { messagesByThread.set(row.threadId, threadMessages); } + for (const row of contextTrimPointRows) { + const points = contextTrimPointsByThread.get(row.threadId) ?? []; + points.push(row.payload.trimPoint); + contextTrimPointsByThread.set(row.threadId, points); + } + for (const row of proposedPlanRows) { updatedAt = maxIso(updatedAt, row.updatedAt); const threadProposedPlans = proposedPlansByThread.get(row.threadId) ?? []; @@ -1202,7 +1211,6 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () { id: row.projectId, title: row.title, workspaceRoot: row.workspaceRoot, - ...(row.managerMetadata !== null ? { managerMetadata: row.managerMetadata } : {}), repositoryIdentity: repositoryIdentities.get(row.projectId) ?? null, defaultModelSelection: row.defaultModelSelection, scripts: row.scripts, @@ -1215,7 +1223,6 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () { id: row.threadId, projectId: row.projectId, title: row.title, - ...(row.managerMetadata !== null ? { managerMetadata: row.managerMetadata } : {}), modelSelection: row.modelSelection, runtimeMode: row.runtimeMode, interactionMode: row.interactionMode, @@ -1227,11 +1234,10 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () { archivedAt: row.archivedAt, deletedAt: row.deletedAt, messages: messagesByThread.get(row.threadId) ?? [], - seededWorkItems: row.seededWorkItems, proposedPlans: proposedPlansByThread.get(row.threadId) ?? [], activities: activitiesByThread.get(row.threadId) ?? [], checkpoints: checkpointsByThread.get(row.threadId) ?? [], - contextTrimPoints: [], + contextTrimPoints: contextTrimPointsByThread.get(row.threadId) ?? [], session: sessionsByThread.get(row.threadId) ?? null, })); @@ -1277,6 +1283,14 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () { ), ), ), + listThreadMessageRows(undefined).pipe( + Effect.mapError( + toPersistenceSqlOrDecodeError( + "ProjectionSnapshotQuery.getCommandReadModel:listThreadMessages:query", + "ProjectionSnapshotQuery.getCommandReadModel:listThreadMessages:decodeRows", + ), + ), + ), listThreadProposedPlanRows(undefined).pipe( Effect.mapError( toPersistenceSqlOrDecodeError( @@ -1301,6 +1315,14 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () { ), ), ), + listContextTrimPointRows(undefined).pipe( + Effect.mapError( + toPersistenceSqlOrDecodeError( + "ProjectionSnapshotQuery.getCommandReadModel:listContextTrimPoints:query", + "ProjectionSnapshotQuery.getCommandReadModel:listContextTrimPoints:decodeRows", + ), + ), + ), listProjectionStateRows(undefined).pipe( Effect.mapError( toPersistenceSqlOrDecodeError( @@ -1313,11 +1335,22 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () { ) .pipe( Effect.flatMap( - ([projectRows, threadRows, proposedPlanRows, sessionRows, latestTurnRows, stateRows]) => + ([ + projectRows, + threadRows, + messageRows, + proposedPlanRows, + sessionRows, + latestTurnRows, + contextTrimPointRows, + stateRows, + ]) => Effect.sync(() => { let updatedAt: string | null = null; const projects: OrchestrationProject[] = []; const threads: OrchestrationThread[] = []; + const messagesByThread = new Map(); + const contextTrimPointsByThread = new Map(); for (let index = 0; index < projectRows.length; index += 1) { const row = projectRows[index]; @@ -1329,7 +1362,6 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () { id: row.projectId, title: row.title, workspaceRoot: row.workspaceRoot, - ...(row.managerMetadata !== null ? { managerMetadata: row.managerMetadata } : {}), defaultModelSelection: row.defaultModelSelection, scripts: row.scripts, createdAt: row.createdAt, @@ -1344,6 +1376,25 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () { } updatedAt = maxIso(updatedAt, row.updatedAt); } + for (const row of messageRows) { + const messages = messagesByThread.get(row.threadId) ?? []; + messages.push({ + id: row.messageId, + role: row.role, + text: row.text, + ...(row.attachments !== null ? { attachments: row.attachments } : {}), + turnId: row.turnId, + streaming: row.isStreaming === 1, + createdAt: row.createdAt, + updatedAt: row.updatedAt, + }); + messagesByThread.set(row.threadId, messages); + } + for (const row of contextTrimPointRows) { + const points = contextTrimPointsByThread.get(row.threadId) ?? []; + points.push(row.payload.trimPoint); + contextTrimPointsByThread.set(row.threadId, points); + } for (let index = 0; index < proposedPlanRows.length; index += 1) { const row = proposedPlanRows[index]; if (!row) { @@ -1417,7 +1468,6 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () { id: row.threadId, projectId: row.projectId, title: row.title, - ...(row.managerMetadata !== null ? { managerMetadata: row.managerMetadata } : {}), modelSelection: row.modelSelection, runtimeMode: row.runtimeMode, interactionMode: row.interactionMode, @@ -1428,12 +1478,11 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () { updatedAt: row.updatedAt, archivedAt: row.archivedAt, deletedAt: row.deletedAt, - messages: [], - seededWorkItems: row.seededWorkItems, + messages: messagesByThread.get(row.threadId) ?? [], proposedPlans: proposedPlansByThread.get(row.threadId) ?? [], activities: [], checkpoints: [], - contextTrimPoints: [], + contextTrimPoints: contextTrimPointsByThread.get(row.threadId) ?? [], session: sessionByThread.get(row.threadId) ?? null, }); } @@ -1563,10 +1612,7 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () { hasPendingApprovals: row.pendingApprovalCount > 0, hasPendingUserInput: row.pendingUserInputCount > 0, hasActionableProposedPlan: row.hasActionableProposedPlan > 0, - ...(row.managerMetadata !== null - ? { managerMetadata: row.managerMetadata } - : {}), - } as OrchestrationThreadShell) + } satisfies OrchestrationThreadShell) : Result.failVoid, ), updatedAt: updatedAt ?? "1970-01-01T00:00:00.000Z", @@ -1686,7 +1732,6 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () { id: row.threadId, projectId: row.projectId, title: row.title, - ...(row.managerMetadata !== null ? { managerMetadata: row.managerMetadata } : {}), modelSelection: row.modelSelection, runtimeMode: row.runtimeMode, interactionMode: row.interactionMode, @@ -1927,9 +1972,6 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () { id: threadRow.value.threadId, projectId: threadRow.value.projectId, title: threadRow.value.title, - ...(threadRow.value.managerMetadata !== null - ? { managerMetadata: threadRow.value.managerMetadata } - : {}), modelSelection: threadRow.value.modelSelection, runtimeMode: threadRow.value.runtimeMode, interactionMode: threadRow.value.interactionMode, @@ -1957,6 +1999,7 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () { checkpointRows, latestTurnRow, sessionRow, + contextTrimPointRows, ] = yield* Effect.all([ getActiveThreadRowById({ threadId }).pipe( Effect.mapError( @@ -2014,6 +2057,14 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () { ), ), ), + listContextTrimPointRowsByThread({ threadId }).pipe( + Effect.mapError( + toPersistenceSqlOrDecodeError( + "ProjectionSnapshotQuery.getThreadDetailById:listContextTrimPoints:query", + "ProjectionSnapshotQuery.getThreadDetailById:listContextTrimPoints:decodeRows", + ), + ), + ), ]); if (Option.isNone(threadRow)) { @@ -2024,9 +2075,6 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () { id: threadRow.value.threadId, projectId: threadRow.value.projectId, title: threadRow.value.title, - ...(threadRow.value.managerMetadata !== null - ? { managerMetadata: threadRow.value.managerMetadata } - : {}), modelSelection: threadRow.value.modelSelection, runtimeMode: threadRow.value.runtimeMode, interactionMode: threadRow.value.interactionMode, @@ -2052,7 +2100,6 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () { } return message; }), - seededWorkItems: threadRow.value.seededWorkItems, proposedPlans: proposedPlanRows.map(mapProposedPlanRow), activities: activityRows.map((row) => { const activity = { @@ -2078,6 +2125,7 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () { assistantMessageId: row.assistantMessageId, completedAt: row.completedAt, })), + contextTrimPoints: contextTrimPointRows.map((row) => row.payload.trimPoint), session: Option.isSome(sessionRow) ? mapSessionRow(sessionRow.value) : null, }; diff --git a/apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts b/apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts index 96e191300a39..739cea68d929 100644 --- a/apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts +++ b/apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts @@ -28,6 +28,7 @@ import * as ManagedRuntime from "effect/ManagedRuntime"; import * as PubSub from "effect/PubSub"; import * as Scope from "effect/Scope"; import * as Stream from "effect/Stream"; +import { it as effectIt } from "@effect/vitest"; import { afterEach, describe, expect, it, vi } from "vite-plus/test"; import { deriveServerPaths, ServerConfig } from "../../config.ts"; @@ -40,6 +41,7 @@ import { ProviderService, type ProviderServiceShape, } from "../../provider/Services/ProviderService.ts"; +import { makeProviderRegistryLayer } from "../../provider/testUtils/providerRegistryMock.ts"; import { TextGeneration, type TextGenerationShape } from "../../textGeneration/TextGeneration.ts"; import { RepositoryIdentityResolverLive } from "../../project/Layers/RepositoryIdentityResolver.ts"; import { OrchestrationEngineLive } from "./OrchestrationEngine.ts"; @@ -142,6 +144,7 @@ describe("ProviderCommandReactor", () => { readonly baseDir?: string; readonly threadModelSelection?: ModelSelection; readonly sessionModelSwitch?: "unsupported" | "in-session"; + readonly requiresNewThreadForModelChange?: boolean; }) { const now = "2026-01-01T00:00:00.000Z"; const baseDir = input?.baseDir ?? fs.mkdtempSync(path.join(os.tmpdir(), "t3code-reactor-")); @@ -280,6 +283,14 @@ describe("ProviderCommandReactor", () => { }), ), ); + const providerSnapshots = [ + { + instanceId: modelSelection.instanceId, + ...(input?.requiresNewThreadForModelChange === true + ? { requiresNewThreadForModelChange: true } + : {}), + }, + ]; const unsupported = () => Effect.die(new Error("Unsupported provider call in test")) as never; const service: ProviderServiceShape = { @@ -341,6 +352,7 @@ describe("ProviderCommandReactor", () => { Layer.provideMerge(orchestrationLayer), Layer.provideMerge(projectionSnapshotLayer), Layer.provideMerge(Layer.succeed(ProviderService, service)), + Layer.provideMerge(makeProviderRegistryLayer(providerSnapshots as never)), Layer.provideMerge( Layer.mock(GitWorkflowService)({ renameBranch, @@ -885,6 +897,80 @@ describe("ProviderCommandReactor", () => { }); }); + effectIt.effect( + "rejects changing models after start when the provider requires a new thread", + () => + Effect.gen(function* () { + const harness = yield* Effect.promise(() => + createHarness({ requiresNewThreadForModelChange: true }), + ); + const now = "2026-01-01T00:00:00.000Z"; + + yield* harness.engine.dispatch({ + type: "thread.turn.start", + commandId: CommandId.make("cmd-turn-start-restricted-1"), + threadId: ThreadId.make("thread-1"), + message: { + messageId: asMessageId("user-message-restricted-1"), + role: "user", + text: "first", + attachments: [], + }, + interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, + runtimeMode: "approval-required", + createdAt: now, + }); + + yield* Effect.promise(() => waitFor(() => harness.sendTurn.mock.calls.length === 1)); + + yield* harness.engine.dispatch({ + type: "thread.turn.start", + commandId: CommandId.make("cmd-turn-start-restricted-2"), + threadId: ThreadId.make("thread-1"), + message: { + messageId: asMessageId("user-message-restricted-2"), + role: "user", + text: "second", + attachments: [], + }, + modelSelection: { + instanceId: ProviderInstanceId.make("codex"), + model: "gpt-5.1-codex", + }, + interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, + runtimeMode: "approval-required", + createdAt: now, + }); + + yield* Effect.promise(() => + waitFor(async () => { + const readModel = await harness.readModel(); + const thread = readModel.threads.find( + (entry) => entry.id === ThreadId.make("thread-1"), + ); + return ( + thread?.activities.some( + (activity) => activity.kind === "provider.turn.start.failed", + ) ?? false + ); + }), + ); + + expect(harness.sendTurn).toHaveBeenCalledTimes(1); + const readModel = yield* Effect.promise(() => harness.readModel()); + const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1")); + expect( + thread?.activities.find((activity) => activity.kind === "provider.turn.start.failed"), + ).toMatchObject({ + payload: { + detail: expect.stringContaining( + "cannot switch models after the conversation has started", + ), + }, + }); + }), + ); + it("starts a first turn on the requested provider instance even when it differs from the thread model", async () => { const harness = await createHarness({ threadModelSelection: { instanceId: ProviderInstanceId.make("codex"), model: "gpt-5-codex" }, diff --git a/apps/server/src/orchestration/Layers/ProviderCommandReactor.ts b/apps/server/src/orchestration/Layers/ProviderCommandReactor.ts index d64b7ddd3082..966fd3c99e01 100644 --- a/apps/server/src/orchestration/Layers/ProviderCommandReactor.ts +++ b/apps/server/src/orchestration/Layers/ProviderCommandReactor.ts @@ -32,6 +32,7 @@ import { ProviderAdapterRequestError } from "../../provider/Errors.ts"; import type { ProviderServiceError } from "../../provider/Errors.ts"; import { TextGeneration } from "../../textGeneration/TextGeneration.ts"; import { ProviderService } from "../../provider/Services/ProviderService.ts"; +import { ProviderRegistry } from "../../provider/Services/ProviderRegistry.ts"; import { OrchestrationEngineService } from "../Services/OrchestrationEngine.ts"; import { ProjectionSnapshotQuery } from "../Services/ProjectionSnapshotQuery.ts"; import { @@ -182,6 +183,7 @@ const make = Effect.gen(function* () { const orchestrationEngine = yield* OrchestrationEngineService; const projectionSnapshotQuery = yield* ProjectionSnapshotQuery; const providerService = yield* ProviderService; + const providerRegistry = yield* ProviderRegistry; const gitWorkflow = yield* GitWorkflowService; const vcsStatusBroadcaster = yield* VcsStatusBroadcaster; const textGeneration = yield* TextGeneration; @@ -307,6 +309,38 @@ const make = Effect.gen(function* () { .pipe(Effect.map(Option.getOrUndefined)); }); + const rejectStartedThreadModelChangeIfRequired = Effect.fnUntraced(function* (input: { + readonly threadId: ThreadId; + readonly currentModelSelection: ModelSelection; + readonly requestedModelSelection: ModelSelection | undefined; + }) { + const requestedModelSelection = input.requestedModelSelection; + if ( + requestedModelSelection === undefined || + (input.currentModelSelection.instanceId === requestedModelSelection.instanceId && + input.currentModelSelection.model === requestedModelSelection.model) + ) { + return; + } + const providers = yield* providerRegistry.getProviders; + const requiresNewThread = + providers.find((snapshot) => snapshot.instanceId === input.currentModelSelection.instanceId) + ?.requiresNewThreadForModelChange === true || + providers.find((snapshot) => snapshot.instanceId === requestedModelSelection.instanceId) + ?.requiresNewThreadForModelChange === true; + if (!requiresNewThread) { + return; + } + return yield* new ProviderAdapterRequestError({ + provider: providerErrorLabelFromInstanceHint({ + instanceId: String(requestedModelSelection.instanceId), + modelSelectionInstanceId: String(input.currentModelSelection.instanceId), + }), + method: "thread.turn.start", + detail: `Thread '${input.threadId}' cannot switch models after the conversation has started. Start a new thread to use '${requestedModelSelection.model}'.`, + }); + }); + const ensureSessionForThread = Effect.fn("ensureSessionForThread")(function* ( threadId: ThreadId, createdAt: string, @@ -386,6 +420,20 @@ const make = Effect.gen(function* () { }); } const preferredProvider: ProviderDriverKind = desiredDriverKind; + if (thread.session !== null) { + yield* rejectStartedThreadModelChangeIfRequired({ + threadId, + currentModelSelection: + activeSession?.model !== undefined + ? { + ...thread.modelSelection, + instanceId: currentInstanceId, + model: activeSession.model, + } + : thread.modelSelection, + requestedModelSelection, + }); + } if ( thread.session !== null && requestedModelSelection !== undefined && diff --git a/apps/server/src/orchestration/Layers/SeededWorkItemWriteback.ts b/apps/server/src/orchestration/Layers/SeededWorkItemWriteback.ts deleted file mode 100644 index a7afa2472f98..000000000000 --- a/apps/server/src/orchestration/Layers/SeededWorkItemWriteback.ts +++ /dev/null @@ -1,19 +0,0 @@ -import * as Effect from "effect/Effect"; -import * as Layer from "effect/Layer"; - -import { - SeededWorkItemWriteback, - SeededWorkItemWritebackError, - type SeededWorkItemWritebackShape, -} from "../Services/SeededWorkItemWriteback.ts"; - -const make = Effect.succeed({ - append: (input) => - Effect.fail( - new SeededWorkItemWritebackError({ - detail: `Append-only write-back is not configured for source '${input.sourceKind}' (${input.sourceLabel}).`, - }), - ), -} satisfies SeededWorkItemWritebackShape); - -export const SeededWorkItemWritebackLive = Layer.effect(SeededWorkItemWriteback, make); diff --git a/apps/server/src/orchestration/Layers/SeededWorkItemWritebackReactor.test.ts b/apps/server/src/orchestration/Layers/SeededWorkItemWritebackReactor.test.ts deleted file mode 100644 index 16b8a5c454ff..000000000000 --- a/apps/server/src/orchestration/Layers/SeededWorkItemWritebackReactor.test.ts +++ /dev/null @@ -1,201 +0,0 @@ -import { - CommandId, - EventId, - ThreadId, - type OrchestrationCommand, - type OrchestrationEvent, -} from "@t3tools/contracts"; -import * as Clock from "effect/Clock"; -import * as Effect from "effect/Effect"; -import * as Exit from "effect/Exit"; -import * as Layer from "effect/Layer"; -import * as ManagedRuntime from "effect/ManagedRuntime"; -import * as PubSub from "effect/PubSub"; -import * as Scope from "effect/Scope"; -import * as Stream from "effect/Stream"; -import { afterEach, describe, expect, it, vi } from "vite-plus/test"; - -import { OrchestrationEngineService } from "../Services/OrchestrationEngine.ts"; -import { - SeededWorkItemWriteback, - SeededWorkItemWritebackError, - type SeededWorkItemWritebackShape, -} from "../Services/SeededWorkItemWriteback.ts"; -import { SeededWorkItemWritebackReactor } from "../Services/SeededWorkItemWritebackReactor.ts"; -import { SeededWorkItemWritebackReactorLive } from "./SeededWorkItemWritebackReactor.ts"; - -function makeWritebackRequestedEvent(input: { - readonly itemId: string; - readonly sourceKind: "jira-set" | "todo-list"; - readonly sourceLabel: string; - readonly title: string; - readonly writebackKind: "refinement-context" | "worker-progress"; - readonly body: string; -}): Extract { - return { - sequence: 1, - eventId: EventId.make("event-writeback-requested"), - type: "thread.seeded-work-item-writeback-requested", - aggregateKind: "thread", - aggregateId: ThreadId.make("manager-console"), - occurredAt: "2026-01-01T00:00:00.000Z", - commandId: CommandId.make("cmd-writeback-request"), - causationEventId: null, - correlationId: CommandId.make("cmd-writeback-request"), - metadata: {}, - payload: { - threadId: ThreadId.make("manager-console"), - itemId: input.itemId, - sourceKind: input.sourceKind, - sourceLabel: input.sourceLabel, - title: input.title, - writebackKind: input.writebackKind, - body: input.body, - createdAt: "2026-01-01T00:00:00.000Z", - }, - }; -} - -describe("SeededWorkItemWritebackReactor", () => { - let runtime: ManagedRuntime.ManagedRuntime | null = null; - let scope: Scope.Closeable | null = null; - - afterEach(async () => { - if (scope) { - await Effect.runPromise(Scope.close(scope, Exit.void)); - } - scope = null; - if (runtime) { - await runtime.dispose(); - } - runtime = null; - }); - - async function waitFor(predicate: () => boolean, timeoutMs = 2000): Promise { - const deadline = (await Effect.runPromise(Clock.currentTimeMillis)) + timeoutMs; - while (!predicate()) { - if ((await Effect.runPromise(Clock.currentTimeMillis)) >= deadline) { - throw new Error("Timed out waiting for expectation."); - } - await Effect.runPromise(Effect.yieldNow); - } - } - - async function createHarness(append: SeededWorkItemWritebackShape["append"]) { - const domainEvents = Effect.runSync(PubSub.unbounded()); - const dispatch = vi.fn((_command: OrchestrationCommand) => Effect.succeed({ sequence: 1 })); - runtime = ManagedRuntime.make( - SeededWorkItemWritebackReactorLive.pipe( - Layer.provide( - Layer.succeed(OrchestrationEngineService, { - readEvents: () => Stream.empty, - dispatch, - streamDomainEvents: Stream.fromPubSub(domainEvents), - }), - ), - Layer.provide(Layer.succeed(SeededWorkItemWriteback, { append })), - ), - ); - const reactor = await runtime.runPromise(Effect.service(SeededWorkItemWritebackReactor)); - scope = await Effect.runPromise(Scope.make("sequential")); - await Effect.runPromise(reactor.start().pipe(Scope.provide(scope))); - await Effect.runPromise(Effect.yieldNow); - - return { - reactor, - dispatch, - publish: (event: OrchestrationEvent) => - Effect.runPromise(PubSub.publish(domainEvents, event)), - }; - } - - it("dispatches a success activity when refinement context is appended back to a Jira item", async () => { - const append = vi.fn((input: Parameters[0]) => - Effect.succeed({ - externalReference: `jira-comment:${input.itemId}`, - }), - ); - const harness = await createHarness(append); - - await harness.publish( - makeWritebackRequestedEvent({ - itemId: "JIRA-21", - sourceKind: "jira-set", - sourceLabel: "Jira", - title: "Refine manager writeback", - writebackKind: "refinement-context", - body: "Refined problem statement and acceptance criteria.", - }), - ); - await waitFor(() => append.mock.calls.length === 1); - await Effect.runPromise(harness.reactor.drain); - - expect(append).toHaveBeenCalledWith({ - sourceKind: "jira-set", - sourceLabel: "Jira", - itemId: "JIRA-21", - title: "Refine manager writeback", - writebackKind: "refinement-context", - body: "Refined problem statement and acceptance criteria.", - }); - expect(harness.dispatch).toHaveBeenCalledWith( - expect.objectContaining({ - type: "thread.activity.append", - threadId: "manager-console", - activity: expect.objectContaining({ - tone: "info", - kind: "manager.seeded-work-item-writeback.succeeded", - summary: "Appended refinement context back to Jira item JIRA-21.", - payload: expect.objectContaining({ - itemId: "JIRA-21", - sourceKind: "jira-set", - writebackKind: "refinement-context", - externalReference: "jira-comment:JIRA-21", - }), - }), - }), - ); - }); - - it("dispatches a failure activity when worker-progress writeback fails", async () => { - const append = vi.fn(() => - Effect.fail( - new SeededWorkItemWritebackError({ - detail: "Atlassian MCP is unavailable for append-only comments.", - }), - ), - ); - const harness = await createHarness(append); - - await harness.publish( - makeWritebackRequestedEvent({ - itemId: "todo-21", - sourceKind: "todo-list", - sourceLabel: "Todo", - title: "Track worker progress", - writebackKind: "worker-progress", - body: "Worker finished the investigation and is awaiting review.", - }), - ); - await waitFor(() => harness.dispatch.mock.calls.length === 1); - await Effect.runPromise(harness.reactor.drain); - - expect(harness.dispatch).toHaveBeenCalledWith( - expect.objectContaining({ - type: "thread.activity.append", - threadId: "manager-console", - activity: expect.objectContaining({ - tone: "error", - kind: "manager.seeded-work-item-writeback.failed", - summary: "Failed to append worker progress back to Todo item todo-21.", - payload: expect.objectContaining({ - itemId: "todo-21", - sourceKind: "todo-list", - writebackKind: "worker-progress", - detail: "Atlassian MCP is unavailable for append-only comments.", - }), - }), - }), - ); - }); -}); diff --git a/apps/server/src/orchestration/Layers/SeededWorkItemWritebackReactor.ts b/apps/server/src/orchestration/Layers/SeededWorkItemWritebackReactor.ts deleted file mode 100644 index 4485cec4c83a..000000000000 --- a/apps/server/src/orchestration/Layers/SeededWorkItemWritebackReactor.ts +++ /dev/null @@ -1,166 +0,0 @@ -import { CommandId, EventId, type OrchestrationEvent } from "@t3tools/contracts"; -import { makeDrainableWorker } from "@t3tools/shared/DrainableWorker"; -import * as Cause from "effect/Cause"; -import * as Effect from "effect/Effect"; -import * as Exit from "effect/Exit"; -import * as Layer from "effect/Layer"; -import * as Schema from "effect/Schema"; -import * as Stream from "effect/Stream"; - -import { OrchestrationEngineService } from "../Services/OrchestrationEngine.ts"; -import { - SeededWorkItemWriteback, - SeededWorkItemWritebackError, -} from "../Services/SeededWorkItemWriteback.ts"; -import { - SeededWorkItemWritebackReactor, - type SeededWorkItemWritebackReactorShape, -} from "../Services/SeededWorkItemWritebackReactor.ts"; - -type WritebackRequestedEvent = Extract< - OrchestrationEvent, - { type: "thread.seeded-work-item-writeback-requested" } ->; - -const serverCommandId = (tag: string): CommandId => - // @effect-diagnostics-next-line cryptoRandomUUID:off - CommandId.make(`server:${tag}:${crypto.randomUUID()}`); -const isSeededWorkItemWritebackError = Schema.is(SeededWorkItemWritebackError); - -function summarizeWritebackKind(kind: WritebackRequestedEvent["payload"]["writebackKind"]): string { - switch (kind) { - case "refinement-context": - return "refinement context"; - case "worker-progress": - return "worker progress"; - } -} - -const make = Effect.gen(function* () { - const orchestrationEngine = yield* OrchestrationEngineService; - const writeback = yield* SeededWorkItemWriteback; - - const appendOutcomeActivity = (input: { - readonly threadId: WritebackRequestedEvent["payload"]["threadId"]; - readonly tone: "info" | "error"; - readonly kind: - | "manager.seeded-work-item-writeback.succeeded" - | "manager.seeded-work-item-writeback.failed"; - readonly summary: string; - readonly payload: Record; - readonly createdAt: string; - }) => - orchestrationEngine.dispatch({ - type: "thread.activity.append", - commandId: serverCommandId("seeded-work-item-writeback-activity"), - threadId: input.threadId, - activity: { - // @effect-diagnostics-next-line cryptoRandomUUID:off - id: EventId.make(crypto.randomUUID()), - tone: input.tone, - kind: input.kind, - summary: input.summary, - payload: input.payload, - turnId: null, - createdAt: input.createdAt, - }, - createdAt: input.createdAt, - }); - - const processWritebackRequested = Effect.fn("processWritebackRequested")(function* ( - event: WritebackRequestedEvent, - ) { - const { payload } = event; - const writebackLabel = summarizeWritebackKind(payload.writebackKind); - const result = yield* Effect.exit( - writeback.append({ - sourceKind: payload.sourceKind, - sourceLabel: payload.sourceLabel, - itemId: payload.itemId, - title: payload.title, - writebackKind: payload.writebackKind, - body: payload.body, - }), - ); - - if (Exit.isSuccess(result)) { - yield* appendOutcomeActivity({ - threadId: payload.threadId, - tone: "info", - kind: "manager.seeded-work-item-writeback.succeeded", - summary: `Appended ${writebackLabel} back to ${payload.sourceLabel} item ${payload.itemId}.`, - payload: { - itemId: payload.itemId, - sourceKind: payload.sourceKind, - sourceLabel: payload.sourceLabel, - writebackKind: payload.writebackKind, - body: payload.body, - ...(result.value.externalReference !== undefined - ? { externalReference: result.value.externalReference } - : {}), - }, - createdAt: payload.createdAt, - }); - return; - } - - const failReason = result.cause.reasons.find(Cause.isFailReason); - const detail = isSeededWorkItemWritebackError(failReason?.error) - ? failReason.error.detail - : Cause.pretty(result.cause); - - yield* appendOutcomeActivity({ - threadId: payload.threadId, - tone: "error", - kind: "manager.seeded-work-item-writeback.failed", - summary: `Failed to append ${writebackLabel} back to ${payload.sourceLabel} item ${payload.itemId}.`, - payload: { - itemId: payload.itemId, - sourceKind: payload.sourceKind, - sourceLabel: payload.sourceLabel, - writebackKind: payload.writebackKind, - body: payload.body, - detail, - }, - createdAt: payload.createdAt, - }); - }); - - const processWritebackRequestedSafely = (event: WritebackRequestedEvent) => - processWritebackRequested(event).pipe( - Effect.catchCause((cause) => { - if (Cause.hasInterruptsOnly(cause)) { - return Effect.failCause(cause); - } - return Effect.logWarning("seeded work item writeback reactor failed to process event", { - eventType: event.type, - threadId: event.payload.threadId, - itemId: event.payload.itemId, - cause: Cause.pretty(cause), - }); - }), - ); - - const worker = yield* makeDrainableWorker(processWritebackRequestedSafely); - - const start: SeededWorkItemWritebackReactorShape["start"] = Effect.fn("start")(function* () { - yield* Effect.forkScoped( - Stream.runForEach(orchestrationEngine.streamDomainEvents, (event) => { - if (event.type !== "thread.seeded-work-item-writeback-requested") { - return Effect.void; - } - return worker.enqueue(event); - }), - ); - }); - - return { - start, - drain: worker.drain, - } satisfies SeededWorkItemWritebackReactorShape; -}); - -export const SeededWorkItemWritebackReactorLive = Layer.effect( - SeededWorkItemWritebackReactor, - make, -); diff --git a/apps/server/src/orchestration/ManagerRuntime.test.ts b/apps/server/src/orchestration/ManagerRuntime.test.ts deleted file mode 100644 index 5192c0c8423e..000000000000 --- a/apps/server/src/orchestration/ManagerRuntime.test.ts +++ /dev/null @@ -1,358 +0,0 @@ -// @effect-diagnostics nodeBuiltinImport:off -import * as fs from "node:fs/promises"; -import * as os from "node:os"; -import * as path from "node:path"; -import { describe, expect, it } from "vite-plus/test"; - -import { - ProjectId, - ThreadId, - type ManagerQueueItem, - type ManagerSeededWorkItem, -} from "@t3tools/contracts"; - -import { - buildPromptFromContext, - createEmptyWorkspaceState, - estimateTokens, - parseWorkspaceState, - readWorkspaceStateFromFile, - reconstructRuntimeContext, - serializeWorkspaceState, - updateWorkspaceState, - writeWorkspaceStateToFile, - type ManagerWorkspaceState, -} from "./ManagerRuntime.ts"; - -describe("ManagerWorkspaceState", () => { - it("round-trips state through serialize and parse", () => { - const now = "2026-01-01T00:00:00.000Z"; - const state = createEmptyWorkspaceState(now); - - const serialized = serializeWorkspaceState(state); - const parsed = parseWorkspaceState(serialized); - - expect(parsed).toEqual(state); - }); - - it("creates empty state with expected defaults", () => { - const now = "2026-01-01T00:00:00.000Z"; - const state = createEmptyWorkspaceState(now); - - expect(state.createdAt).toBe(now); - expect(state.updatedAt).toBe(now); - expect(state.lastProcessedEventSequence).toBe(0); - expect(state.activeWorkItemSummaries).toEqual([]); - expect(state.preferences).toEqual([]); - expect(state.runtimeCycleCount).toBe(0); - }); - - it("updateWorkspaceState bumps updatedAt and increments cycle count", () => { - const now = "2026-01-01T00:00:00.000Z"; - const later = "2026-01-02T00:00:00.000Z"; - const state = createEmptyWorkspaceState(now); - - const updated = updateWorkspaceState(state, { - updatedAt: later, - lastProcessedEventSequence: 5, - }); - - expect(updated.createdAt).toBe(now); - expect(updated.updatedAt).toBe(later); - expect(updated.lastProcessedEventSequence).toBe(5); - expect(updated.runtimeCycleCount).toBe(1); - }); - - it("does not mutate input state on update", () => { - const now = "2026-01-01T00:00:00.000Z"; - const state = createEmptyWorkspaceState(now); - const original = { ...state }; - - updateWorkspaceState(state, { - updatedAt: "2026-01-02T00:00:00.000Z", - lastProcessedEventSequence: 10, - }); - - expect(state).toEqual(original); - }); -}); - -describe("ManagerWorkspaceState file persistence", () => { - const makeTempDir = () => fs.mkdtemp(path.join(os.tmpdir(), "manager-runtime-test-")); - - it("round-trips state through file write and read", async () => { - const dir = await makeTempDir(); - const stateFile = path.join(dir, "manager-state.json"); - const now = "2026-01-01T00:00:00.000Z"; - - const state = createEmptyWorkspaceState(now); - const updated = updateWorkspaceState(state, { - updatedAt: now, - lastProcessedEventSequence: 7, - }); - - await writeWorkspaceStateToFile(stateFile, updated); - const loaded = await readWorkspaceStateFromFile(stateFile, now); - - expect(loaded).toEqual(updated); - - await fs.rm(dir, { recursive: true }); - }); - - it("returns empty default state when file does not exist", async () => { - const dir = await makeTempDir(); - const stateFile = path.join(dir, "nonexistent.json"); - const now = "2026-01-01T00:00:00.000Z"; - - const loaded = await readWorkspaceStateFromFile(stateFile, now); - - expect(loaded).toEqual(createEmptyWorkspaceState(now)); - - await fs.rm(dir, { recursive: true }); - }); - - it("returns empty default state when file contains invalid JSON", async () => { - const dir = await makeTempDir(); - const stateFile = path.join(dir, "corrupt.json"); - const now = "2026-01-01T00:00:00.000Z"; - - await fs.writeFile(stateFile, "not json at all {{{", "utf-8"); - const loaded = await readWorkspaceStateFromFile(stateFile, now); - - expect(loaded).toEqual(createEmptyWorkspaceState(now)); - - await fs.rm(dir, { recursive: true }); - }); -}); - -function makeMockQueueItem(overrides: Partial = {}): ManagerQueueItem { - return { - itemId: "q-1", - escalationThreadId: ThreadId.make("worker-thread-1"), - category: "question", - summary: "How should I handle this error?", - detail: "Encountered a type error in file x.ts.", - status: "pending", - createdAt: "2026-06-01T00:00:00.000Z", - addressedAt: null, - dismissedAt: null, - ...overrides, - } as unknown as ManagerQueueItem; -} - -function makeMockSeededWorkItem( - overrides: Partial = {}, -): ManagerSeededWorkItem { - return { - itemId: "sw-1", - sourceKind: "todo-list", - sourceLabel: "Sprint Backlog", - title: "Add login page", - body: "Implement login page with OAuth support.", - delegationIntent: "delegate", - targetProjectId: ProjectId.make("project-a"), - acceptanceCriteria: ["User can log in", "Supports OAuth"], - readiness: "ready-for-worker", - readinessReason: "Has project and acceptance criteria.", - delegationStatus: "idle", - delegationRequestedAt: null, - createdAt: "2026-06-01T00:00:00.000Z", - updatedAt: "2026-06-01T00:00:00.000Z", - ...overrides, - } as unknown as ManagerSeededWorkItem; -} - -describe("Manager Runtime Context reconstruction", () => { - it("builds runtime context from workspace state and queue items", () => { - const now = "2026-06-01T00:00:00.000Z"; - const state = createEmptyWorkspaceState(now); - - const context = reconstructRuntimeContext({ - workspaceState: state, - queueItems: [makeMockQueueItem()], - seededWorkItems: [], - }); - - expect(context.pendingQueueItemCount).toBe(1); - expect(context.pendingQueueItemSummaries).toHaveLength(1); - expect(context.pendingQueueItemSummaries[0]).toContain("How should I handle this error?"); - expect(context.activeWorkItemCount).toBe(0); - expect(context.preferences).toEqual([]); - expect(context.cycleCount).toBe(0); - }); - - it("filters out non-pending queue items", () => { - const now = "2026-06-01T00:00:00.000Z"; - const state = createEmptyWorkspaceState(now); - - const context = reconstructRuntimeContext({ - workspaceState: state, - queueItems: [ - makeMockQueueItem({ itemId: "q-1", status: "pending" }), - makeMockQueueItem({ itemId: "q-2", status: "addressed" }), - makeMockQueueItem({ itemId: "q-3", status: "dismissed" }), - ], - seededWorkItems: [], - }); - - expect(context.pendingQueueItemCount).toBe(1); - }); - - it("includes seeded work item titles in context", () => { - const now = "2026-06-01T00:00:00.000Z"; - const state = createEmptyWorkspaceState(now); - - const context = reconstructRuntimeContext({ - workspaceState: state, - queueItems: [], - seededWorkItems: [ - makeMockSeededWorkItem({ itemId: "sw-1", title: "Add login" }), - makeMockSeededWorkItem({ itemId: "sw-2", title: "Fix auth bug" }), - ], - }); - - expect(context.activeWorkItemCount).toBe(2); - expect(context.activeWorkItemTitles).toEqual(["Add login", "Fix auth bug"]); - }); - - it("includes workspace preferences when present", () => { - const now = "2026-06-01T00:00:00.000Z"; - const state: ManagerWorkspaceState = { - ...createEmptyWorkspaceState(now), - preferences: ["prefer functional style", "use Effect-TS"], - }; - - const context = reconstructRuntimeContext({ - workspaceState: state, - queueItems: [], - seededWorkItems: [], - }); - - expect(context.preferences).toEqual(["prefer functional style", "use Effect-TS"]); - }); - - it("empty inputs produce empty but well-formed context", () => { - const now = "2026-06-01T00:00:00.000Z"; - const state = createEmptyWorkspaceState(now); - - const context = reconstructRuntimeContext({ - workspaceState: state, - queueItems: [], - seededWorkItems: [], - }); - - expect(context.pendingQueueItemCount).toBe(0); - expect(context.activeWorkItemCount).toBe(0); - expect(context.cycleCount).toBe(0); - expect(context.summary).toBeTruthy(); - }); -}); - -describe("Token estimation", () => { - it("estimates tokens with ~4 chars per token approximation", () => { - expect(estimateTokens("")).toBe(0); - expect(estimateTokens("hello")).toBeGreaterThanOrEqual(1); - expect(estimateTokens("hello")).toBeLessThanOrEqual(3); - - const oneHundredChars = "a".repeat(100); - expect(estimateTokens(oneHundredChars)).toBe(25); - }); - - it("estimateTokens returns zero for empty string", () => { - expect(estimateTokens("")).toBe(0); - }); -}); - -describe("Prompt building and token efficiency", () => { - it("builds a prompt from runtime context", () => { - const now = "2026-06-01T00:00:00.000Z"; - const state: ManagerWorkspaceState = { - ...createEmptyWorkspaceState(now), - preferences: ["prefer functional style"], - }; - - const context = reconstructRuntimeContext({ - workspaceState: state, - queueItems: [makeMockQueueItem({ summary: "How to handle errors?", category: "question" })], - seededWorkItems: [makeMockSeededWorkItem({ title: "Add login page" })], - }); - - const prompt = buildPromptFromContext(context); - - expect(prompt).toContain("Manager Runtime Context"); - expect(prompt).toContain("How to handle errors?"); - expect(prompt).toContain("Add login page"); - expect(prompt).toContain("prefer functional style"); - }); - - it("summary-based context uses far fewer tokens than detail-based full transcript", () => { - const now = "2026-06-01T00:00:00.000Z"; - const state = createEmptyWorkspaceState(now); - - const queueItems = Array.from({ length: 50 }, (_, i) => - makeMockQueueItem({ - itemId: `q-${i}`, - summary: `Task number ${i}: process item`, - detail: - `Detailed description for item ${i} that has a lot of text which would normally bloat a transcript.`.repeat( - 5, - ), - }), - ); - - const runtimeContext = reconstructRuntimeContext({ - workspaceState: state, - queueItems, - seededWorkItems: [], - }); - - const prompt = buildPromptFromContext(runtimeContext); - const runtimeTokens = estimateTokens(prompt); - - // Full transcript approach: includes verbose detail fields - const fullTranscriptDetailText = queueItems - .map((q) => `${q.summary}\n${q.detail}`) - .join("\n\n"); - const fullTranscriptTokens = estimateTokens(fullTranscriptDetailText); - - // Runtime context summaries should use significantly fewer tokens - // than including all verbose details - expect(runtimeTokens).toBeLessThan(fullTranscriptTokens); - expect(runtimeTokens).toBeLessThanOrEqual(fullTranscriptTokens * 0.5); - }); - - it("demonstrates token efficiency vs full transcript approach", () => { - const now = "2026-06-01T00:00:00.000Z"; - const state = createEmptyWorkspaceState(now); - const queueItems = Array.from({ length: 50 }, (_, i) => - makeMockQueueItem({ - itemId: `q-${i}`, - summary: `Item ${i} question`, - detail: - `This is a very long detailed message that would consume many tokens in a full transcript for item ${i}. It repeats many times to simulate real-world chat verbosity. `.repeat( - 20, - ), - }), - ); - - const runtimeContext = reconstructRuntimeContext({ - workspaceState: state, - queueItems, - seededWorkItems: [], - }); - - const prompt = buildPromptFromContext(runtimeContext); - const runtimeTokens = estimateTokens(prompt); - - // Full transcript approach: reconstruct all detail fields verbatim - const fullTranscriptText = queueItems - .map((q) => `[${q.category}] ${q.summary}\nDetail: ${q.detail}`) - .join("\n\n"); - const fullTranscriptTokens = estimateTokens(fullTranscriptText); - - // Runtime context should use significantly fewer tokens than full transcript - // because it uses summaries, not verbose details - const ratio = runtimeTokens / fullTranscriptTokens; - expect(ratio).toBeLessThan(0.3); - }); -}); diff --git a/apps/server/src/orchestration/ManagerRuntime.ts b/apps/server/src/orchestration/ManagerRuntime.ts deleted file mode 100644 index b1e9c6b257f9..000000000000 --- a/apps/server/src/orchestration/ManagerRuntime.ts +++ /dev/null @@ -1,180 +0,0 @@ -// @effect-diagnostics nodeBuiltinImport:off -import * as fs from "node:fs/promises"; - -import type { ManagerQueueItem, ManagerSeededWorkItem } from "@t3tools/contracts"; - -export interface ManagerWorkItemSummary { - readonly itemId: string; - readonly title: string; - readonly readiness: string; - readonly delegationStatus: string; - readonly hasRefinementHandoff: boolean; -} - -export interface ManagerWorkspaceState { - readonly createdAt: string; - readonly updatedAt: string; - readonly lastProcessedEventSequence: number; - readonly activeWorkItemSummaries: ReadonlyArray; - readonly preferences: ReadonlyArray; - readonly runtimeCycleCount: number; -} - -export interface ManagerRuntimeContext { - readonly summary: string; - readonly pendingQueueItemCount: number; - readonly pendingQueueItemSummaries: ReadonlyArray; - readonly activeWorkItemCount: number; - readonly activeWorkItemTitles: ReadonlyArray; - readonly preferences: ReadonlyArray; - readonly cycleCount: number; -} - -export function createEmptyWorkspaceState(now: string): ManagerWorkspaceState { - return { - createdAt: now, - updatedAt: now, - lastProcessedEventSequence: 0, - activeWorkItemSummaries: [], - preferences: [], - runtimeCycleCount: 0, - }; -} - -export interface WorkspaceStatePatch { - readonly updatedAt: string; - readonly lastProcessedEventSequence?: number; -} - -export function updateWorkspaceState( - state: ManagerWorkspaceState, - patch: WorkspaceStatePatch, -): ManagerWorkspaceState { - return { - ...state, - updatedAt: patch.updatedAt, - lastProcessedEventSequence: - patch.lastProcessedEventSequence ?? state.lastProcessedEventSequence, - runtimeCycleCount: state.runtimeCycleCount + 1, - }; -} - -export function serializeWorkspaceState(state: ManagerWorkspaceState): string { - return JSON.stringify(state, null, 2); -} - -export function parseWorkspaceState(json: string): ManagerWorkspaceState { - const parsed = JSON.parse(json); - return { - createdAt: String(parsed.createdAt ?? ""), - updatedAt: String(parsed.updatedAt ?? ""), - lastProcessedEventSequence: Number(parsed.lastProcessedEventSequence ?? 0), - activeWorkItemSummaries: Array.isArray(parsed.activeWorkItemSummaries) - ? parsed.activeWorkItemSummaries - : [], - preferences: Array.isArray(parsed.preferences) ? parsed.preferences : [], - runtimeCycleCount: Number(parsed.runtimeCycleCount ?? 0), - }; -} - -export async function writeWorkspaceStateToFile( - filePath: string, - state: ManagerWorkspaceState, -): Promise { - const serialized = serializeWorkspaceState(state); - // @effect-diagnostics-next-line cryptoRandomUUID:off - const tmpPath = `${filePath}.${crypto.randomUUID()}.tmp`; - await fs.writeFile(tmpPath, serialized, "utf-8"); - await fs.rename(tmpPath, filePath); -} - -export async function readWorkspaceStateFromFile( - filePath: string, - now: string, -): Promise { - try { - const raw = await fs.readFile(filePath, "utf-8"); - return parseWorkspaceState(raw); - } catch (error) { - process.stderr.write( - `[ManagerRuntime] Failed to read workspace state from '${filePath}', falling back to empty state: ${ - error instanceof Error ? error.message : String(error) - }\n`, - ); - return createEmptyWorkspaceState(now); - } -} - -export function reconstructRuntimeContext(input: { - readonly workspaceState: ManagerWorkspaceState; - readonly queueItems: ReadonlyArray; - readonly seededWorkItems: ReadonlyArray; -}): ManagerRuntimeContext { - const pendingQueueItems = input.queueItems.filter((q) => q.status === "pending"); - const queueSummaries = pendingQueueItems.map((q) => `[${q.category}] ${q.summary}`); - - const workItemTitles = input.seededWorkItems.map((w) => w.title); - - const summaryParts: string[] = []; - - if (pendingQueueItems.length > 0) { - summaryParts.push(`${pendingQueueItems.length} pending queue item(s) need attention`); - } - if (input.seededWorkItems.length > 0) { - summaryParts.push(`${input.seededWorkItems.length} active seeded work item(s)`); - } - - const summary = - summaryParts.length > 0 - ? `Manager runtime context: ${summaryParts.join("; ")}.` - : "Manager runtime context: no pending items to coordinate."; - - return { - summary, - pendingQueueItemCount: pendingQueueItems.length, - pendingQueueItemSummaries: queueSummaries, - activeWorkItemCount: input.seededWorkItems.length, - activeWorkItemTitles: workItemTitles, - preferences: input.workspaceState.preferences, - cycleCount: input.workspaceState.runtimeCycleCount, - }; -} - -export function buildPromptFromContext(context: ManagerRuntimeContext): string { - const lines: string[] = ["## Manager Runtime Context", "", context.summary, ""]; - - if (context.preferences.length > 0) { - lines.push("### Learned Preferences"); - for (const pref of context.preferences) { - lines.push(`- ${pref}`); - } - lines.push(""); - } - - if (context.pendingQueueItemSummaries.length > 0) { - lines.push("### Pending Queue Items"); - for (const qs of context.pendingQueueItemSummaries) { - lines.push(`- ${qs}`); - } - lines.push(""); - } - - if (context.activeWorkItemTitles.length > 0) { - lines.push("### Active Work Items"); - for (const title of context.activeWorkItemTitles) { - lines.push(`- ${title}`); - } - lines.push(""); - } - - lines.push(`Runtime cycle: ${context.cycleCount}`); - - return lines.join("\n"); -} - -const TOKEN_CHARS_PER_TOKEN = 4; - -export function estimateTokens(text: string): number { - if (text.length === 0) return 0; - return Math.ceil(text.length / TOKEN_CHARS_PER_TOKEN); -} diff --git a/apps/server/src/orchestration/Normalizer.ts b/apps/server/src/orchestration/Normalizer.ts index 2e72140d5f0c..95d29e3d6d29 100644 --- a/apps/server/src/orchestration/Normalizer.ts +++ b/apps/server/src/orchestration/Normalizer.ts @@ -58,13 +58,6 @@ export const normalizeDispatchCommand = (command: ClientOrchestrationCommand) => } satisfies OrchestrationCommand; } - if (command.type === "manager.bootstrap") { - return { - ...command, - workspaceRoot: yield* normalizeProjectWorkspaceRootForCreate(command.workspaceRoot, true), - } satisfies OrchestrationCommand; - } - if (command.type === "project.meta.update" && command.workspaceRoot !== undefined) { return { ...command, diff --git a/apps/server/src/orchestration/Schemas.ts b/apps/server/src/orchestration/Schemas.ts index 4a6c8a896bf7..4d2c12842c12 100644 --- a/apps/server/src/orchestration/Schemas.ts +++ b/apps/server/src/orchestration/Schemas.ts @@ -3,8 +3,6 @@ import { ProjectMetaUpdatedPayload as ContractsProjectMetaUpdatedPayloadSchema, ProjectDeletedPayload as ContractsProjectDeletedPayloadSchema, ThreadCreatedPayload as ContractsThreadCreatedPayloadSchema, - ThreadSeededWorkItemsUpsertedPayload as ContractsThreadSeededWorkItemsUpsertedPayloadSchema, - ThreadSeededWorkItemWritebackRequestedPayload as ContractsThreadSeededWorkItemWritebackRequestedPayloadSchema, ThreadArchivedPayload as ContractsThreadArchivedPayloadSchema, ThreadArchivedAndNewCreatedPayload as ContractsThreadArchivedAndNewCreatedPayloadSchema, ThreadMetaUpdatedPayload as ContractsThreadMetaUpdatedPayloadSchema, @@ -23,7 +21,6 @@ import { ThreadApprovalResponseRequestedPayload as ContractsThreadApprovalResponseRequestedPayloadSchema, ThreadCheckpointRevertRequestedPayload as ContractsThreadCheckpointRevertRequestedPayloadSchema, ThreadSessionStopRequestedPayload as ContractsThreadSessionStopRequestedPayloadSchema, - ThreadManagerQueueItemsUpsertedPayload as ContractsThreadManagerQueueItemsUpsertedPayloadSchema, ThreadTrimPointCreatedPayload as ContractsThreadTrimPointCreatedPayloadSchema, } from "@t3tools/contracts"; @@ -33,10 +30,6 @@ export const ProjectMetaUpdatedPayload = ContractsProjectMetaUpdatedPayloadSchem export const ProjectDeletedPayload = ContractsProjectDeletedPayloadSchema; export const ThreadCreatedPayload = ContractsThreadCreatedPayloadSchema; -export const ThreadSeededWorkItemsUpsertedPayload = - ContractsThreadSeededWorkItemsUpsertedPayloadSchema; -export const ThreadSeededWorkItemWritebackRequestedPayload = - ContractsThreadSeededWorkItemWritebackRequestedPayloadSchema; export const ThreadArchivedPayload = ContractsThreadArchivedPayloadSchema; export const ThreadArchivedAndNewCreatedPayload = ContractsThreadArchivedAndNewCreatedPayloadSchema; export const ThreadMetaUpdatedPayload = ContractsThreadMetaUpdatedPayloadSchema; @@ -61,7 +54,4 @@ export const ThreadCheckpointRevertRequestedPayload = ContractsThreadCheckpointRevertRequestedPayloadSchema; export const ThreadSessionStopRequestedPayload = ContractsThreadSessionStopRequestedPayloadSchema; -export const ThreadManagerQueueItemsUpsertedPayload = - ContractsThreadManagerQueueItemsUpsertedPayloadSchema; - export const ThreadTrimPointCreatedPayload = ContractsThreadTrimPointCreatedPayloadSchema; diff --git a/apps/server/src/orchestration/Services/SeededWorkItemWriteback.ts b/apps/server/src/orchestration/Services/SeededWorkItemWriteback.ts deleted file mode 100644 index 857b3b1aa1e5..000000000000 --- a/apps/server/src/orchestration/Services/SeededWorkItemWriteback.ts +++ /dev/null @@ -1,36 +0,0 @@ -import type { - SeededWorkItemId, - SeededWorkItemWritebackKind, - SeededWorkSourceKind, -} from "@t3tools/contracts"; -import * as Context from "effect/Context"; -import type * as Effect from "effect/Effect"; -import * as Schema from "effect/Schema"; - -export class SeededWorkItemWritebackError extends Schema.TaggedErrorClass()( - "SeededWorkItemWritebackError", - { - detail: Schema.String, - }, -) {} - -export interface SeededWorkItemWritebackShape { - readonly append: (input: { - readonly sourceKind: SeededWorkSourceKind; - readonly sourceLabel: string; - readonly itemId: SeededWorkItemId; - readonly title: string; - readonly writebackKind: SeededWorkItemWritebackKind; - readonly body: string; - }) => Effect.Effect< - { - readonly externalReference?: string; - }, - SeededWorkItemWritebackError - >; -} - -export class SeededWorkItemWriteback extends Context.Service< - SeededWorkItemWriteback, - SeededWorkItemWritebackShape ->()("t3/orchestration/Services/SeededWorkItemWriteback") {} diff --git a/apps/server/src/orchestration/Services/SeededWorkItemWritebackReactor.ts b/apps/server/src/orchestration/Services/SeededWorkItemWritebackReactor.ts deleted file mode 100644 index 80faeae0beb2..000000000000 --- a/apps/server/src/orchestration/Services/SeededWorkItemWritebackReactor.ts +++ /dev/null @@ -1,13 +0,0 @@ -import * as Context from "effect/Context"; -import type * as Effect from "effect/Effect"; -import type * as Scope from "effect/Scope"; - -export interface SeededWorkItemWritebackReactorShape { - readonly start: () => Effect.Effect; - readonly drain: Effect.Effect; -} - -export class SeededWorkItemWritebackReactor extends Context.Service< - SeededWorkItemWritebackReactor, - SeededWorkItemWritebackReactorShape ->()("t3/orchestration/Services/SeededWorkItemWritebackReactor") {} diff --git a/apps/server/src/orchestration/commandInvariants.ts b/apps/server/src/orchestration/commandInvariants.ts index 8391d72958a6..f852a8f4b9c7 100644 --- a/apps/server/src/orchestration/commandInvariants.ts +++ b/apps/server/src/orchestration/commandInvariants.ts @@ -1,5 +1,4 @@ import type { - ManagerSeededWorkItem, OrchestrationCommand, OrchestrationProject, OrchestrationReadModel, @@ -39,68 +38,21 @@ export function listThreadsByProjectId( return readModel.threads.filter((thread) => thread.projectId === projectId); } -export function findManagerWorkspace( - readModel: OrchestrationReadModel, -): OrchestrationProject | undefined { - return readModel.projects.find((project) => project.managerMetadata?.role === "workspace"); -} - -export function findManagerConsole( - readModel: OrchestrationReadModel, -): OrchestrationThread | undefined { - return readModel.threads.find((thread) => thread.managerMetadata?.role === "console"); -} - -export function findSeededWorkItemOnManagerConsole( - readModel: OrchestrationReadModel, - managerThreadId: ThreadId, - seededWorkItemId: string, -): ManagerSeededWorkItem | undefined { - const managerConsole = findThreadById(readModel, managerThreadId); - if (managerConsole?.managerMetadata?.role !== "console") { - return undefined; - } - return (managerConsole.seededWorkItems ?? []).find((item) => item.itemId === seededWorkItemId); -} - -export function findActiveRefinerThreadForSeededWorkItem( - readModel: OrchestrationReadModel, - managerThreadId: ThreadId, - seededWorkItemId: string, -): OrchestrationThread | undefined { - return readModel.threads.find( - (thread) => - thread.deletedAt === null && - thread.archivedAt === null && - thread.managerMetadata?.role === "refiner" && - thread.managerMetadata.managerThreadId === managerThreadId && - thread.managerMetadata.seededWorkItemId === seededWorkItemId, - ); -} - export function requireProject(input: { readonly readModel: OrchestrationReadModel; readonly command: OrchestrationCommand; readonly projectId: ProjectId; }): Effect.Effect { const project = findProjectById(input.readModel, input.projectId); - if (!project) { - return Effect.fail( - invariantError( - input.command.type, - `Project '${input.projectId}' does not exist for command '${input.command.type}'.`, - ), - ); - } - if (project.deletedAt !== null) { - return Effect.fail( - invariantError( - input.command.type, - `Project '${input.projectId}' has been deleted and cannot handle command '${input.command.type}'.`, - ), - ); + if (project) { + return Effect.succeed(project); } - return Effect.succeed(project); + return Effect.fail( + invariantError( + input.command.type, + `Project '${input.projectId}' does not exist for command '${input.command.type}'.`, + ), + ); } export function requireProjectAbsent(input: { @@ -108,8 +60,7 @@ export function requireProjectAbsent(input: { readonly command: OrchestrationCommand; readonly projectId: ProjectId; }): Effect.Effect { - const existing = findProjectById(input.readModel, input.projectId); - if (!existing || existing.deletedAt !== null) { + if (!findProjectById(input.readModel, input.projectId)) { return Effect.void; } return Effect.fail( @@ -126,23 +77,15 @@ export function requireThread(input: { readonly threadId: ThreadId; }): Effect.Effect { const thread = findThreadById(input.readModel, input.threadId); - if (!thread) { - return Effect.fail( - invariantError( - input.command.type, - `Thread '${input.threadId}' does not exist for command '${input.command.type}'.`, - ), - ); - } - if (thread.deletedAt !== null) { - return Effect.fail( - invariantError( - input.command.type, - `Thread '${input.threadId}' has been deleted and cannot handle command '${input.command.type}'.`, - ), - ); + if (thread) { + return Effect.succeed(thread); } - return Effect.succeed(thread); + return Effect.fail( + invariantError( + input.command.type, + `Thread '${input.threadId}' does not exist for command '${input.command.type}'.`, + ), + ); } export function requireThreadArchived(input: { @@ -183,32 +126,12 @@ export function requireThreadNotArchived(input: { ); } -export function requireManagerConsole(input: { - readonly readModel: OrchestrationReadModel; - readonly command: OrchestrationCommand; - readonly threadId: ThreadId; -}): Effect.Effect { - return requireThread(input).pipe( - Effect.flatMap((thread) => - thread.managerMetadata?.role === "console" - ? Effect.succeed(thread) - : Effect.fail( - invariantError( - input.command.type, - `Thread '${input.threadId}' is not the Manager Console for command '${input.command.type}'.`, - ), - ), - ), - ); -} - export function requireThreadAbsent(input: { readonly readModel: OrchestrationReadModel; readonly command: OrchestrationCommand; readonly threadId: ThreadId; }): Effect.Effect { - const existing = findThreadById(input.readModel, input.threadId); - if (!existing || existing.deletedAt !== null) { + if (!findThreadById(input.readModel, input.threadId)) { return Effect.void; } return Effect.fail( diff --git a/apps/server/src/orchestration/decider.archiveAndNew.test.ts b/apps/server/src/orchestration/decider.archiveAndNew.test.ts index dc31666ea169..55a469bb1bbd 100644 --- a/apps/server/src/orchestration/decider.archiveAndNew.test.ts +++ b/apps/server/src/orchestration/decider.archiveAndNew.test.ts @@ -13,7 +13,6 @@ import { import { assert, describe, it } from "@effect/vitest"; import * as Crypto from "effect/Crypto"; import * as Effect from "effect/Effect"; -import * as Layer from "effect/Layer"; import type * as PlatformError from "effect/PlatformError"; import { NodeCrypto } from "@effect/platform-node"; diff --git a/apps/server/src/orchestration/decider.escalation.test.ts b/apps/server/src/orchestration/decider.escalation.test.ts deleted file mode 100644 index 75b6010bcc22..000000000000 --- a/apps/server/src/orchestration/decider.escalation.test.ts +++ /dev/null @@ -1,400 +0,0 @@ -import { - CommandId, - DEFAULT_PROVIDER_INTERACTION_MODE, - EventId, - ProjectId, - ThreadId, - type OrchestrationCommand, - type OrchestrationEvent, - type OrchestrationReadModel, - ProviderInstanceId, -} from "@t3tools/contracts"; -import * as Effect from "effect/Effect"; -import { describe, expect, it } from "vite-plus/test"; - -import { NodeCrypto } from "@effect/platform-node"; - -import { decideOrchestrationCommand as decideOrchestrationCommandRaw } from "./decider.ts"; - -const decideOrchestrationCommand = (input: Parameters[0]) => - decideOrchestrationCommandRaw(input).pipe(Effect.provide(NodeCrypto.layer)); -import { createEmptyReadModel, projectEvent } from "./projector.ts"; - -const asCommandId = (value: string): CommandId => CommandId.make(value); -const asEventId = (value: string): EventId => EventId.make(value); -const asProjectId = (value: string): ProjectId => ProjectId.make(value); -const asThreadId = (value: string): ThreadId => ThreadId.make(value); - -type PlannedEvent = Omit; - -async function seedEscalationReadModel(): Promise { - const now = "2026-01-01T00:00:00.000Z"; - let model = createEmptyReadModel(now); - - // Manager Workspace + Console - model = await Effect.runPromise( - projectEvent(model, { - sequence: 1, - eventId: asEventId("evt-project-manager"), - aggregateKind: "project", - aggregateId: asProjectId("manager-workspace"), - type: "project.created", - occurredAt: now, - commandId: asCommandId("cmd-manager-bootstrap"), - causationEventId: null, - correlationId: asCommandId("cmd-manager-bootstrap"), - metadata: {}, - payload: { - projectId: asProjectId("manager-workspace"), - title: "Manager Workspace", - workspaceRoot: "/tmp/manager", - managerMetadata: { role: "workspace" }, - defaultModelSelection: { - instanceId: ProviderInstanceId.make("codex"), - model: "gpt-5-codex", - }, - scripts: [], - createdAt: now, - updatedAt: now, - }, - }), - ); - - model = await Effect.runPromise( - projectEvent(model, { - sequence: 2, - eventId: asEventId("evt-thread-manager-console"), - aggregateKind: "thread", - aggregateId: asThreadId("manager-console"), - type: "thread.created", - occurredAt: now, - commandId: asCommandId("cmd-manager-bootstrap"), - causationEventId: null, - correlationId: asCommandId("cmd-manager-bootstrap"), - metadata: {}, - payload: { - threadId: asThreadId("manager-console"), - projectId: asProjectId("manager-workspace"), - title: "Manager Console", - managerMetadata: { role: "console" }, - modelSelection: { - instanceId: ProviderInstanceId.make("codex"), - model: "gpt-5-codex", - }, - runtimeMode: "full-access", - interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, - branch: null, - worktreePath: "/tmp/manager", - createdAt: now, - updatedAt: now, - }, - }), - ); - - // App project - model = await Effect.runPromise( - projectEvent(model, { - sequence: 3, - eventId: asEventId("evt-project-app"), - aggregateKind: "project", - aggregateId: asProjectId("app-project"), - type: "project.created", - occurredAt: now, - commandId: asCommandId("cmd-project-create"), - causationEventId: null, - correlationId: asCommandId("cmd-project-create"), - metadata: {}, - payload: { - projectId: asProjectId("app-project"), - title: "App Project", - workspaceRoot: "/tmp/app", - defaultModelSelection: { - instanceId: ProviderInstanceId.make("codex"), - model: "gpt-5-codex", - }, - scripts: [], - createdAt: now, - updatedAt: now, - }, - }), - ); - - // Worker thread delegated from manager - model = await Effect.runPromise( - projectEvent(model, { - sequence: 4, - eventId: asEventId("evt-thread-worker"), - aggregateKind: "thread", - aggregateId: asThreadId("worker-thread-1"), - type: "thread.created", - occurredAt: now, - commandId: asCommandId("cmd-worker-delegate"), - causationEventId: null, - correlationId: asCommandId("cmd-worker-delegate"), - metadata: {}, - payload: { - threadId: asThreadId("worker-thread-1"), - projectId: asProjectId("app-project"), - title: "Billing CSV export", - managerMetadata: { - role: "worker", - managerThreadId: asThreadId("manager-console"), - seededWorkItemId: "work-refine", - sourceBody: "The original Jira description for billing CSV export.", - refinedBrief: "Users can export billing data as CSV from the invoices screen.", - acceptanceCriteria: ["Export button visible", "CSV includes invoice data"], - }, - modelSelection: { - instanceId: ProviderInstanceId.make("codex"), - model: "gpt-5-codex", - }, - runtimeMode: "full-access", - interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, - branch: null, - worktreePath: null, - createdAt: now, - updatedAt: now, - }, - }), - ); - - return model; -} - -function normalizeEvent(event: PlannedEvent | ReadonlyArray): PlannedEvent[] { - const events = Array.isArray(event) ? event : [event]; - return events.map((entry) => { - if (entry.type === "thread.manager-queue-items-upserted") { - return { - type: entry.type, - aggregateKind: entry.aggregateKind, - aggregateId: entry.aggregateId, - payload: entry.payload, - }; - } - return entry; - }); -} - -describe("worker.escalate", () => { - it("creates a Manager Queue Item on the Manager Console", async () => { - const readModel = await seedEscalationReadModel(); - const createdAt = "2026-01-01T00:00:10.000Z"; - - const command: OrchestrationCommand = { - type: "worker.escalate", - commandId: asCommandId("cmd-escalate-1"), - threadId: asThreadId("worker-thread-1"), - escalationId: "escalation-001", - category: "blocker", - summary: "Need approval for file deletion", - detail: "The worker wants to delete src/legacy/ but it may be used by other teams.", - createdAt, - }; - - const result = await Effect.runPromise(decideOrchestrationCommand({ command, readModel })); - - const events = normalizeEvent(result); - - expect(events).toEqual([ - expect.objectContaining({ - type: "thread.manager-queue-items-upserted", - aggregateKind: "thread", - aggregateId: asThreadId("manager-console"), - payload: expect.objectContaining({ - threadId: asThreadId("manager-console"), - managerQueueItems: [ - expect.objectContaining({ - itemId: "escalation-001", - escalationThreadId: asThreadId("worker-thread-1"), - category: "blocker", - summary: "Need approval for file deletion", - detail: "The worker wants to delete src/legacy/ but it may be used by other teams.", - status: "pending", - createdAt, - addressedAt: null, - dismissedAt: null, - }), - ], - updatedAt: createdAt, - }), - }), - ]); - }); - - it("appends to existing queue items to maintain FIFO order", async () => { - let readModel = await seedEscalationReadModel(); - const now = "2026-01-01T00:00:05.000Z"; - - // Pre-seed with an existing queue item - readModel = await Effect.runPromise( - projectEvent(readModel, { - sequence: 5, - eventId: asEventId("evt-queue-seed"), - aggregateKind: "thread", - aggregateId: asThreadId("manager-console"), - type: "thread.manager-queue-items-upserted", - occurredAt: now, - commandId: asCommandId("cmd-escalate-0"), - causationEventId: null, - correlationId: asCommandId("cmd-escalate-0"), - metadata: {}, - payload: { - threadId: asThreadId("manager-console"), - managerQueueItems: [ - { - itemId: "escalation-000", - escalationThreadId: asThreadId("worker-thread-1"), - category: "question", - summary: "What is the deployment process?", - detail: "Need clarification on how deployments are handled.", - status: "pending", - createdAt: now, - addressedAt: null, - dismissedAt: null, - }, - ], - updatedAt: now, - }, - }), - ); - - const createdAt = "2026-01-01T00:00:10.000Z"; - const command: OrchestrationCommand = { - type: "worker.escalate", - commandId: asCommandId("cmd-escalate-1"), - threadId: asThreadId("worker-thread-1"), - escalationId: "escalation-001", - category: "blocker", - summary: "Need approval for file deletion", - detail: "The worker wants to delete src/legacy/ but it may be used by other teams.", - createdAt, - }; - - const result = await Effect.runPromise(decideOrchestrationCommand({ command, readModel })); - - const events = normalizeEvent(result); - - expect(events).toEqual([ - expect.objectContaining({ - type: "thread.manager-queue-items-upserted", - aggregateKind: "thread", - aggregateId: asThreadId("manager-console"), - payload: expect.objectContaining({ - threadId: asThreadId("manager-console"), - managerQueueItems: [ - expect.objectContaining({ itemId: "escalation-000" }), - expect.objectContaining({ itemId: "escalation-001" }), - ], - updatedAt: createdAt, - }), - }), - ]); - }); - - it("rejects escalation when escalationId already exists (duplicate-safe)", async () => { - let readModel = await seedEscalationReadModel(); - const now = "2026-01-01T00:00:05.000Z"; - - // Pre-seed with the same escalation - readModel = await Effect.runPromise( - projectEvent(readModel, { - sequence: 5, - eventId: asEventId("evt-queue-seed"), - aggregateKind: "thread", - aggregateId: asThreadId("manager-console"), - type: "thread.manager-queue-items-upserted", - occurredAt: now, - commandId: asCommandId("cmd-escalate-initial"), - causationEventId: null, - correlationId: asCommandId("cmd-escalate-initial"), - metadata: {}, - payload: { - threadId: asThreadId("manager-console"), - managerQueueItems: [ - { - itemId: "escalation-001", - escalationThreadId: asThreadId("worker-thread-1"), - category: "blocker", - summary: "Need approval for file deletion", - detail: "The worker wants to delete src/legacy/ but it may be used by other teams.", - status: "pending", - createdAt: now, - addressedAt: null, - dismissedAt: null, - }, - ], - updatedAt: now, - }, - }), - ); - - const createdAt = "2026-01-01T00:00:10.000Z"; - const command: OrchestrationCommand = { - type: "worker.escalate", - commandId: asCommandId("cmd-escalate-dup"), - threadId: asThreadId("worker-thread-1"), - escalationId: "escalation-001", - category: "blocker", - summary: "Need approval for file deletion", - detail: "The worker wants to delete src/legacy/ but it may be used by other teams.", - createdAt, - }; - - await expect( - Effect.runPromise(decideOrchestrationCommand({ command, readModel })), - ).rejects.toEqual( - expect.objectContaining({ - detail: expect.stringContaining("already exists on Manager Console"), - }), - ); - }); - - it("rejects escalation from a non-worker thread", async () => { - const readModel = await seedEscalationReadModel(); - const createdAt = "2026-01-01T00:00:10.000Z"; - - const command: OrchestrationCommand = { - type: "worker.escalate", - commandId: asCommandId("cmd-escalate-bad"), - threadId: asThreadId("manager-console"), - escalationId: "escalation-001", - category: "blocker", - summary: "Should fail", - detail: "Manager console is not a worker thread.", - createdAt, - }; - - await expect( - Effect.runPromise(decideOrchestrationCommand({ command, readModel })), - ).rejects.toEqual( - expect.objectContaining({ - detail: expect.stringContaining("is not a Worker Thread"), - }), - ); - }); - - it("rejects escalation when thread does not exist", async () => { - const readModel = await seedEscalationReadModel(); - const createdAt = "2026-01-01T00:00:10.000Z"; - - const command: OrchestrationCommand = { - type: "worker.escalate", - commandId: asCommandId("cmd-escalate-bad"), - threadId: asThreadId("nonexistent-thread"), - escalationId: "escalation-001", - category: "blocker", - summary: "Should fail", - detail: "This thread does not exist.", - createdAt, - }; - - await expect( - Effect.runPromise(decideOrchestrationCommand({ command, readModel })), - ).rejects.toEqual( - expect.objectContaining({ - detail: expect.stringContaining("does not exist"), - }), - ); - }); -}); diff --git a/apps/server/src/orchestration/decider.queue-resolution.test.ts b/apps/server/src/orchestration/decider.queue-resolution.test.ts deleted file mode 100644 index 39d4e6c2ddbe..000000000000 --- a/apps/server/src/orchestration/decider.queue-resolution.test.ts +++ /dev/null @@ -1,586 +0,0 @@ -import { - CommandId, - DEFAULT_PROVIDER_INTERACTION_MODE, - EventId, - ProjectId, - ThreadId, - type OrchestrationCommand, - type OrchestrationEvent, - type OrchestrationReadModel, - ProviderInstanceId, -} from "@t3tools/contracts"; -import * as Effect from "effect/Effect"; -import { describe, expect, it } from "vite-plus/test"; - -import { NodeCrypto } from "@effect/platform-node"; - -import { decideOrchestrationCommand as decideOrchestrationCommandRaw } from "./decider.ts"; - -const decideOrchestrationCommand = (input: Parameters[0]) => - decideOrchestrationCommandRaw(input).pipe(Effect.provide(NodeCrypto.layer)); -import { createEmptyReadModel, projectEvent } from "./projector.ts"; - -const asCommandId = (value: string): CommandId => CommandId.make(value); -const asEventId = (value: string): EventId => EventId.make(value); -const asProjectId = (value: string): ProjectId => ProjectId.make(value); -const asThreadId = (value: string): ThreadId => ThreadId.make(value); - -type PlannedEvent = Omit; - -async function seedResolutionReadModel(): Promise { - const now = "2026-01-01T00:00:00.000Z"; - let model = createEmptyReadModel(now); - - // Manager Workspace + Console - model = await Effect.runPromise( - projectEvent(model, { - sequence: 1, - eventId: asEventId("evt-project-manager"), - aggregateKind: "project", - aggregateId: asProjectId("manager-workspace"), - type: "project.created", - occurredAt: now, - commandId: asCommandId("cmd-manager-bootstrap"), - causationEventId: null, - correlationId: asCommandId("cmd-manager-bootstrap"), - metadata: {}, - payload: { - projectId: asProjectId("manager-workspace"), - title: "Manager Workspace", - workspaceRoot: "/tmp/manager", - managerMetadata: { role: "workspace" }, - defaultModelSelection: { - instanceId: ProviderInstanceId.make("codex"), - model: "gpt-5-codex", - }, - scripts: [], - createdAt: now, - updatedAt: now, - }, - }), - ); - - model = await Effect.runPromise( - projectEvent(model, { - sequence: 2, - eventId: asEventId("evt-thread-manager-console"), - aggregateKind: "thread", - aggregateId: asThreadId("manager-console"), - type: "thread.created", - occurredAt: now, - commandId: asCommandId("cmd-manager-bootstrap"), - causationEventId: null, - correlationId: asCommandId("cmd-manager-bootstrap"), - metadata: {}, - payload: { - threadId: asThreadId("manager-console"), - projectId: asProjectId("manager-workspace"), - title: "Manager Console", - managerMetadata: { role: "console" }, - modelSelection: { - instanceId: ProviderInstanceId.make("codex"), - model: "gpt-5-codex", - }, - runtimeMode: "full-access", - interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, - branch: null, - worktreePath: "/tmp/manager", - createdAt: now, - updatedAt: now, - }, - }), - ); - - // App project - model = await Effect.runPromise( - projectEvent(model, { - sequence: 3, - eventId: asEventId("evt-project-app"), - aggregateKind: "project", - aggregateId: asProjectId("app-project"), - type: "project.created", - occurredAt: now, - commandId: asCommandId("cmd-project-create"), - causationEventId: null, - correlationId: asCommandId("cmd-project-create"), - metadata: {}, - payload: { - projectId: asProjectId("app-project"), - title: "App Project", - workspaceRoot: "/tmp/app", - defaultModelSelection: { - instanceId: ProviderInstanceId.make("codex"), - model: "gpt-5-codex", - }, - scripts: [], - createdAt: now, - updatedAt: now, - }, - }), - ); - - // Worker thread delegated from manager - model = await Effect.runPromise( - projectEvent(model, { - sequence: 4, - eventId: asEventId("evt-thread-worker"), - aggregateKind: "thread", - aggregateId: asThreadId("worker-thread-1"), - type: "thread.created", - occurredAt: now, - commandId: asCommandId("cmd-worker-delegate"), - causationEventId: null, - correlationId: asCommandId("cmd-worker-delegate"), - metadata: {}, - payload: { - threadId: asThreadId("worker-thread-1"), - projectId: asProjectId("app-project"), - title: "Billing CSV export", - managerMetadata: { - role: "worker", - managerThreadId: asThreadId("manager-console"), - seededWorkItemId: "work-refine", - sourceBody: "The original Jira description for billing CSV export.", - refinedBrief: "Users can export billing data as CSV from the invoices screen.", - acceptanceCriteria: ["Export button visible", "CSV includes invoice data"], - }, - modelSelection: { - instanceId: ProviderInstanceId.make("codex"), - model: "gpt-5-codex", - }, - runtimeMode: "full-access", - interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, - branch: null, - worktreePath: null, - createdAt: now, - updatedAt: now, - }, - }), - ); - - // Escalation on manager console - model = await Effect.runPromise( - projectEvent(model, { - sequence: 5, - eventId: asEventId("evt-escalation-001"), - aggregateKind: "thread", - aggregateId: asThreadId("manager-console"), - type: "thread.manager-queue-items-upserted", - occurredAt: "2026-01-01T00:00:05.000Z", - commandId: asCommandId("cmd-escalate-001"), - causationEventId: null, - correlationId: asCommandId("cmd-escalate-001"), - metadata: {}, - payload: { - threadId: asThreadId("manager-console"), - managerQueueItems: [ - { - itemId: "escalation-001", - escalationThreadId: asThreadId("worker-thread-1"), - category: "blocker", - summary: "Need approval for file deletion", - detail: "The worker wants to delete src/legacy/ but it may be used by other teams.", - status: "pending", - createdAt: "2026-01-01T00:00:05.000Z", - addressedAt: null, - dismissedAt: null, - }, - ], - updatedAt: "2026-01-01T00:00:05.000Z", - }, - }), - ); - - return model; -} - -function normalizeEvents(events: PlannedEvent | ReadonlyArray): PlannedEvent[] { - const list = Array.isArray(events) ? events : [events]; - return list.map((entry) => { - if (entry.type === "thread.manager-queue-items-upserted") { - return { - type: entry.type, - aggregateKind: entry.aggregateKind, - aggregateId: entry.aggregateId, - payload: entry.payload, - }; - } - if (entry.type === "thread.activity-appended") { - return { - type: entry.type, - aggregateKind: entry.aggregateKind, - aggregateId: entry.aggregateId, - payload: entry.payload, - }; - } - return entry; - }); -} - -describe("manager.resolve-queue-item", () => { - it("resolves pending queue item and writes instruction to worker thread", async () => { - const readModel = await seedResolutionReadModel(); - const createdAt = "2026-01-01T00:00:10.000Z"; - - const command: OrchestrationCommand = { - type: "manager.resolve-queue-item", - commandId: asCommandId("cmd-resolve-1"), - threadId: asThreadId("manager-console"), - itemId: "escalation-001", - instruction: "Go ahead and delete the legacy directory.", - createdAt, - }; - - const result = await Effect.runPromise(decideOrchestrationCommand({ command, readModel })); - - const events = normalizeEvents(result); - - expect(events).toEqual([ - expect.objectContaining({ - type: "thread.manager-queue-items-upserted", - aggregateKind: "thread", - aggregateId: asThreadId("manager-console"), - payload: expect.objectContaining({ - threadId: asThreadId("manager-console"), - managerQueueItems: [ - expect.objectContaining({ - itemId: "escalation-001", - escalationThreadId: asThreadId("worker-thread-1"), - category: "blocker", - summary: "Need approval for file deletion", - detail: "The worker wants to delete src/legacy/ but it may be used by other teams.", - status: "addressed", - createdAt: "2026-01-01T00:00:05.000Z", - addressedAt: createdAt, - dismissedAt: null, - }), - ], - updatedAt: createdAt, - }), - }), - expect.objectContaining({ - type: "thread.activity-appended", - aggregateKind: "thread", - aggregateId: asThreadId("worker-thread-1"), - payload: expect.objectContaining({ - threadId: asThreadId("worker-thread-1"), - activity: expect.objectContaining({ - tone: "info", - kind: "manager.queue-item.resolved", - summary: "Go ahead and delete the legacy directory.", - payload: expect.objectContaining({ - queueItemId: "escalation-001", - category: "blocker", - }), - turnId: null, - createdAt, - }), - }), - }), - ]); - }); - - it("preserves other queue items in FIFO order when one is resolved", async () => { - let readModel = await seedResolutionReadModel(); - - // Add a second queue item - readModel = await Effect.runPromise( - projectEvent(readModel, { - sequence: 6, - eventId: asEventId("evt-escalation-002"), - aggregateKind: "thread", - aggregateId: asThreadId("manager-console"), - type: "thread.manager-queue-items-upserted", - occurredAt: "2026-01-01T00:00:07.000Z", - commandId: asCommandId("cmd-escalate-002"), - causationEventId: null, - correlationId: asCommandId("cmd-escalate-002"), - metadata: {}, - payload: { - threadId: asThreadId("manager-console"), - managerQueueItems: [ - { - itemId: "escalation-001", - escalationThreadId: asThreadId("worker-thread-1"), - category: "blocker", - summary: "Need approval for file deletion", - detail: "The worker wants to delete src/legacy/ but it may be used by other teams.", - status: "pending", - createdAt: "2026-01-01T00:00:05.000Z", - addressedAt: null, - dismissedAt: null, - }, - { - itemId: "escalation-002", - escalationThreadId: asThreadId("worker-thread-1"), - category: "question", - summary: "Which logging library?", - detail: "Should we use pino or winston?", - status: "pending", - createdAt: "2026-01-01T00:00:07.000Z", - addressedAt: null, - dismissedAt: null, - }, - ], - updatedAt: "2026-01-01T00:00:07.000Z", - }, - }), - ); - - const createdAt = "2026-01-01T00:00:10.000Z"; - - // Resolve the first item - const command: OrchestrationCommand = { - type: "manager.resolve-queue-item", - commandId: asCommandId("cmd-resolve-1"), - threadId: asThreadId("manager-console"), - itemId: "escalation-001", - instruction: "Use pino, it's faster.", - createdAt, - }; - - const result = await Effect.runPromise(decideOrchestrationCommand({ command, readModel })); - - const events = normalizeEvents(result); - - expect(events).toEqual([ - expect.objectContaining({ - type: "thread.manager-queue-items-upserted", - aggregateKind: "thread", - aggregateId: asThreadId("manager-console"), - payload: expect.objectContaining({ - threadId: asThreadId("manager-console"), - managerQueueItems: [ - expect.objectContaining({ - itemId: "escalation-001", - status: "addressed", - addressedAt: createdAt, - }), - expect.objectContaining({ - itemId: "escalation-002", - status: "pending", - }), - ], - updatedAt: createdAt, - }), - }), - expect.objectContaining({ - type: "thread.activity-appended", - aggregateKind: "thread", - aggregateId: asThreadId("worker-thread-1"), - }), - ]); - }); - - it("rejects when thread is not the Manager Console", async () => { - const readModel = await seedResolutionReadModel(); - const createdAt = "2026-01-01T00:00:10.000Z"; - - const command: OrchestrationCommand = { - type: "manager.resolve-queue-item", - commandId: asCommandId("cmd-resolve-bad"), - threadId: asThreadId("worker-thread-1"), - itemId: "escalation-001", - instruction: "This should fail.", - createdAt, - }; - - await expect( - Effect.runPromise(decideOrchestrationCommand({ command, readModel })), - ).rejects.toEqual( - expect.objectContaining({ - detail: expect.stringContaining("is not the Manager Console"), - }), - ); - }); - - it("rejects when queue item is not found", async () => { - const readModel = await seedResolutionReadModel(); - const createdAt = "2026-01-01T00:00:10.000Z"; - - const command: OrchestrationCommand = { - type: "manager.resolve-queue-item", - commandId: asCommandId("cmd-resolve-missing"), - threadId: asThreadId("manager-console"), - itemId: "nonexistent-item", - instruction: "This should fail.", - createdAt, - }; - - await expect( - Effect.runPromise(decideOrchestrationCommand({ command, readModel })), - ).rejects.toEqual( - expect.objectContaining({ - detail: expect.stringContaining("not found on Manager Console"), - }), - ); - }); - - it("rejects when queue item is already addressed", async () => { - let readModel = await seedResolutionReadModel(); - - // Mark item as already addressed - readModel = await Effect.runPromise( - projectEvent(readModel, { - sequence: 6, - eventId: asEventId("evt-resolved-already"), - aggregateKind: "thread", - aggregateId: asThreadId("manager-console"), - type: "thread.manager-queue-items-upserted", - occurredAt: "2026-01-01T00:00:07.000Z", - commandId: asCommandId("cmd-resolve-prev"), - causationEventId: null, - correlationId: asCommandId("cmd-resolve-prev"), - metadata: {}, - payload: { - threadId: asThreadId("manager-console"), - managerQueueItems: [ - { - itemId: "escalation-001", - escalationThreadId: asThreadId("worker-thread-1"), - category: "blocker", - summary: "Need approval for file deletion", - detail: "The worker wants to delete src/legacy/ but it may be used by other teams.", - status: "addressed", - createdAt: "2026-01-01T00:00:05.000Z", - addressedAt: "2026-01-01T00:00:07.000Z", - dismissedAt: null, - }, - ], - updatedAt: "2026-01-01T00:00:07.000Z", - }, - }), - ); - - const createdAt = "2026-01-01T00:00:10.000Z"; - - const command: OrchestrationCommand = { - type: "manager.resolve-queue-item", - commandId: asCommandId("cmd-resolve-dup"), - threadId: asThreadId("manager-console"), - itemId: "escalation-001", - instruction: "This should fail.", - createdAt, - }; - - await expect( - Effect.runPromise(decideOrchestrationCommand({ command, readModel })), - ).rejects.toEqual( - expect.objectContaining({ - detail: expect.stringContaining("cannot be resolved because it is already"), - }), - ); - }); - - it("rejects when queue item is already dismissed", async () => { - let readModel = await seedResolutionReadModel(); - - // Mark item as dismissed - readModel = await Effect.runPromise( - projectEvent(readModel, { - sequence: 6, - eventId: asEventId("evt-dismissed"), - aggregateKind: "thread", - aggregateId: asThreadId("manager-console"), - type: "thread.manager-queue-items-upserted", - occurredAt: "2026-01-01T00:00:07.000Z", - commandId: asCommandId("cmd-dismiss"), - causationEventId: null, - correlationId: asCommandId("cmd-dismiss"), - metadata: {}, - payload: { - threadId: asThreadId("manager-console"), - managerQueueItems: [ - { - itemId: "escalation-001", - escalationThreadId: asThreadId("worker-thread-1"), - category: "blocker", - summary: "Need approval for file deletion", - detail: "The worker wants to delete src/legacy/ but it may be used by other teams.", - status: "dismissed", - createdAt: "2026-01-01T00:00:05.000Z", - addressedAt: null, - dismissedAt: "2026-01-01T00:00:07.000Z", - }, - ], - updatedAt: "2026-01-01T00:00:07.000Z", - }, - }), - ); - - const createdAt = "2026-01-01T00:00:10.000Z"; - - const command: OrchestrationCommand = { - type: "manager.resolve-queue-item", - commandId: asCommandId("cmd-resolve-dismissed"), - threadId: asThreadId("manager-console"), - itemId: "escalation-001", - instruction: "This should fail.", - createdAt, - }; - - await expect( - Effect.runPromise(decideOrchestrationCommand({ command, readModel })), - ).rejects.toEqual( - expect.objectContaining({ - detail: expect.stringContaining("cannot be resolved because it is already"), - }), - ); - }); - - it("rejects when linked escalation thread is not a worker", async () => { - const createdAt = "2026-01-01T00:00:10.000Z"; - - let badModel = await seedResolutionReadModel(); - - // Override the queue item to point to manager-console (not a worker) - badModel = await Effect.runPromise( - projectEvent(badModel, { - sequence: 6, - eventId: asEventId("evt-bad-escalation"), - aggregateKind: "thread", - aggregateId: asThreadId("manager-console"), - type: "thread.manager-queue-items-upserted", - occurredAt: "2026-01-01T00:00:07.000Z", - commandId: asCommandId("cmd-escalate-bad"), - causationEventId: null, - correlationId: asCommandId("cmd-escalate-bad"), - metadata: {}, - payload: { - threadId: asThreadId("manager-console"), - managerQueueItems: [ - { - itemId: "escalation-bad", - escalationThreadId: asThreadId("manager-console"), - category: "blocker", - summary: "Bad escalation to non-worker", - detail: "This escalation points to the manager console itself.", - status: "pending", - createdAt: "2026-01-01T00:00:07.000Z", - addressedAt: null, - dismissedAt: null, - }, - ], - updatedAt: "2026-01-01T00:00:07.000Z", - }, - }), - ); - - const badCommand: OrchestrationCommand = { - type: "manager.resolve-queue-item", - commandId: asCommandId("cmd-resolve-bad"), - threadId: asThreadId("manager-console"), - itemId: "escalation-bad", - instruction: "This should fail.", - createdAt, - }; - - await expect( - Effect.runPromise(decideOrchestrationCommand({ command: badCommand, readModel: badModel })), - ).rejects.toEqual( - expect.objectContaining({ - detail: expect.stringContaining("is not a Worker Thread"), - }), - ); - }); -}); diff --git a/apps/server/src/orchestration/decider.ts b/apps/server/src/orchestration/decider.ts index 5fb407bea03b..7205c3db193f 100644 --- a/apps/server/src/orchestration/decider.ts +++ b/apps/server/src/orchestration/decider.ts @@ -13,14 +13,7 @@ import type * as PlatformError from "effect/PlatformError"; import { OrchestrationCommandInvariantError } from "./Errors.ts"; import { - findThreadById, - findActiveRefinerThreadForSeededWorkItem, - findSeededWorkItemOnManagerConsole, - findManagerConsole, - findManagerWorkspace, listThreadsByProjectId, - requireManagerConsole, - requireNonNegativeInteger, requireProject, requireProjectAbsent, requireThread, @@ -29,20 +22,10 @@ import { requireThreadNotArchived, requireTurnNotActive, } from "./commandInvariants.ts"; -import { - applyRefinementHandoffToSeededWorkItem, - materializeSeededWorkItems, -} from "./managerSeededWork.ts"; import { projectEvent } from "./projector.ts"; const nowIso = Effect.map(DateTime.now, DateTime.formatIso); -const randomEventId: Effect.Effect = - Crypto.Crypto.pipe( - Effect.flatMap((crypto) => crypto.randomUUIDv4), - Effect.map(EventId.make), - ); - function withEventBase( input: Pick & { readonly aggregateKind: OrchestrationEvent["aggregateKind"]; @@ -106,15 +89,7 @@ const decideCommandSequence = Effect.fn("decideCommandSequence")(function* ({ nextReadModel = yield* projectEvent(nextReadModel, { ...nextEvent, sequence: nextSequence, - }).pipe( - Effect.mapError( - () => - new OrchestrationCommandInvariantError({ - commandType: nextCommand.type, - detail: `Projection error in command sequence.`, - }), - ), - ); + }).pipe(Effect.orDie); } } @@ -152,9 +127,6 @@ export const decideOrchestrationCommand = Effect.fn("decideOrchestrationCommand" projectId: command.projectId, title: command.title, workspaceRoot: command.workspaceRoot, - ...(command.managerMetadata !== undefined - ? { managerMetadata: command.managerMetadata } - : {}), defaultModelSelection: command.defaultModelSelection ?? null, scripts: [], createdAt: command.createdAt, @@ -163,428 +135,6 @@ export const decideOrchestrationCommand = Effect.fn("decideOrchestrationCommand" }; } - case "manager.bootstrap": { - const existingWorkspace = findManagerWorkspace(readModel); - if (existingWorkspace !== undefined) { - return yield* new OrchestrationCommandInvariantError({ - commandType: command.type, - detail: `Manager Workspace '${existingWorkspace.id}' already exists.`, - }); - } - const existingConsole = findManagerConsole(readModel); - if (existingConsole !== undefined) { - return yield* new OrchestrationCommandInvariantError({ - commandType: command.type, - detail: `Manager Console '${existingConsole.id}' already exists.`, - }); - } - yield* requireProjectAbsent({ - readModel, - command, - projectId: command.projectId, - }); - yield* requireThreadAbsent({ - readModel, - command, - threadId: command.threadId, - }); - - return [ - { - ...(yield* withEventBase({ - aggregateKind: "project", - aggregateId: command.projectId, - occurredAt: command.createdAt, - commandId: command.commandId, - })), - type: "project.created", - payload: { - projectId: command.projectId, - title: "Manager Workspace", - workspaceRoot: command.workspaceRoot, - managerMetadata: { - role: "workspace", - }, - defaultModelSelection: command.modelSelection, - scripts: [], - createdAt: command.createdAt, - updatedAt: command.createdAt, - }, - }, - { - ...(yield* withEventBase({ - aggregateKind: "thread", - aggregateId: command.threadId, - occurredAt: command.createdAt, - commandId: command.commandId, - })), - type: "thread.created", - payload: { - threadId: command.threadId, - projectId: command.projectId, - title: "Manager Console", - managerMetadata: { - role: "console", - }, - modelSelection: command.modelSelection, - runtimeMode: command.runtimeMode, - interactionMode: command.interactionMode, - branch: null, - worktreePath: command.workspaceRoot, - createdAt: command.createdAt, - updatedAt: command.createdAt, - }, - }, - ]; - } - - case "manager.seed-work-items": { - yield* requireManagerConsole({ - readModel, - command, - threadId: command.threadId, - }); - for (const item of command.items) { - if (item.targetProjectId !== null) { - yield* requireProject({ - readModel, - command, - projectId: item.targetProjectId, - }); - } - } - - const seededWorkItems = materializeSeededWorkItems({ - sourceKind: command.sourceKind, - sourceLabel: command.sourceLabel, - items: command.items, - createdAt: command.createdAt, - }); - - return { - ...(yield* withEventBase({ - aggregateKind: "thread", - aggregateId: command.threadId, - occurredAt: command.createdAt, - commandId: command.commandId, - })), - type: "thread.seeded-work-items-upserted", - payload: { - threadId: command.threadId, - seededWorkItems, - updatedAt: command.createdAt, - }, - }; - } - - case "thread.seeded-work-item-writeback.request": { - const managerConsole = yield* requireManagerConsole({ - readModel, - command, - threadId: command.threadId, - }); - const seededWorkItem = managerConsole.seededWorkItems?.find( - (item) => item.itemId === command.itemId, - ); - if (!seededWorkItem) { - return yield* new OrchestrationCommandInvariantError({ - commandType: command.type, - detail: `Seeded work item '${command.itemId}' does not exist on Manager Console '${command.threadId}'.`, - }); - } - - return { - ...(yield* withEventBase({ - aggregateKind: "thread", - aggregateId: command.threadId, - occurredAt: command.createdAt, - commandId: command.commandId, - })), - type: "thread.seeded-work-item-writeback-requested", - payload: { - threadId: command.threadId, - itemId: seededWorkItem.itemId, - sourceKind: seededWorkItem.sourceKind, - sourceLabel: seededWorkItem.sourceLabel, - title: seededWorkItem.title, - writebackKind: command.writebackKind, - body: command.body, - createdAt: command.createdAt, - }, - }; - } - - case "manager.refiner-thread.create": { - yield* requireManagerConsole({ - readModel, - command, - threadId: command.managerThreadId, - }); - yield* requireThreadAbsent({ - readModel, - command, - threadId: command.threadId, - }); - - const seededWorkItem = findSeededWorkItemOnManagerConsole( - readModel, - command.managerThreadId, - command.seededWorkItemId, - ); - if (seededWorkItem === undefined) { - return yield* new OrchestrationCommandInvariantError({ - commandType: command.type, - detail: `Seeded work item '${command.seededWorkItemId}' does not exist on Manager Console '${command.managerThreadId}'.`, - }); - } - if (seededWorkItem.readiness !== "needs-refinement") { - return yield* new OrchestrationCommandInvariantError({ - commandType: command.type, - detail: `Seeded work item '${command.seededWorkItemId}' is '${seededWorkItem.readiness}' and cannot create a Refiner Thread.`, - }); - } - if (seededWorkItem.targetProjectId === null) { - return yield* new OrchestrationCommandInvariantError({ - commandType: command.type, - detail: `Seeded work item '${command.seededWorkItemId}' does not target a Project for refinement.`, - }); - } - const existingRefinerThread = findActiveRefinerThreadForSeededWorkItem( - readModel, - command.managerThreadId, - command.seededWorkItemId, - ); - if (existingRefinerThread !== undefined) { - return yield* new OrchestrationCommandInvariantError({ - commandType: command.type, - detail: `Seeded work item '${command.seededWorkItemId}' already has active Refiner Thread '${existingRefinerThread.id}'.`, - }); - } - - yield* requireProject({ - readModel, - command, - projectId: seededWorkItem.targetProjectId, - }); - - return { - ...(yield* withEventBase({ - aggregateKind: "thread", - aggregateId: command.threadId, - occurredAt: command.createdAt, - commandId: command.commandId, - })), - type: "thread.created", - payload: { - threadId: command.threadId, - projectId: seededWorkItem.targetProjectId, - title: `Refine: ${seededWorkItem.title}`, - managerMetadata: { - role: "refiner", - managerThreadId: command.managerThreadId, - seededWorkItemId: command.seededWorkItemId, - }, - modelSelection: command.modelSelection, - runtimeMode: command.runtimeMode, - interactionMode: command.interactionMode, - branch: command.branch, - worktreePath: command.worktreePath, - createdAt: command.createdAt, - updatedAt: command.createdAt, - }, - }; - } - - case "manager.refinement-handoff.record": { - const refinerThread = yield* requireThread({ - readModel, - command, - threadId: command.refinerThreadId, - }); - if (refinerThread.managerMetadata?.role !== "refiner") { - return yield* new OrchestrationCommandInvariantError({ - commandType: command.type, - detail: `Thread '${command.refinerThreadId}' is not a Refiner Thread.`, - }); - } - if (command.acceptanceCriteria.length === 0) { - return yield* new OrchestrationCommandInvariantError({ - commandType: command.type, - detail: "Refinement Handoff requires at least one acceptance criterion.", - }); - } - - yield* requireProject({ - readModel, - command, - projectId: command.targetProjectId, - }); - - const managerThreadId = refinerThread.managerMetadata.managerThreadId; - const seededWorkItemId = refinerThread.managerMetadata.seededWorkItemId; - const seededWorkItem = findSeededWorkItemOnManagerConsole( - readModel, - managerThreadId, - seededWorkItemId, - ); - if (seededWorkItem === undefined) { - return yield* new OrchestrationCommandInvariantError({ - commandType: command.type, - detail: `Seeded work item '${seededWorkItemId}' does not exist on Manager Console '${managerThreadId}'.`, - }); - } - - const managerConsole = findThreadById(readModel, managerThreadId); - if (managerConsole?.managerMetadata?.role !== "console") { - return yield* new OrchestrationCommandInvariantError({ - commandType: command.type, - detail: `Thread '${managerThreadId}' is not the Manager Console for command '${command.type}'.`, - }); - } - - const nextSeededWorkItem = applyRefinementHandoffToSeededWorkItem({ - seededWorkItem, - refinementHandoff: { - refinerThreadId: command.refinerThreadId, - sourceBody: seededWorkItem.body, - refinedProblemStatement: command.refinedProblemStatement, - acceptanceCriteria: command.acceptanceCriteria, - targetProjectId: command.targetProjectId, - recordedAt: command.createdAt, - }, - }); - const seededWorkItems = (managerConsole.seededWorkItems ?? []).map((item) => - item.itemId === seededWorkItemId ? nextSeededWorkItem : item, - ); - - return [ - { - ...(yield* withEventBase({ - aggregateKind: "thread", - aggregateId: managerThreadId, - occurredAt: command.createdAt, - commandId: command.commandId, - })), - type: "thread.seeded-work-items-upserted", - payload: { - threadId: managerThreadId, - seededWorkItems, - updatedAt: command.createdAt, - }, - }, - ...(nextSeededWorkItem.delegationStatus === "requested" - ? [ - { - ...(yield* withEventBase({ - aggregateKind: "thread" as const, - aggregateId: managerThreadId, - occurredAt: command.createdAt, - commandId: command.commandId, - })), - type: "thread.activity-appended" as const, - payload: { - threadId: managerThreadId, - activity: { - id: yield* randomEventId, - tone: "info" as const, - kind: "manager.delegation.requested", - summary: `Auto-requested worker delegation for '${seededWorkItem.title}'.`, - payload: { - seededWorkItemId, - refinerThreadId: command.refinerThreadId, - targetProjectId: command.targetProjectId, - }, - turnId: null, - createdAt: command.createdAt, - }, - }, - }, - ] - : []), - ]; - } - - case "worker.delegate": { - const refinerThread = yield* requireThread({ - readModel, - command, - threadId: command.refinerThreadId, - }); - if (refinerThread.managerMetadata?.role !== "refiner") { - return yield* new OrchestrationCommandInvariantError({ - commandType: command.type, - detail: `Thread '${command.refinerThreadId}' is not a Refiner Thread.`, - }); - } - - const managerThreadId = refinerThread.managerMetadata.managerThreadId; - const seededWorkItemId = refinerThread.managerMetadata.seededWorkItemId; - const seededWorkItem = findSeededWorkItemOnManagerConsole( - readModel, - managerThreadId, - seededWorkItemId, - ); - if (seededWorkItem === undefined) { - return yield* new OrchestrationCommandInvariantError({ - commandType: command.type, - detail: `Seeded work item '${seededWorkItemId}' does not exist on Manager Console '${managerThreadId}'.`, - }); - } - if (!seededWorkItem.refinementHandoff) { - return yield* new OrchestrationCommandInvariantError({ - commandType: command.type, - detail: `Seeded work item '${seededWorkItemId}' does not have a refinement handoff.`, - }); - } - if (seededWorkItem.delegationStatus !== "requested") { - return yield* new OrchestrationCommandInvariantError({ - commandType: command.type, - detail: `Seeded work item '${seededWorkItemId}' delegation status is '${seededWorkItem.delegationStatus}' and cannot create a Worker Thread.`, - }); - } - - yield* requireProject({ - readModel, - command, - projectId: seededWorkItem.refinementHandoff.targetProjectId, - }); - yield* requireThreadAbsent({ - readModel, - command, - threadId: command.workerThreadId, - }); - - return { - ...(yield* withEventBase({ - aggregateKind: "thread", - aggregateId: command.workerThreadId, - occurredAt: command.createdAt, - commandId: command.commandId, - })), - type: "thread.created", - payload: { - threadId: command.workerThreadId, - projectId: seededWorkItem.refinementHandoff.targetProjectId, - title: seededWorkItem.title, - managerMetadata: { - role: "worker", - managerThreadId, - seededWorkItemId, - sourceBody: seededWorkItem.refinementHandoff.sourceBody, - refinedBrief: seededWorkItem.refinementHandoff.refinedProblemStatement, - acceptanceCriteria: seededWorkItem.refinementHandoff.acceptanceCriteria, - }, - modelSelection: command.modelSelection, - runtimeMode: command.runtimeMode, - interactionMode: command.interactionMode, - branch: command.branch, - worktreePath: command.worktreePath, - createdAt: command.createdAt, - updatedAt: command.createdAt, - }, - }; - } - case "project.meta.update": { yield* requireProject({ readModel, @@ -687,9 +237,6 @@ export const decideOrchestrationCommand = Effect.fn("decideOrchestrationCommand" threadId: command.threadId, projectId: command.projectId, title: command.title, - ...(command.managerMetadata !== undefined - ? { managerMetadata: command.managerMetadata } - : {}), modelSelection: command.modelSelection, runtimeMode: command.runtimeMode, interactionMode: command.interactionMode, @@ -1041,11 +588,6 @@ export const decideOrchestrationCommand = Effect.fn("decideOrchestrationCommand" command, threadId: command.threadId, }); - yield* requireNonNegativeInteger({ - commandType: command.type, - field: "turnCount", - value: command.turnCount, - }); return { ...(yield* withEventBase({ aggregateKind: "thread", @@ -1147,7 +689,8 @@ export const decideOrchestrationCommand = Effect.fn("decideOrchestrationCommand" prunedMessageCount += unkeyedMessages.length; const occurredAt = yield* nowIso; - const trimPointId = yield* randomEventId; + const crypto = yield* Crypto.Crypto; + const trimPointId = EventId.make(yield* crypto.randomUUIDv4); const trimPoint: ContextTrimPoint = { id: trimPointId, createdAt: occurredAt, @@ -1223,7 +766,8 @@ export const decideOrchestrationCommand = Effect.fn("decideOrchestrationCommand" }); yield* requireTurnNotActive({ thread, command }); const occurredAt = yield* nowIso; - const trimPointId = yield* randomEventId; + const crypto = yield* Crypto.Crypto; + const trimPointId = EventId.make(yield* crypto.randomUUIDv4); return [ { ...(yield* withEventBase({ @@ -1420,220 +964,6 @@ export const decideOrchestrationCommand = Effect.fn("decideOrchestrationCommand" }; } - case "worker.escalate": { - const workerThread = yield* requireThread({ - readModel, - command, - threadId: command.threadId, - }); - if (workerThread.managerMetadata?.role !== "worker") { - return yield* new OrchestrationCommandInvariantError({ - commandType: command.type, - detail: `Thread '${command.threadId}' is not a Worker Thread.`, - }); - } - - const managerThreadId = workerThread.managerMetadata.managerThreadId; - if (managerThreadId === undefined) { - return yield* new OrchestrationCommandInvariantError({ - commandType: command.type, - detail: `Worker thread '${command.threadId}' is missing a manager thread reference.`, - }); - } - const managerConsole = yield* requireManagerConsole({ - readModel, - command, - threadId: managerThreadId, - }); - - const existingQueueItems = managerConsole.managerQueueItems ?? []; - const alreadyEscalated = existingQueueItems.some( - (item) => item.itemId === command.escalationId, - ); - if (alreadyEscalated) { - return yield* new OrchestrationCommandInvariantError({ - commandType: command.type, - detail: `Escalation '${command.escalationId}' already exists on Manager Console '${managerThreadId}'.`, - }); - } - - const newQueueItem = { - itemId: command.escalationId, - escalationThreadId: command.threadId, - category: command.category, - summary: command.summary, - detail: command.detail, - status: "pending" as const, - createdAt: command.createdAt, - addressedAt: null as null, - dismissedAt: null as null, - }; - - const managerQueueItems = [...existingQueueItems, newQueueItem]; - - return { - ...(yield* withEventBase({ - aggregateKind: "thread", - aggregateId: managerThreadId, - occurredAt: command.createdAt, - commandId: command.commandId, - })), - type: "thread.manager-queue-items-upserted", - payload: { - threadId: managerThreadId, - managerQueueItems, - updatedAt: command.createdAt, - }, - }; - } - - case "manager.resolve-queue-item": { - const managerConsole = yield* requireManagerConsole({ - readModel, - command, - threadId: command.threadId, - }); - - const existingQueueItems = managerConsole.managerQueueItems ?? []; - const queueItemIndex = existingQueueItems.findIndex((item) => item.itemId === command.itemId); - if (queueItemIndex === -1) { - return yield* new OrchestrationCommandInvariantError({ - commandType: command.type, - detail: `Queue item '${command.itemId}' not found on Manager Console '${command.threadId}'.`, - }); - } - - const queueItem = existingQueueItems[queueItemIndex]!; - if (queueItem.status !== "pending") { - return yield* new OrchestrationCommandInvariantError({ - commandType: command.type, - detail: `Queue item '${command.itemId}' cannot be resolved because it is already '${queueItem.status}'.`, - }); - } - - // Capture before yield* boundary so narrowing is preserved - const escalatedThreadId = queueItem.escalationThreadId; - const queueItemCategory = queueItem.category; - const workerThread = yield* requireThread({ - readModel, - command, - threadId: escalatedThreadId, - }); - if (workerThread.managerMetadata?.role !== "worker") { - return yield* new OrchestrationCommandInvariantError({ - commandType: command.type, - detail: `Thread '${escalatedThreadId}' is not a Worker Thread.`, - }); - } - - const updatedItem = { - ...queueItem, - status: "addressed" as const, - addressedAt: command.createdAt, - }; - - const updatedQueueItems = [ - ...existingQueueItems.slice(0, queueItemIndex), - updatedItem as typeof queueItem, - ...existingQueueItems.slice(queueItemIndex + 1), - ]; - - return [ - { - ...(yield* withEventBase({ - aggregateKind: "thread" as const, - aggregateId: managerConsole.id, - occurredAt: command.createdAt, - commandId: command.commandId, - })), - type: "thread.manager-queue-items-upserted" as const, - payload: { - threadId: managerConsole.id, - managerQueueItems: updatedQueueItems, - updatedAt: command.createdAt, - }, - }, - { - ...(yield* withEventBase({ - aggregateKind: "thread" as const, - aggregateId: queueItem.escalationThreadId, - occurredAt: command.createdAt, - commandId: command.commandId, - })), - type: "thread.activity-appended" as const, - payload: { - threadId: escalatedThreadId, - activity: { - id: yield* randomEventId, - tone: "info" as const, - kind: "manager.queue-item.resolved", - summary: command.instruction, - payload: { - queueItemId: command.itemId, - category: queueItemCategory, - }, - turnId: null, - createdAt: command.createdAt, - }, - }, - }, - ]; - } - - case "manager.dismiss-queue-item": { - const managerConsole = yield* requireManagerConsole({ - readModel, - command, - threadId: command.threadId, - }); - - const existingQueueItems = managerConsole.managerQueueItems ?? []; - const queueItemIndex = existingQueueItems.findIndex((item) => item.itemId === command.itemId); - if (queueItemIndex === -1) { - return yield* new OrchestrationCommandInvariantError({ - commandType: command.type, - detail: `Queue item '${command.itemId}' not found on Manager Console '${command.threadId}'.`, - }); - } - - const queueItem = existingQueueItems[queueItemIndex]!; - if (queueItem.status !== "pending") { - return yield* new OrchestrationCommandInvariantError({ - commandType: command.type, - detail: `Queue item '${command.itemId}' cannot be dismissed because it is already '${queueItem.status}'.`, - }); - } - - const dismissedItem = { - ...queueItem, - status: "dismissed" as const, - dismissedAt: command.createdAt, - }; - - const updatedQueueItems = [ - ...existingQueueItems.slice(0, queueItemIndex), - dismissedItem as typeof queueItem, - ...existingQueueItems.slice(queueItemIndex + 1), - ]; - - return { - ...(yield* withEventBase({ - aggregateKind: "thread" as const, - aggregateId: managerConsole.id, - occurredAt: command.createdAt, - commandId: command.commandId, - })), - type: "thread.manager-queue-items-upserted" as const, - payload: { - threadId: managerConsole.id, - managerQueueItems: updatedQueueItems, - updatedAt: command.createdAt, - }, - }; - } - - // NOTE: thread.context.summarize (issue #87) must also guard against - // active turns using requireTurnNotActive when the command is implemented. default: { command satisfies never; const fallback = command as never as { type: string }; diff --git a/apps/server/src/orchestration/decider.worker.test.ts b/apps/server/src/orchestration/decider.worker.test.ts deleted file mode 100644 index 2bcf8d6761c6..000000000000 --- a/apps/server/src/orchestration/decider.worker.test.ts +++ /dev/null @@ -1,369 +0,0 @@ -import { - CommandId, - DEFAULT_PROVIDER_INTERACTION_MODE, - EventId, - ProjectId, - ThreadId, - type OrchestrationCommand, - type OrchestrationEvent, - type OrchestrationReadModel, - ProviderInstanceId, -} from "@t3tools/contracts"; -import * as Effect from "effect/Effect"; -import { describe, expect, it } from "vite-plus/test"; - -import { NodeCrypto } from "@effect/platform-node"; - -import { decideOrchestrationCommand as decideOrchestrationCommandRaw } from "./decider.ts"; - -const decideOrchestrationCommand = (input: Parameters[0]) => - decideOrchestrationCommandRaw(input).pipe(Effect.provide(NodeCrypto.layer)); -import { createEmptyReadModel, projectEvent } from "./projector.ts"; - -const asCommandId = (value: string): CommandId => CommandId.make(value); -const asEventId = (value: string): EventId => EventId.make(value); -const asProjectId = (value: string): ProjectId => ProjectId.make(value); -const asThreadId = (value: string): ThreadId => ThreadId.make(value); - -type PlannedEvent = Omit; - -async function seedWorkerDelegationReadModel(): Promise { - const now = "2026-01-01T00:00:00.000Z"; - let model = createEmptyReadModel(now); - - const eventIds = { - projectManager: asEventId("evt-project-manager"), - threadManagerConsole: asEventId("evt-thread-manager-console"), - projectApp: asEventId("evt-project-app"), - threadRefiner: asEventId("evt-thread-refiner"), - seedWorkItems: asEventId("evt-seed-work-items"), - }; - - model = await Effect.runPromise( - projectEvent(model, { - sequence: 1, - eventId: eventIds.projectManager, - aggregateKind: "project", - aggregateId: asProjectId("manager-workspace"), - type: "project.created", - occurredAt: now, - commandId: asCommandId("cmd-manager-bootstrap"), - causationEventId: null, - correlationId: asCommandId("cmd-manager-bootstrap"), - metadata: {}, - payload: { - projectId: asProjectId("manager-workspace"), - title: "Manager Workspace", - workspaceRoot: "/tmp/manager", - managerMetadata: { role: "workspace" }, - defaultModelSelection: { - instanceId: ProviderInstanceId.make("codex"), - model: "gpt-5-codex", - }, - scripts: [], - createdAt: now, - updatedAt: now, - }, - }), - ); - - model = await Effect.runPromise( - projectEvent(model, { - sequence: 2, - eventId: eventIds.threadManagerConsole, - aggregateKind: "thread", - aggregateId: asThreadId("manager-console"), - type: "thread.created", - occurredAt: now, - commandId: asCommandId("cmd-manager-bootstrap"), - causationEventId: null, - correlationId: asCommandId("cmd-manager-bootstrap"), - metadata: {}, - payload: { - threadId: asThreadId("manager-console"), - projectId: asProjectId("manager-workspace"), - title: "Manager Console", - managerMetadata: { role: "console" }, - modelSelection: { - instanceId: ProviderInstanceId.make("codex"), - model: "gpt-5-codex", - }, - runtimeMode: "full-access", - interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, - branch: null, - worktreePath: "/tmp/manager", - createdAt: now, - updatedAt: now, - }, - }), - ); - - model = await Effect.runPromise( - projectEvent(model, { - sequence: 3, - eventId: eventIds.projectApp, - aggregateKind: "project", - aggregateId: asProjectId("app-project"), - type: "project.created", - occurredAt: now, - commandId: asCommandId("cmd-project-create"), - causationEventId: null, - correlationId: asCommandId("cmd-project-create"), - metadata: {}, - payload: { - projectId: asProjectId("app-project"), - title: "App Project", - workspaceRoot: "/tmp/app", - defaultModelSelection: { - instanceId: ProviderInstanceId.make("codex"), - model: "gpt-5-codex", - }, - scripts: [], - createdAt: now, - updatedAt: now, - }, - }), - ); - - model = await Effect.runPromise( - projectEvent(model, { - sequence: 4, - eventId: eventIds.seedWorkItems, - aggregateKind: "thread", - aggregateId: asThreadId("manager-console"), - type: "thread.seeded-work-items-upserted", - occurredAt: now, - commandId: asCommandId("cmd-seed"), - causationEventId: null, - correlationId: asCommandId("cmd-seed"), - metadata: {}, - payload: { - threadId: asThreadId("manager-console"), - seededWorkItems: [ - { - itemId: "work-refine", - sourceKind: "todo-list", - sourceLabel: "Sprint Backlog", - title: "Billing CSV export", - body: "The original Jira description for billing CSV export.", - delegationIntent: "delegate", - targetProjectId: asProjectId("app-project"), - acceptanceCriteria: ["Export button visible", "CSV includes invoice data"], - refinementHandoff: { - refinerThreadId: asThreadId("refiner-thread-1"), - sourceBody: "The original Jira description for billing CSV export.", - refinedProblemStatement: - "Users can export billing data as CSV from the invoices screen.", - acceptanceCriteria: ["Export button visible", "CSV includes invoice data"], - targetProjectId: asProjectId("app-project"), - recordedAt: "2026-01-01T00:00:05.000Z", - }, - readiness: "ready-for-worker", - readinessReason: "Has project and acceptance criteria.", - delegationStatus: "requested", - delegationRequestedAt: "2026-01-01T00:00:05.000Z", - createdAt: now, - updatedAt: "2026-01-01T00:00:05.000Z", - }, - ], - updatedAt: now, - }, - }), - ); - - model = await Effect.runPromise( - projectEvent(model, { - sequence: 5, - eventId: eventIds.threadRefiner, - aggregateKind: "thread", - aggregateId: asThreadId("refiner-thread-1"), - type: "thread.created", - occurredAt: now, - commandId: asCommandId("cmd-create-refiner"), - causationEventId: null, - correlationId: asCommandId("cmd-create-refiner"), - metadata: {}, - payload: { - threadId: asThreadId("refiner-thread-1"), - projectId: asProjectId("app-project"), - title: "Refine: Billing CSV export", - managerMetadata: { - role: "refiner", - managerThreadId: asThreadId("manager-console"), - seededWorkItemId: "work-refine", - }, - modelSelection: { - instanceId: ProviderInstanceId.make("codex"), - model: "gpt-5-codex", - }, - runtimeMode: "full-access", - interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, - branch: null, - worktreePath: null, - createdAt: now, - updatedAt: now, - }, - }), - ); - - return model; -} - -function normalizeEvent(event: PlannedEvent | ReadonlyArray): PlannedEvent[] { - const events = Array.isArray(event) ? event : [event]; - return events.map((entry) => { - if (entry.type === "thread.created") { - return { - type: entry.type, - aggregateKind: entry.aggregateKind, - aggregateId: entry.aggregateId, - payload: entry.payload, - }; - } - return entry; - }); -} - -describe("worker.delegate", () => { - it("creates a Worker Thread in the target project with correct metadata", async () => { - const readModel = await seedWorkerDelegationReadModel(); - const createdAt = "2026-01-01T00:00:10.000Z"; - - const command: OrchestrationCommand = { - type: "worker.delegate", - commandId: asCommandId("cmd-worker-delegate"), - workerThreadId: asThreadId("worker-thread-1"), - refinerThreadId: asThreadId("refiner-thread-1"), - modelSelection: { - instanceId: ProviderInstanceId.make("codex"), - model: "gpt-5-codex", - }, - runtimeMode: "full-access", - interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, - branch: null, - worktreePath: null, - createdAt, - }; - - const result = await Effect.runPromise(decideOrchestrationCommand({ command, readModel })); - - const events = normalizeEvent(result); - - expect(events).toEqual([ - expect.objectContaining({ - type: "thread.created", - aggregateKind: "thread", - aggregateId: asThreadId("worker-thread-1"), - payload: expect.objectContaining({ - threadId: asThreadId("worker-thread-1"), - projectId: asProjectId("app-project"), - title: "Billing CSV export", - managerMetadata: { - role: "worker", - managerThreadId: asThreadId("manager-console"), - seededWorkItemId: "work-refine", - sourceBody: "The original Jira description for billing CSV export.", - refinedBrief: "Users can export billing data as CSV from the invoices screen.", - acceptanceCriteria: ["Export button visible", "CSV includes invoice data"], - }, - modelSelection: { - instanceId: ProviderInstanceId.make("codex"), - model: "gpt-5-codex", - }, - runtimeMode: "full-access", - interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, - branch: null, - worktreePath: null, - createdAt, - updatedAt: createdAt, - }), - }), - ]); - }); - - it("rejects delegation if the seeded work item has no refinement handoff", async () => { - const readModel = await seedWorkerDelegationReadModel(); - const createdAt = "2026-01-01T00:00:10.000Z"; - - const readModelWithoutHandoff: OrchestrationReadModel = { - ...readModel, - threads: readModel.threads.map((thread) => { - if (thread.id !== asThreadId("manager-console")) return thread; - return Object.assign({}, thread, { - seededWorkItems: thread.seededWorkItems?.map((item) => { - const copy = { ...item, refinementHandoff: undefined }; - return copy; - }), - }); - }), - }; - - const command: OrchestrationCommand = { - type: "worker.delegate", - commandId: asCommandId("cmd-worker-delegate"), - workerThreadId: asThreadId("worker-thread-1"), - refinerThreadId: asThreadId("refiner-thread-1"), - modelSelection: { - instanceId: ProviderInstanceId.make("codex"), - model: "gpt-5-codex", - }, - runtimeMode: "full-access", - interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, - branch: null, - worktreePath: null, - createdAt, - }; - - await expect( - Effect.runPromise( - decideOrchestrationCommand({ command, readModel: readModelWithoutHandoff }), - ), - ).rejects.toEqual( - expect.objectContaining({ - detail: expect.stringContaining("does not have a refinement handoff"), - }), - ); - }); - - it("rejects delegation if the seeded work item is not delegation-requested", async () => { - const readModel = await seedWorkerDelegationReadModel(); - const createdAt = "2026-01-01T00:00:10.000Z"; - - const readModelNotRequested: OrchestrationReadModel = { - ...readModel, - threads: readModel.threads.map((thread) => { - if (thread.id !== asThreadId("manager-console")) return thread; - return Object.assign({}, thread, { - seededWorkItems: thread.seededWorkItems?.map((item) => { - const copy = { ...item, delegationStatus: "idle" as const }; - return copy; - }), - }); - }), - }; - - const command: OrchestrationCommand = { - type: "worker.delegate", - commandId: asCommandId("cmd-worker-delegate"), - workerThreadId: asThreadId("worker-thread-1"), - refinerThreadId: asThreadId("refiner-thread-1"), - modelSelection: { - instanceId: ProviderInstanceId.make("codex"), - model: "gpt-5-codex", - }, - runtimeMode: "full-access", - interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE, - branch: null, - worktreePath: null, - createdAt, - }; - - await expect( - Effect.runPromise(decideOrchestrationCommand({ command, readModel: readModelNotRequested })), - ).rejects.toEqual( - expect.objectContaining({ - detail: expect.stringContaining("delegation status is 'idle'"), - }), - ); - }); -}); diff --git a/apps/server/src/orchestration/managerSeededWork.test.ts b/apps/server/src/orchestration/managerSeededWork.test.ts deleted file mode 100644 index 1f802b08dc36..000000000000 --- a/apps/server/src/orchestration/managerSeededWork.test.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { ProjectId, ThreadId } from "@t3tools/contracts"; -import { describe, expect, it } from "vite-plus/test"; - -import { - applyRefinementHandoffToSeededWorkItem, - materializeSeededWorkItems, -} from "./managerSeededWork.ts"; - -describe("manager seeded work classification", () => { - it("classifies seeded work items by delegation readiness", () => { - const seededWorkItems = materializeSeededWorkItems({ - sourceKind: "todo-list", - sourceLabel: "Sprint Backlog", - createdAt: "2026-01-01T00:00:00.000Z", - items: [ - { - itemId: "work-ready", - title: "Ready item", - body: "Has a project and acceptance criteria.", - delegationIntent: "delegate", - targetProjectId: ProjectId.make("project-a"), - acceptanceCriteria: ["Done"], - }, - { - itemId: "work-refine", - title: "Needs refinement", - body: "No acceptance criteria yet.", - delegationIntent: "delegate", - targetProjectId: ProjectId.make("project-a"), - acceptanceCriteria: [], - }, - { - itemId: "work-human", - title: "Human owned", - body: "Keep this with the human.", - delegationIntent: "human-owned", - targetProjectId: ProjectId.make("project-a"), - acceptanceCriteria: ["Handled"], - }, - { - itemId: "work-blocked", - title: "Blocked on context", - body: "Needs a project selection first.", - delegationIntent: "delegate", - targetProjectId: null, - acceptanceCriteria: ["Investigated"], - }, - ], - }); - - expect(seededWorkItems.map((item) => item.readiness)).toEqual([ - "ready-for-worker", - "needs-refinement", - "human-owned", - "blocked-on-context", - ]); - expect(seededWorkItems.map((item) => item.delegationStatus)).toEqual([ - "idle", - "idle", - "idle", - "idle", - ]); - }); - - it("applies a refinement handoff and marks ready work for delegation", () => { - const [seededWorkItem] = materializeSeededWorkItems({ - sourceKind: "todo-list", - sourceLabel: "Sprint Backlog", - createdAt: "2026-01-01T00:00:00.000Z", - items: [ - { - itemId: "work-refine", - title: "Needs refinement", - body: "No acceptance criteria yet.", - delegationIntent: "delegate", - targetProjectId: ProjectId.make("project-a"), - acceptanceCriteria: [], - }, - ], - }); - - const next = applyRefinementHandoffToSeededWorkItem({ - seededWorkItem: seededWorkItem!, - refinementHandoff: { - refinerThreadId: ThreadId.make("refiner-thread-1"), - sourceBody: "No acceptance criteria yet.", - refinedProblemStatement: "Support CSV export from billing history.", - acceptanceCriteria: ["Export action is visible", "CSV download includes invoice rows"], - targetProjectId: ProjectId.make("project-b"), - recordedAt: "2026-01-01T00:00:05.000Z", - }, - }); - - expect(next.body).toBe("Support CSV export from billing history."); - expect(next.targetProjectId).toBe("project-b"); - expect(next.readiness).toBe("ready-for-worker"); - expect(next.delegationStatus).toBe("requested"); - expect(next.delegationRequestedAt).toBe("2026-01-01T00:00:05.000Z"); - expect(next.refinementHandoff).toEqual({ - refinerThreadId: "refiner-thread-1", - sourceBody: "No acceptance criteria yet.", - refinedProblemStatement: "Support CSV export from billing history.", - acceptanceCriteria: ["Export action is visible", "CSV download includes invoice rows"], - targetProjectId: "project-b", - recordedAt: "2026-01-01T00:00:05.000Z", - }); - }); -}); diff --git a/apps/server/src/orchestration/managerSeededWork.ts b/apps/server/src/orchestration/managerSeededWork.ts deleted file mode 100644 index 5c0479d67694..000000000000 --- a/apps/server/src/orchestration/managerSeededWork.ts +++ /dev/null @@ -1,91 +0,0 @@ -import type { - ManagerSeededWorkItem, - ManagerSeededWorkItemInput, - RefinementHandoff, - SeededWorkSourceKind, - WorkReadiness, -} from "@t3tools/contracts"; - -function classifySeededWorkItem(input: ManagerSeededWorkItemInput): { - readonly readiness: WorkReadiness; - readonly readinessReason: string; -} { - if (input.delegationIntent === "human-owned") { - return { - readiness: "human-owned", - readinessReason: "The item is explicitly reserved for the human operator.", - }; - } - - if (input.targetProjectId === null) { - return { - readiness: "blocked-on-context", - readinessReason: "Delegation Intake requires a target Project before work can be routed.", - }; - } - - if (input.acceptanceCriteria.length === 0) { - return { - readiness: "needs-refinement", - readinessReason: "Delegation Intake needs acceptance criteria before worker delegation.", - }; - } - - return { - readiness: "ready-for-worker", - readinessReason: "Delegation Intake found a target Project and explicit acceptance criteria.", - }; -} - -export function applyRefinementHandoffToSeededWorkItem(input: { - readonly seededWorkItem: ManagerSeededWorkItem; - readonly refinementHandoff: RefinementHandoff; -}): ManagerSeededWorkItem { - const classification = classifySeededWorkItem({ - itemId: input.seededWorkItem.itemId, - title: input.seededWorkItem.title, - body: input.refinementHandoff.refinedProblemStatement, - delegationIntent: input.seededWorkItem.delegationIntent, - targetProjectId: input.refinementHandoff.targetProjectId, - acceptanceCriteria: input.refinementHandoff.acceptanceCriteria, - }); - const delegationRequestedAt = - classification.readiness === "ready-for-worker" - ? (input.seededWorkItem.delegationRequestedAt ?? input.refinementHandoff.recordedAt) - : null; - - return { - ...input.seededWorkItem, - body: input.refinementHandoff.refinedProblemStatement, - acceptanceCriteria: input.refinementHandoff.acceptanceCriteria, - targetProjectId: input.refinementHandoff.targetProjectId, - refinementHandoff: input.refinementHandoff, - readiness: classification.readiness, - readinessReason: classification.readinessReason, - delegationStatus: classification.readiness === "ready-for-worker" ? "requested" : "idle", - delegationRequestedAt, - updatedAt: input.refinementHandoff.recordedAt, - }; -} - -export function materializeSeededWorkItems(input: { - readonly sourceKind: SeededWorkSourceKind; - readonly sourceLabel: string; - readonly items: ReadonlyArray; - readonly createdAt: string; -}): ReadonlyArray { - return input.items.map((item) => { - const classification = classifySeededWorkItem(item); - return { - ...item, - sourceKind: input.sourceKind, - sourceLabel: input.sourceLabel, - readiness: classification.readiness, - readinessReason: classification.readinessReason, - delegationStatus: "idle", - delegationRequestedAt: null, - createdAt: input.createdAt, - updatedAt: input.createdAt, - }; - }); -} diff --git a/apps/server/src/orchestration/projector.test.ts b/apps/server/src/orchestration/projector.test.ts index 9602ebab3c19..cdbb4fa035be 100644 --- a/apps/server/src/orchestration/projector.test.ts +++ b/apps/server/src/orchestration/projector.test.ts @@ -91,8 +91,6 @@ describe("orchestration projector", () => { archivedAt: null, deletedAt: null, messages: [], - seededWorkItems: [], - managerQueueItems: [], proposedPlans: [], activities: [], checkpoints: [], diff --git a/apps/server/src/orchestration/projector.ts b/apps/server/src/orchestration/projector.ts index c80e81c30191..9b5552f5ee3b 100644 --- a/apps/server/src/orchestration/projector.ts +++ b/apps/server/src/orchestration/projector.ts @@ -23,12 +23,10 @@ import { ThreadMetaUpdatedPayload, ThreadProposedPlanUpsertedPayload, ThreadRuntimeModeSetPayload, - ThreadSeededWorkItemsUpsertedPayload, ThreadUnarchivedPayload, ThreadRevertedPayload, ThreadSessionSetPayload, ThreadTurnDiffCompletedPayload, - ThreadManagerQueueItemsUpsertedPayload, ThreadTrimPointCreatedPayload, } from "./Schemas.ts"; @@ -187,9 +185,6 @@ export function projectEvent( id: payload.projectId, title: payload.title, workspaceRoot: payload.workspaceRoot, - ...(payload.managerMetadata !== undefined - ? { managerMetadata: payload.managerMetadata } - : {}), defaultModelSelection: payload.defaultModelSelection, scripts: payload.scripts, createdAt: payload.createdAt, @@ -261,9 +256,6 @@ export function projectEvent( id: payload.threadId, projectId: payload.projectId, title: payload.title, - ...(payload.managerMetadata !== undefined - ? { managerMetadata: payload.managerMetadata } - : {}), modelSelection: payload.modelSelection, runtimeMode: payload.runtimeMode, interactionMode: payload.interactionMode, @@ -275,11 +267,10 @@ export function projectEvent( archivedAt: null, deletedAt: null, messages: [], - seededWorkItems: [], - managerQueueItems: [], proposedPlans: [], activities: [], checkpoints: [], + contextTrimPoints: [], session: null, }, event.type, @@ -306,20 +297,9 @@ export function projectEvent( ); case "thread.seeded-work-items-upserted": - return decodeForEvent( - ThreadSeededWorkItemsUpsertedPayload, - event.payload, - event.type, - "payload", - ).pipe( - Effect.map((payload) => ({ - ...nextBase, - threads: updateThread(nextBase.threads, payload.threadId, { - seededWorkItems: payload.seededWorkItems, - updatedAt: payload.updatedAt, - }), - })), - ); + case "thread.seeded-work-item-writeback-requested": + case "thread.manager-queue-items-upserted": + return Effect.succeed(nextBase); case "thread.archived": return decodeForEvent(ThreadArchivedPayload, event.payload, event.type, "payload").pipe( @@ -677,22 +657,6 @@ export function projectEvent( }), ); - case "thread.manager-queue-items-upserted": - return decodeForEvent( - ThreadManagerQueueItemsUpsertedPayload, - event.payload, - event.type, - "payload", - ).pipe( - Effect.map((payload) => ({ - ...nextBase, - threads: updateThread(nextBase.threads, payload.threadId, { - managerQueueItems: payload.managerQueueItems, - updatedAt: payload.updatedAt, - }), - })), - ); - case "thread.trim-point-created": return decodeForEvent( ThreadTrimPointCreatedPayload, @@ -705,9 +669,10 @@ export function projectEvent( if (!thread) { return nextBase; } - const contextTrimPoints = [...thread.contextTrimPoints, payload.trimPoint].toSorted( - (a, b) => a.createdAt.localeCompare(b.createdAt) || a.id.localeCompare(b.id), - ); + const contextTrimPoints = [ + ...(thread.contextTrimPoints ?? []), + payload.trimPoint, + ].toSorted((a, b) => a.createdAt.localeCompare(b.createdAt) || a.id.localeCompare(b.id)); return { ...nextBase, threads: updateThread(nextBase.threads, payload.threadId, { @@ -737,9 +702,6 @@ export function projectEvent( id: payload.newThreadId, projectId: oldThread.projectId, title: oldThread.title, - ...(oldThread.managerMetadata !== undefined - ? { managerMetadata: oldThread.managerMetadata } - : {}), modelSelection: oldThread.modelSelection, runtimeMode: oldThread.runtimeMode, interactionMode: oldThread.interactionMode, @@ -751,8 +713,6 @@ export function projectEvent( archivedAt: null, deletedAt: null, messages: [], - seededWorkItems: [], - managerQueueItems: [], proposedPlans: [], activities: [], checkpoints: [], diff --git a/apps/server/src/persistence/Layers/ProjectionProjects.ts b/apps/server/src/persistence/Layers/ProjectionProjects.ts index 89197f26715a..c1ca6d3104e6 100644 --- a/apps/server/src/persistence/Layers/ProjectionProjects.ts +++ b/apps/server/src/persistence/Layers/ProjectionProjects.ts @@ -2,10 +2,10 @@ import * as SqlClient from "effect/unstable/sql/SqlClient"; import * as SqlSchema from "effect/unstable/sql/SqlSchema"; import * as Effect from "effect/Effect"; import * as Layer from "effect/Layer"; -import * as Option from "effect/Option"; import * as Schema from "effect/Schema"; +import * as Struct from "effect/Struct"; -import { ManagerProjectMetadata, ModelSelection, ProjectScript } from "@t3tools/contracts"; +import { ModelSelection, ProjectScript } from "@t3tools/contracts"; import { toPersistenceSqlError } from "../Errors.ts"; import { DeleteProjectionProjectInput, @@ -15,33 +15,14 @@ import { type ProjectionProjectRepositoryShape, } from "../Services/ProjectionProjects.ts"; -const ProjectionProjectDbRow = Schema.Struct({ - projectId: ProjectionProject.fields.projectId, - title: ProjectionProject.fields.title, - workspaceRoot: ProjectionProject.fields.workspaceRoot, - managerMetadata: Schema.NullOr(Schema.fromJsonString(ManagerProjectMetadata)), - defaultModelSelection: Schema.NullOr(Schema.fromJsonString(ModelSelection)), - scripts: Schema.fromJsonString(Schema.Array(ProjectScript)), - createdAt: ProjectionProject.fields.createdAt, - updatedAt: ProjectionProject.fields.updatedAt, - deletedAt: ProjectionProject.fields.deletedAt, -}); +const ProjectionProjectDbRow = ProjectionProject.mapFields( + Struct.assign({ + defaultModelSelection: Schema.NullOr(Schema.fromJsonString(ModelSelection)), + scripts: Schema.fromJsonString(Schema.Array(ProjectScript)), + }), +); type ProjectionProjectDbRow = typeof ProjectionProjectDbRow.Type; -function mapProjectionProjectRow(row: ProjectionProjectDbRow) { - return { - projectId: row.projectId, - title: row.title, - workspaceRoot: row.workspaceRoot, - ...(row.managerMetadata !== null ? { managerMetadata: row.managerMetadata } : {}), - defaultModelSelection: row.defaultModelSelection, - scripts: row.scripts, - createdAt: row.createdAt, - updatedAt: row.updatedAt, - deletedAt: row.deletedAt, - }; -} - const makeProjectionProjectRepository = Effect.gen(function* () { const sql = yield* SqlClient.SqlClient; @@ -53,7 +34,6 @@ const makeProjectionProjectRepository = Effect.gen(function* () { project_id, title, workspace_root, - manager_metadata_json, default_model_selection_json, scripts_json, created_at, @@ -64,7 +44,6 @@ const makeProjectionProjectRepository = Effect.gen(function* () { ${row.projectId}, ${row.title}, ${row.workspaceRoot}, - ${row.managerMetadata !== undefined ? JSON.stringify(row.managerMetadata) : null}, ${row.defaultModelSelection !== null ? JSON.stringify(row.defaultModelSelection) : null}, ${JSON.stringify(row.scripts)}, ${row.createdAt}, @@ -75,7 +54,6 @@ const makeProjectionProjectRepository = Effect.gen(function* () { DO UPDATE SET title = excluded.title, workspace_root = excluded.workspace_root, - manager_metadata_json = excluded.manager_metadata_json, default_model_selection_json = excluded.default_model_selection_json, scripts_json = excluded.scripts_json, created_at = excluded.created_at, @@ -93,7 +71,6 @@ const makeProjectionProjectRepository = Effect.gen(function* () { project_id AS "projectId", title, workspace_root AS "workspaceRoot", - manager_metadata_json AS "managerMetadata", default_model_selection_json AS "defaultModelSelection", scripts_json AS "scripts", created_at AS "createdAt", @@ -113,7 +90,6 @@ const makeProjectionProjectRepository = Effect.gen(function* () { project_id AS "projectId", title, workspace_root AS "workspaceRoot", - manager_metadata_json AS "managerMetadata", default_model_selection_json AS "defaultModelSelection", scripts_json AS "scripts", created_at AS "createdAt", @@ -140,13 +116,11 @@ const makeProjectionProjectRepository = Effect.gen(function* () { const getById: ProjectionProjectRepositoryShape["getById"] = (input) => getProjectionProjectRow(input).pipe( - Effect.map(Option.map(mapProjectionProjectRow)), Effect.mapError(toPersistenceSqlError("ProjectionProjectRepository.getById:query")), ); const listAll: ProjectionProjectRepositoryShape["listAll"] = () => listProjectionProjectRows().pipe( - Effect.map((rows) => rows.map(mapProjectionProjectRow)), Effect.mapError(toPersistenceSqlError("ProjectionProjectRepository.listAll:query")), ); diff --git a/apps/server/src/persistence/Layers/ProjectionRepositories.test.ts b/apps/server/src/persistence/Layers/ProjectionRepositories.test.ts index 9b50db76dca7..a2069e62a14c 100644 --- a/apps/server/src/persistence/Layers/ProjectionRepositories.test.ts +++ b/apps/server/src/persistence/Layers/ProjectionRepositories.test.ts @@ -91,7 +91,6 @@ projectionRepositoriesLayer("Projection repositories", (it) => { createdAt: "2026-03-24T00:00:00.000Z", updatedAt: "2026-03-24T00:00:00.000Z", archivedAt: null, - seededWorkItems: [], latestUserMessageAt: null, pendingApprovalCount: 0, pendingUserInputCount: 0, diff --git a/apps/server/src/persistence/Layers/ProjectionThreads.ts b/apps/server/src/persistence/Layers/ProjectionThreads.ts index 9d6bd46ae3b1..1baeb375c152 100644 --- a/apps/server/src/persistence/Layers/ProjectionThreads.ts +++ b/apps/server/src/persistence/Layers/ProjectionThreads.ts @@ -2,10 +2,9 @@ import * as SqlClient from "effect/unstable/sql/SqlClient"; import * as SqlSchema from "effect/unstable/sql/SqlSchema"; import * as Effect from "effect/Effect"; import * as Layer from "effect/Layer"; -import * as Option from "effect/Option"; import * as Schema from "effect/Schema"; +import * as Struct from "effect/Struct"; -import { ManagerSeededWorkItem, ManagerThreadMetadata, ModelSelection } from "@t3tools/contracts"; import { toPersistenceSqlError } from "../Errors.ts"; import { DeleteProjectionThreadInput, @@ -15,54 +14,15 @@ import { ProjectionThreadRepository, type ProjectionThreadRepositoryShape, } from "../Services/ProjectionThreads.ts"; +import { ModelSelection } from "@t3tools/contracts"; -const ProjectionThreadDbRow = Schema.Struct({ - threadId: ProjectionThread.fields.threadId, - projectId: ProjectionThread.fields.projectId, - title: ProjectionThread.fields.title, - managerMetadata: Schema.NullOr(Schema.fromJsonString(ManagerThreadMetadata)), - modelSelection: Schema.fromJsonString(ModelSelection), - runtimeMode: ProjectionThread.fields.runtimeMode, - interactionMode: ProjectionThread.fields.interactionMode, - branch: ProjectionThread.fields.branch, - worktreePath: ProjectionThread.fields.worktreePath, - latestTurnId: ProjectionThread.fields.latestTurnId, - createdAt: ProjectionThread.fields.createdAt, - updatedAt: ProjectionThread.fields.updatedAt, - archivedAt: ProjectionThread.fields.archivedAt, - seededWorkItems: Schema.fromJsonString(Schema.Array(ManagerSeededWorkItem)), - latestUserMessageAt: ProjectionThread.fields.latestUserMessageAt, - pendingApprovalCount: ProjectionThread.fields.pendingApprovalCount, - pendingUserInputCount: ProjectionThread.fields.pendingUserInputCount, - hasActionableProposedPlan: ProjectionThread.fields.hasActionableProposedPlan, - deletedAt: ProjectionThread.fields.deletedAt, -}); +const ProjectionThreadDbRow = ProjectionThread.mapFields( + Struct.assign({ + modelSelection: Schema.fromJsonString(ModelSelection), + }), +); type ProjectionThreadDbRow = typeof ProjectionThreadDbRow.Type; -function mapProjectionThreadRow(row: ProjectionThreadDbRow) { - return { - threadId: row.threadId, - projectId: row.projectId, - title: row.title, - ...(row.managerMetadata !== null ? { managerMetadata: row.managerMetadata } : {}), - modelSelection: row.modelSelection, - runtimeMode: row.runtimeMode, - interactionMode: row.interactionMode, - branch: row.branch, - worktreePath: row.worktreePath, - latestTurnId: row.latestTurnId, - createdAt: row.createdAt, - updatedAt: row.updatedAt, - archivedAt: row.archivedAt, - seededWorkItems: row.seededWorkItems, - latestUserMessageAt: row.latestUserMessageAt, - pendingApprovalCount: row.pendingApprovalCount, - pendingUserInputCount: row.pendingUserInputCount, - hasActionableProposedPlan: row.hasActionableProposedPlan, - deletedAt: row.deletedAt, - }; -} - const makeProjectionThreadRepository = Effect.gen(function* () { const sql = yield* SqlClient.SqlClient; @@ -74,7 +34,6 @@ const makeProjectionThreadRepository = Effect.gen(function* () { thread_id, project_id, title, - manager_metadata_json, model_selection_json, runtime_mode, interaction_mode, @@ -84,7 +43,6 @@ const makeProjectionThreadRepository = Effect.gen(function* () { created_at, updated_at, archived_at, - seeded_work_items_json, latest_user_message_at, pending_approval_count, pending_user_input_count, @@ -95,7 +53,6 @@ const makeProjectionThreadRepository = Effect.gen(function* () { ${row.threadId}, ${row.projectId}, ${row.title}, - ${row.managerMetadata !== undefined ? JSON.stringify(row.managerMetadata) : null}, ${JSON.stringify(row.modelSelection)}, ${row.runtimeMode}, ${row.interactionMode}, @@ -105,7 +62,6 @@ const makeProjectionThreadRepository = Effect.gen(function* () { ${row.createdAt}, ${row.updatedAt}, ${row.archivedAt}, - ${JSON.stringify(row.seededWorkItems)}, ${row.latestUserMessageAt}, ${row.pendingApprovalCount}, ${row.pendingUserInputCount}, @@ -116,7 +72,6 @@ const makeProjectionThreadRepository = Effect.gen(function* () { DO UPDATE SET project_id = excluded.project_id, title = excluded.title, - manager_metadata_json = excluded.manager_metadata_json, model_selection_json = excluded.model_selection_json, runtime_mode = excluded.runtime_mode, interaction_mode = excluded.interaction_mode, @@ -126,7 +81,6 @@ const makeProjectionThreadRepository = Effect.gen(function* () { created_at = excluded.created_at, updated_at = excluded.updated_at, archived_at = excluded.archived_at, - seeded_work_items_json = excluded.seeded_work_items_json, latest_user_message_at = excluded.latest_user_message_at, pending_approval_count = excluded.pending_approval_count, pending_user_input_count = excluded.pending_user_input_count, @@ -144,7 +98,6 @@ const makeProjectionThreadRepository = Effect.gen(function* () { thread_id AS "threadId", project_id AS "projectId", title, - manager_metadata_json AS "managerMetadata", model_selection_json AS "modelSelection", runtime_mode AS "runtimeMode", interaction_mode AS "interactionMode", @@ -154,7 +107,6 @@ const makeProjectionThreadRepository = Effect.gen(function* () { created_at AS "createdAt", updated_at AS "updatedAt", archived_at AS "archivedAt", - seeded_work_items_json AS "seededWorkItems", latest_user_message_at AS "latestUserMessageAt", pending_approval_count AS "pendingApprovalCount", pending_user_input_count AS "pendingUserInputCount", @@ -174,7 +126,6 @@ const makeProjectionThreadRepository = Effect.gen(function* () { thread_id AS "threadId", project_id AS "projectId", title, - manager_metadata_json AS "managerMetadata", model_selection_json AS "modelSelection", runtime_mode AS "runtimeMode", interaction_mode AS "interactionMode", @@ -184,7 +135,6 @@ const makeProjectionThreadRepository = Effect.gen(function* () { created_at AS "createdAt", updated_at AS "updatedAt", archived_at AS "archivedAt", - seeded_work_items_json AS "seededWorkItems", latest_user_message_at AS "latestUserMessageAt", pending_approval_count AS "pendingApprovalCount", pending_user_input_count AS "pendingUserInputCount", @@ -212,13 +162,11 @@ const makeProjectionThreadRepository = Effect.gen(function* () { const getById: ProjectionThreadRepositoryShape["getById"] = (input) => getProjectionThreadRow(input).pipe( - Effect.map(Option.map(mapProjectionThreadRow)), Effect.mapError(toPersistenceSqlError("ProjectionThreadRepository.getById:query")), ); const listByProjectId: ProjectionThreadRepositoryShape["listByProjectId"] = (input) => listProjectionThreadRows(input).pipe( - Effect.map((rows) => rows.map(mapProjectionThreadRow)), Effect.mapError(toPersistenceSqlError("ProjectionThreadRepository.listByProjectId:query")), ); diff --git a/apps/server/src/persistence/Services/ProjectionProjects.ts b/apps/server/src/persistence/Services/ProjectionProjects.ts index a8ea0d529841..5632205a2699 100644 --- a/apps/server/src/persistence/Services/ProjectionProjects.ts +++ b/apps/server/src/persistence/Services/ProjectionProjects.ts @@ -6,13 +6,7 @@ * * @module ProjectionProjectRepository */ -import { - IsoDateTime, - ManagerProjectMetadata, - ModelSelection, - ProjectId, - ProjectScript, -} from "@t3tools/contracts"; +import { IsoDateTime, ModelSelection, ProjectId, ProjectScript } from "@t3tools/contracts"; import * as Option from "effect/Option"; import * as Schema from "effect/Schema"; import * as Context from "effect/Context"; @@ -24,7 +18,6 @@ export const ProjectionProject = Schema.Struct({ projectId: ProjectId, title: Schema.String, workspaceRoot: Schema.String, - managerMetadata: Schema.optional(ManagerProjectMetadata), defaultModelSelection: Schema.NullOr(ModelSelection), scripts: Schema.Array(ProjectScript), createdAt: IsoDateTime, diff --git a/apps/server/src/persistence/Services/ProjectionThreadSessions.ts b/apps/server/src/persistence/Services/ProjectionThreadSessions.ts index d693680cc449..7cecac33eb6a 100644 --- a/apps/server/src/persistence/Services/ProjectionThreadSessions.ts +++ b/apps/server/src/persistence/Services/ProjectionThreadSessions.ts @@ -7,7 +7,6 @@ * @module ProjectionThreadSessionRepository */ import { - DEFAULT_RUNTIME_MODE, RuntimeMode, IsoDateTime, OrchestrationSessionStatus, @@ -15,10 +14,10 @@ import { ThreadId, TurnId, } from "@t3tools/contracts"; -import * as Effect from "effect/Effect"; import * as Option from "effect/Option"; import * as Schema from "effect/Schema"; import * as Context from "effect/Context"; +import type * as Effect from "effect/Effect"; import type { ProjectionRepositoryError } from "../Errors.ts"; @@ -27,7 +26,7 @@ export const ProjectionThreadSession = Schema.Struct({ status: OrchestrationSessionStatus, providerName: Schema.NullOr(Schema.String), providerInstanceId: Schema.NullOr(ProviderInstanceId), - runtimeMode: RuntimeMode.pipe(Schema.withDecodingDefault(Effect.succeed(DEFAULT_RUNTIME_MODE))), + runtimeMode: RuntimeMode, activeTurnId: Schema.NullOr(TurnId), lastError: Schema.NullOr(Schema.String), updatedAt: IsoDateTime, diff --git a/apps/server/src/persistence/Services/ProjectionThreads.ts b/apps/server/src/persistence/Services/ProjectionThreads.ts index 1997cd575c6a..44fdc147a4a2 100644 --- a/apps/server/src/persistence/Services/ProjectionThreads.ts +++ b/apps/server/src/persistence/Services/ProjectionThreads.ts @@ -7,10 +7,7 @@ * @module ProjectionThreadRepository */ import { - DEFAULT_RUNTIME_MODE, IsoDateTime, - ManagerSeededWorkItem, - ManagerThreadMetadata, ModelSelection, NonNegativeInt, ProjectId, @@ -22,7 +19,7 @@ import { import * as Option from "effect/Option"; import * as Schema from "effect/Schema"; import * as Context from "effect/Context"; -import * as Effect from "effect/Effect"; +import type * as Effect from "effect/Effect"; import type { ProjectionRepositoryError } from "../Errors.ts"; @@ -30,9 +27,8 @@ export const ProjectionThread = Schema.Struct({ threadId: ThreadId, projectId: ProjectId, title: Schema.String, - managerMetadata: Schema.optional(ManagerThreadMetadata), modelSelection: ModelSelection, - runtimeMode: RuntimeMode.pipe(Schema.withDecodingDefault(Effect.succeed(DEFAULT_RUNTIME_MODE))), + runtimeMode: RuntimeMode, interactionMode: ProviderInteractionMode, branch: Schema.NullOr(Schema.String), worktreePath: Schema.NullOr(Schema.String), @@ -40,9 +36,6 @@ export const ProjectionThread = Schema.Struct({ createdAt: IsoDateTime, updatedAt: IsoDateTime, archivedAt: Schema.NullOr(IsoDateTime), - seededWorkItems: Schema.Array(ManagerSeededWorkItem).pipe( - Schema.withDecodingDefault(Effect.succeed([])), - ), latestUserMessageAt: Schema.NullOr(IsoDateTime), pendingApprovalCount: NonNegativeInt, pendingUserInputCount: NonNegativeInt, diff --git a/apps/server/src/persistence/Services/ProviderSessionRuntime.ts b/apps/server/src/persistence/Services/ProviderSessionRuntime.ts index d4f31646ad7c..125f4fa5bbf2 100644 --- a/apps/server/src/persistence/Services/ProviderSessionRuntime.ts +++ b/apps/server/src/persistence/Services/ProviderSessionRuntime.ts @@ -6,7 +6,6 @@ * @module ProviderSessionRuntimeRepository */ import { - DEFAULT_RUNTIME_MODE, IsoDateTime, ProviderInstanceId, ProviderSessionRuntimeStatus, @@ -16,7 +15,7 @@ import { import * as Option from "effect/Option"; import * as Schema from "effect/Schema"; import * as Context from "effect/Context"; -import * as Effect from "effect/Effect"; +import type * as Effect from "effect/Effect"; import type { ProviderSessionRuntimeRepositoryError } from "../Errors.ts"; @@ -32,7 +31,7 @@ export const ProviderSessionRuntime = Schema.Struct({ */ providerInstanceId: Schema.NullOr(ProviderInstanceId), adapterKey: Schema.String, - runtimeMode: RuntimeMode.pipe(Schema.withDecodingDefault(Effect.succeed(DEFAULT_RUNTIME_MODE))), + runtimeMode: RuntimeMode, status: ProviderSessionRuntimeStatus, lastSeenAt: IsoDateTime, resumeCursor: Schema.NullOr(Schema.Unknown), diff --git a/apps/server/src/provider/Drivers/GrokDriver.ts b/apps/server/src/provider/Drivers/GrokDriver.ts new file mode 100644 index 000000000000..ab01439ffd39 --- /dev/null +++ b/apps/server/src/provider/Drivers/GrokDriver.ts @@ -0,0 +1,153 @@ +import { GrokSettings, ProviderDriverKind, type ServerProvider } from "@t3tools/contracts"; +import * as Duration from "effect/Duration"; +import * as Crypto from "effect/Crypto"; +import * as Effect from "effect/Effect"; +import * as FileSystem from "effect/FileSystem"; +import * as Path from "effect/Path"; +import * as Schema from "effect/Schema"; +import * as Stream from "effect/Stream"; +import { HttpClient } from "effect/unstable/http"; +import { ChildProcessSpawner } from "effect/unstable/process"; + +import { ServerConfig } from "../../config.ts"; +import { makeGrokTextGeneration } from "../../textGeneration/GrokTextGeneration.ts"; +import { ProviderDriverError } from "../Errors.ts"; +import { makeGrokAdapter } from "../Layers/GrokAdapter.ts"; +import { + buildInitialGrokProviderSnapshot, + checkGrokProviderStatus, + enrichGrokSnapshot, +} from "../Layers/GrokProvider.ts"; +import { ProviderEventLoggers } from "../Layers/ProviderEventLoggers.ts"; +import { makeManagedServerProvider } from "../makeManagedServerProvider.ts"; +import { + defaultProviderContinuationIdentity, + type ProviderDriver, + type ProviderInstance, +} from "../ProviderDriver.ts"; +import type { ServerProviderDraft } from "../providerSnapshot.ts"; +import { mergeProviderInstanceEnvironment } from "../ProviderInstanceEnvironment.ts"; +import { + makeManualOnlyProviderMaintenanceCapabilities, + makeStaticProviderMaintenanceResolver, + resolveProviderMaintenanceCapabilitiesEffect, +} from "../providerMaintenance.ts"; +const decodeGrokSettings = Schema.decodeSync(GrokSettings); + +const DRIVER_KIND = ProviderDriverKind.make("grok"); +const SNAPSHOT_REFRESH_INTERVAL = Duration.minutes(5); +const UPDATE = makeStaticProviderMaintenanceResolver( + makeManualOnlyProviderMaintenanceCapabilities({ + provider: DRIVER_KIND, + packageName: null, + }), +); + +export type GrokDriverEnv = + | ChildProcessSpawner.ChildProcessSpawner + | Crypto.Crypto + | FileSystem.FileSystem + | HttpClient.HttpClient + | Path.Path + | ProviderEventLoggers + | ServerConfig; + +const withInstanceIdentity = + (input: { + readonly instanceId: ProviderInstance["instanceId"]; + readonly displayName: string | undefined; + readonly accentColor: string | undefined; + readonly continuationGroupKey: string; + }) => + (snapshot: ServerProviderDraft): ServerProvider => ({ + ...snapshot, + instanceId: input.instanceId, + driver: DRIVER_KIND, + ...(input.displayName ? { displayName: input.displayName } : {}), + ...(input.accentColor ? { accentColor: input.accentColor } : {}), + continuation: { groupKey: input.continuationGroupKey }, + }); + +export const GrokDriver: ProviderDriver = { + driverKind: DRIVER_KIND, + metadata: { + displayName: "Grok", + supportsMultipleInstances: true, + }, + configSchema: GrokSettings, + defaultConfig: (): GrokSettings => decodeGrokSettings({}), + create: ({ instanceId, displayName, accentColor, environment, enabled, config }) => + Effect.gen(function* () { + const spawner = yield* ChildProcessSpawner.ChildProcessSpawner; + const httpClient = yield* HttpClient.HttpClient; + const eventLoggers = yield* ProviderEventLoggers; + const processEnv = mergeProviderInstanceEnvironment(environment); + const continuationIdentity = defaultProviderContinuationIdentity({ + driverKind: DRIVER_KIND, + instanceId, + }); + const stampIdentity = withInstanceIdentity({ + instanceId, + displayName, + accentColor, + continuationGroupKey: continuationIdentity.continuationKey, + }); + const effectiveConfig = { ...config, enabled } satisfies GrokSettings; + const maintenanceCapabilities = yield* resolveProviderMaintenanceCapabilitiesEffect(UPDATE, { + binaryPath: effectiveConfig.binaryPath, + env: processEnv, + }); + + const adapter = yield* makeGrokAdapter(effectiveConfig, { + environment: processEnv, + ...(eventLoggers.native ? { nativeEventLogger: eventLoggers.native } : {}), + instanceId, + }); + const textGeneration = yield* makeGrokTextGeneration(effectiveConfig, processEnv); + + const checkProvider = checkGrokProviderStatus(effectiveConfig, processEnv).pipe( + Effect.map(stampIdentity), + Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, spawner), + ); + + const snapshot = yield* makeManagedServerProvider({ + maintenanceCapabilities, + getSettings: Effect.succeed(effectiveConfig), + streamSettings: Stream.never, + haveSettingsChanged: () => false, + initialSnapshot: (settings) => + buildInitialGrokProviderSnapshot(settings).pipe(Effect.map(stampIdentity)), + checkProvider, + enrichSnapshot: ({ snapshot: currentSnapshot, publishSnapshot }) => + enrichGrokSnapshot({ + snapshot: currentSnapshot, + maintenanceCapabilities, + publishSnapshot, + httpClient, + }), + refreshInterval: SNAPSHOT_REFRESH_INTERVAL, + }).pipe( + Effect.mapError( + (cause) => + new ProviderDriverError({ + driver: DRIVER_KIND, + instanceId, + detail: `Failed to build Grok snapshot: ${cause.message ?? String(cause)}`, + cause, + }), + ), + ); + + return { + instanceId, + driverKind: DRIVER_KIND, + continuationIdentity, + displayName, + accentColor, + enabled, + snapshot, + adapter, + textGeneration, + } satisfies ProviderInstance; + }), +}; diff --git a/apps/server/src/provider/Layers/ClaudeAdapter.test.ts b/apps/server/src/provider/Layers/ClaudeAdapter.test.ts index b1f871595a4c..6e272fdb70b9 100644 --- a/apps/server/src/provider/Layers/ClaudeAdapter.test.ts +++ b/apps/server/src/provider/Layers/ClaudeAdapter.test.ts @@ -633,6 +633,29 @@ describe("ClaudeAdapterLive", () => { ); }); + it.effect("preserves xhigh effort for Claude Fable 5", () => { + const harness = makeHarness(); + return Effect.gen(function* () { + const adapter = yield* ClaudeAdapter; + yield* adapter.startSession({ + threadId: THREAD_ID, + provider: ProviderDriverKind.make("claudeAgent"), + modelSelection: createModelSelection( + ProviderInstanceId.make("claudeAgent"), + "claude-fable-5", + [{ id: "effort", value: "xhigh" }], + ), + runtimeMode: "full-access", + }); + + const createInput = harness.getLastCreateQueryInput(); + assert.equal(createInput?.options.effort, "xhigh"); + }).pipe( + Effect.provideService(Random.Random, makeDeterministicRandomService()), + Effect.provide(harness.layer), + ); + }); + it.effect("falls back to default effort when unsupported max is requested for Sonnet 4.6", () => { const harness = makeHarness(); return Effect.gen(function* () { diff --git a/apps/server/src/provider/Layers/ClaudeAdapter.ts b/apps/server/src/provider/Layers/ClaudeAdapter.ts index 6e902b0f4e68..abbb1f0ab585 100644 --- a/apps/server/src/provider/Layers/ClaudeAdapter.ts +++ b/apps/server/src/provider/Layers/ClaudeAdapter.ts @@ -72,8 +72,8 @@ import { ServerSettingsService } from "../../serverSettings.ts"; import { makeClaudeEnvironment } from "../Drivers/ClaudeHome.ts"; import { getClaudeModelCapabilities, - type McpServerSnapshot, isClaudeUltracodeEffort, + type McpServerSnapshot, normalizeClaudeCliEffort, resolveClaudeApiModelId, resolveClaudeEffort, @@ -1057,9 +1057,9 @@ export const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* ( const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; const serverConfig = yield* ServerConfig; + const crypto = yield* Crypto.Crypto; const settingsService = yield* ServerSettingsService; const threadMcpToggleRepository = yield* ThreadMcpToggleRepository; - const crypto = yield* Crypto.Crypto; const claudeEnvironment = yield* makeClaudeEnvironment(claudeSettings, options?.environment).pipe( Effect.provideService(Path.Path, path), ); diff --git a/apps/server/src/provider/Layers/ClaudeProvider.ts b/apps/server/src/provider/Layers/ClaudeProvider.ts index 6f71e3648b9a..487003daa62f 100644 --- a/apps/server/src/provider/Layers/ClaudeProvider.ts +++ b/apps/server/src/provider/Layers/ClaudeProvider.ts @@ -48,50 +48,42 @@ const CLAUDE_PRESENTATION = { displayName: "Claude", showInteractionModeToggle: true, } as const; +const MINIMUM_CLAUDE_FABLE_5_VERSION = "2.1.169"; const MINIMUM_CLAUDE_OPUS_4_8_VERSION = "2.1.154"; const MINIMUM_CLAUDE_OPUS_4_7_VERSION = "2.1.111"; -const CLAUDE_EFFORT_OPTIONS = { - opus48: [ - { value: "low", label: "Low" }, - { value: "medium", label: "Medium" }, - { value: "high", label: "High", isDefault: true }, - { value: "xhigh", label: "Extra High" }, - { value: "max", label: "Max" }, - { value: "ultracode", label: "Ultracode" }, - { value: "ultrathink", label: "Ultrathink" }, - ], - opus47: [ - { value: "low", label: "Low" }, - { value: "medium", label: "Medium" }, - { value: "high", label: "High" }, - { value: "xhigh", label: "Extra High", isDefault: true }, - { value: "max", label: "Max" }, - { value: "ultrathink", label: "Ultrathink" }, - ], - opus46: [ - { value: "low", label: "Low" }, - { value: "medium", label: "Medium" }, - { value: "high", label: "High", isDefault: true }, - { value: "max", label: "Max" }, - { value: "ultrathink", label: "Ultrathink" }, - ], - sonnet46: [ - { value: "low", label: "Low" }, - { value: "medium", label: "Medium" }, - { value: "high", label: "High", isDefault: true }, - { value: "max", label: "Max" }, - { value: "ultrathink", label: "Ultrathink" }, - ], - opus45: [ - { value: "low", label: "Low" }, - { value: "medium", label: "Medium" }, - { value: "high", label: "High", isDefault: true }, - { value: "max", label: "Max" }, - ], -} as const; - const BUILT_IN_MODELS: ReadonlyArray = [ + { + slug: "claude-fable-5", + name: "Claude Fable 5", + isCustom: false, + capabilities: createModelCapabilities({ + optionDescriptors: [ + buildSelectOptionDescriptor({ + id: "effort", + label: "Reasoning", + options: [ + { value: "low", label: "Low" }, + { value: "medium", label: "Medium" }, + { value: "high", label: "High", isDefault: true }, + { value: "xhigh", label: "Extra High" }, + { value: "max", label: "Max" }, + { value: "ultracode", label: "Ultracode" }, + { value: "ultrathink", label: "Ultrathink" }, + ], + promptInjectedValues: ["ultrathink"], + }), + buildSelectOptionDescriptor({ + id: "contextWindow", + label: "Context Window", + options: [ + { value: "200k", label: "200k", isDefault: true }, + { value: "1m", label: "1M" }, + ], + }), + ], + }), + }, { slug: "claude-opus-4-8", name: "Claude Opus 4.8", @@ -101,9 +93,21 @@ const BUILT_IN_MODELS: ReadonlyArray = [ buildSelectOptionDescriptor({ id: "effort", label: "Reasoning", - options: CLAUDE_EFFORT_OPTIONS.opus48, + options: [ + { value: "low", label: "Low" }, + { value: "medium", label: "Medium" }, + { value: "high", label: "High", isDefault: true }, + { value: "xhigh", label: "Extra High" }, + { value: "max", label: "Max" }, + { value: "ultracode", label: "Ultracode" }, + { value: "ultrathink", label: "Ultrathink" }, + ], promptInjectedValues: ["ultrathink"], }), + buildBooleanOptionDescriptor({ + id: "fastMode", + label: "Fast Mode", + }), buildSelectOptionDescriptor({ id: "contextWindow", label: "Context Window", @@ -124,9 +128,20 @@ const BUILT_IN_MODELS: ReadonlyArray = [ buildSelectOptionDescriptor({ id: "effort", label: "Reasoning", - options: CLAUDE_EFFORT_OPTIONS.opus47, + options: [ + { value: "low", label: "Low" }, + { value: "medium", label: "Medium" }, + { value: "high", label: "High" }, + { value: "xhigh", label: "Extra High", isDefault: true }, + { value: "max", label: "Max" }, + { value: "ultrathink", label: "Ultrathink" }, + ], promptInjectedValues: ["ultrathink"], }), + buildBooleanOptionDescriptor({ + id: "fastMode", + label: "Fast Mode", + }), buildSelectOptionDescriptor({ id: "contextWindow", label: "Context Window", @@ -147,7 +162,13 @@ const BUILT_IN_MODELS: ReadonlyArray = [ buildSelectOptionDescriptor({ id: "effort", label: "Reasoning", - options: CLAUDE_EFFORT_OPTIONS.opus46, + options: [ + { value: "low", label: "Low" }, + { value: "medium", label: "Medium" }, + { value: "high", label: "High", isDefault: true }, + { value: "max", label: "Max" }, + { value: "ultrathink", label: "Ultrathink" }, + ], promptInjectedValues: ["ultrathink"], }), buildBooleanOptionDescriptor({ @@ -174,7 +195,12 @@ const BUILT_IN_MODELS: ReadonlyArray = [ buildSelectOptionDescriptor({ id: "effort", label: "Reasoning", - options: CLAUDE_EFFORT_OPTIONS.opus45, + options: [ + { value: "low", label: "Low" }, + { value: "medium", label: "Medium" }, + { value: "high", label: "High", isDefault: true }, + { value: "max", label: "Max" }, + ], }), buildBooleanOptionDescriptor({ id: "fastMode", @@ -192,7 +218,13 @@ const BUILT_IN_MODELS: ReadonlyArray = [ buildSelectOptionDescriptor({ id: "effort", label: "Reasoning", - options: CLAUDE_EFFORT_OPTIONS.sonnet46, + options: [ + { value: "low", label: "Low" }, + { value: "medium", label: "Medium" }, + { value: "high", label: "High", isDefault: true }, + { value: "max", label: "Max" }, + { value: "ultrathink", label: "Ultrathink" }, + ], promptInjectedValues: ["ultrathink"], }), buildSelectOptionDescriptor({ @@ -221,6 +253,10 @@ const BUILT_IN_MODELS: ReadonlyArray = [ }, ]; +function supportsClaudeFable5(version: string | null | undefined): boolean { + return version ? compareSemverVersions(version, MINIMUM_CLAUDE_FABLE_5_VERSION) >= 0 : false; +} + function supportsClaudeOpus48(version: string | null | undefined): boolean { return version ? compareSemverVersions(version, MINIMUM_CLAUDE_OPUS_4_8_VERSION) >= 0 : false; } @@ -233,6 +269,9 @@ function getBuiltInClaudeModelsForVersion( version: string | null | undefined, ): ReadonlyArray { return BUILT_IN_MODELS.filter((model) => { + if (model.slug === "claude-fable-5") { + return supportsClaudeFable5(version); + } if (model.slug === "claude-opus-4-8") { return supportsClaudeOpus48(version); } @@ -243,6 +282,11 @@ function getBuiltInClaudeModelsForVersion( }); } +function formatClaudeFable5UpgradeMessage(version: string | null): string { + const versionLabel = version ? `v${version}` : "the installed version"; + return `Claude Code ${versionLabel} is too old for Claude Fable 5. Upgrade to v${MINIMUM_CLAUDE_FABLE_5_VERSION} or newer to access it.`; +} + function formatClaudeOpus48UpgradeMessage(version: string | null): string { const versionLabel = version ? `v${version}` : "the installed version"; return `Claude Code ${versionLabel} is too old for Claude Opus 4.8. Upgrade to v${MINIMUM_CLAUDE_OPUS_4_8_VERSION} or newer to access it.`; @@ -294,7 +338,7 @@ export function normalizeClaudeCliEffort( if (effort === "ultracode") { return "xhigh"; } - if (effort === "xhigh" && model !== "claude-opus-4-8") { + if (effort === "xhigh" && model !== "claude-fable-5" && model !== "claude-opus-4-8") { return "max"; } if (effort === "max" && model === "claude-sonnet-4-6") { @@ -735,11 +779,13 @@ export const checkClaudeProviderStatus = Effect.fn("checkClaudeProviderStatus")( claudeSettings.customModels, DEFAULT_CLAUDE_MODEL_CAPABILITIES, ); - const versionUpgradeMessage = supportsClaudeOpus48(parsedVersion) + const versionUpgradeMessage = supportsClaudeFable5(parsedVersion) ? undefined - : supportsClaudeOpus47(parsedVersion) - ? formatClaudeOpus48UpgradeMessage(parsedVersion) - : formatClaudeOpus47UpgradeMessage(parsedVersion); + : supportsClaudeOpus48(parsedVersion) + ? formatClaudeFable5UpgradeMessage(parsedVersion) + : supportsClaudeOpus47(parsedVersion) + ? formatClaudeOpus48UpgradeMessage(parsedVersion) + : formatClaudeOpus47UpgradeMessage(parsedVersion); const capabilities = resolveCapabilities ? yield* resolveCapabilities(claudeSettings).pipe(Effect.orElseSucceed(() => undefined)) diff --git a/apps/server/src/provider/Layers/GrokAdapter.test.ts b/apps/server/src/provider/Layers/GrokAdapter.test.ts new file mode 100644 index 000000000000..bfd5ae25755d --- /dev/null +++ b/apps/server/src/provider/Layers/GrokAdapter.test.ts @@ -0,0 +1,377 @@ +// @effect-diagnostics nodeBuiltinImport:off +import * as path from "node:path"; +import * as os from "node:os"; +import { chmod, mkdtemp, readFile, writeFile } from "node:fs/promises"; +import { fileURLToPath } from "node:url"; + +import * as NodeServices from "@effect/platform-node/NodeServices"; +import { assert, it } from "@effect/vitest"; +import * as Deferred from "effect/Deferred"; +import * as Effect from "effect/Effect"; +import * as Fiber from "effect/Fiber"; +import * as Layer from "effect/Layer"; +import * as Schema from "effect/Schema"; +import * as Stream from "effect/Stream"; + +import { + ApprovalRequestId, + GrokSettings, + ProviderDriverKind, + ThreadId, + ProviderInstanceId, + type ProviderRuntimeEvent, +} from "@t3tools/contracts"; + +import { ServerConfig } from "../../config.ts"; +import { makeGrokAdapter } from "./GrokAdapter.ts"; +const decodeGrokSettings = Schema.decodeSync(GrokSettings); + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const mockAgentPath = path.join(__dirname, "../../../scripts/acp-mock-agent.ts"); +const mockAgentCommand = process.execPath; + +async function makeMockGrokWrapper(extraEnv?: Record) { + const dir = await mkdtemp(path.join(os.tmpdir(), "grok-acp-mock-")); + const wrapperPath = path.join(dir, "fake-grok.sh"); + const envExports = Object.entries(extraEnv ?? {}) + .map(([key, value]) => `export ${key}=${JSON.stringify(value)}`) + .join("\n"); + const script = `#!/bin/sh +${envExports} +exec ${JSON.stringify(mockAgentCommand)} ${JSON.stringify(mockAgentPath)} "$@" +`; + await writeFile(wrapperPath, script, "utf8"); + await chmod(wrapperPath, 0o755); + return wrapperPath; +} + +function waitForFileContent(filePath: string, attempts = 40): Effect.Effect { + const readAttempt = (remainingAttempts: number): Effect.Effect => + Effect.gen(function* () { + if (remainingAttempts <= 0) { + return yield* Effect.die(new Error(`Timed out waiting for file content at ${filePath}`)); + } + const raw = yield* Effect.tryPromise(() => readFile(filePath, "utf8")).pipe( + Effect.orElseSucceed(() => ""), + ); + if (raw.trim().length > 0) { + return raw; + } + yield* Effect.sleep("25 millis"); + return yield* readAttempt(remainingAttempts - 1); + }); + return readAttempt(attempts); +} + +async function readJsonLines(filePath: string) { + const raw = await readFile(filePath, "utf8"); + return raw + .split("\n") + .map((line) => line.trim()) + .filter((line) => line.length > 0) + .map((line) => JSON.parse(line) as Record); +} + +const grokAdapterTestLayer = ServerConfig.layerTest(process.cwd(), { + prefix: "t3code-grok-adapter-test-", +}).pipe(Layer.provideMerge(NodeServices.layer)); + +const makeTestAdapter = (binaryPath: string, options?: Parameters[1]) => + makeGrokAdapter(decodeGrokSettings({ binaryPath }), options).pipe(Effect.orDie); + +it.layer(grokAdapterTestLayer)("GrokAdapterLive", (it) => { + it.effect("starts a session and maps mock ACP prompt flow to runtime events", () => + Effect.gen(function* () { + const threadId = ThreadId.make("grok-mock-thread"); + const wrapperPath = yield* Effect.promise(() => makeMockGrokWrapper()); + const adapter = yield* makeTestAdapter(wrapperPath); + + const runtimeEvents: ProviderRuntimeEvent[] = []; + const turnCompleted = yield* Deferred.make(); + const runtimeEventsFiber = yield* Stream.runForEach(adapter.streamEvents, (event) => + Effect.sync(() => { + runtimeEvents.push(event); + }).pipe( + Effect.andThen( + event.type === "turn.completed" + ? Deferred.succeed(turnCompleted, undefined) + : Effect.void, + ), + ), + ).pipe(Effect.forkChild); + + const session = yield* adapter.startSession({ + threadId, + provider: ProviderDriverKind.make("grok"), + cwd: process.cwd(), + runtimeMode: "full-access", + modelSelection: { instanceId: ProviderInstanceId.make("grok"), model: "grok-mock-alt" }, + }); + + assert.equal(session.provider, "grok"); + assert.equal(session.model, "grok-mock-alt"); + assert.deepStrictEqual(session.resumeCursor, { + schemaVersion: 1, + sessionId: "mock-session-1", + }); + + yield* adapter.sendTurn({ + threadId, + input: "hello grok", + attachments: [], + }); + + yield* Deferred.await(turnCompleted); + yield* Fiber.interrupt(runtimeEventsFiber); + const types = runtimeEvents.map((e) => e.type); + + assert.includeMembers(types, [ + "session.started", + "session.state.changed", + "thread.started", + "turn.started", + "item.started", + "content.delta", + "turn.completed", + ] as const); + + const delta = runtimeEvents.find((e) => e.type === "content.delta"); + assert.isDefined(delta); + if (delta?.type === "content.delta") { + assert.equal(delta.payload.delta, "hello from mock"); + } + + yield* adapter.stopSession(threadId); + }), + ); + + it.effect("closes the ACP child process when a session stops", () => + Effect.gen(function* () { + const threadId = ThreadId.make("grok-stop-session-close"); + const tempDir = yield* Effect.promise(() => + mkdtemp(path.join(os.tmpdir(), "grok-adapter-exit-log-")), + ); + const exitLogPath = path.join(tempDir, "exit.log"); + + const wrapperPath = yield* Effect.promise(() => + makeMockGrokWrapper({ + T3_ACP_EXIT_LOG_PATH: exitLogPath, + }), + ); + const adapter = yield* makeTestAdapter(wrapperPath); + + yield* adapter.startSession({ + threadId, + provider: ProviderDriverKind.make("grok"), + cwd: process.cwd(), + runtimeMode: "full-access", + modelSelection: { instanceId: ProviderInstanceId.make("grok"), model: "grok-build" }, + }); + + yield* adapter.stopSession(threadId); + + const exitLog = yield* waitForFileContent(exitLogPath); + assert.include(exitLog, "SIGTERM"); + }), + ); + + it.effect("rejects startSession when provider mismatches", () => + Effect.gen(function* () { + const wrapperPath = yield* Effect.promise(() => makeMockGrokWrapper()); + const adapter = yield* makeTestAdapter(wrapperPath); + const threadId = ThreadId.make("grok-provider-mismatch"); + + const error = yield* Effect.flip( + adapter.startSession({ + threadId, + provider: ProviderDriverKind.make("cursor"), + cwd: process.cwd(), + runtimeMode: "full-access", + modelSelection: { instanceId: ProviderInstanceId.make("grok"), model: "grok-build" }, + }), + ); + + assert.equal(error._tag, "ProviderAdapterValidationError"); + }), + ); + + it.effect("rejects sendTurn with empty input and no attachments", () => + Effect.gen(function* () { + const threadId = ThreadId.make("grok-empty-turn"); + + const wrapperPath = yield* Effect.promise(() => makeMockGrokWrapper()); + const adapter = yield* makeTestAdapter(wrapperPath); + + yield* adapter.startSession({ + threadId, + provider: ProviderDriverKind.make("grok"), + cwd: process.cwd(), + runtimeMode: "full-access", + modelSelection: { instanceId: ProviderInstanceId.make("grok"), model: "grok-build" }, + }); + + const error = yield* Effect.flip( + adapter.sendTurn({ + threadId, + input: " ", + attachments: [], + }), + ); + + assert.equal(error._tag, "ProviderAdapterValidationError"); + + yield* adapter.stopSession(threadId); + }), + ); + + it.effect("responds to ACP approvals using provider-supplied option ids", () => + Effect.gen(function* () { + const threadId = ThreadId.make("grok-custom-approval-option-id"); + const tempDir = yield* Effect.promise(() => mkdtemp(path.join(os.tmpdir(), "grok-acp-"))); + const requestLogPath = path.join(tempDir, "requests.ndjson"); + const wrapperPath = yield* Effect.promise(() => + makeMockGrokWrapper({ + T3_ACP_REQUEST_LOG_PATH: requestLogPath, + T3_ACP_EMIT_TOOL_CALLS: "1", + T3_ACP_ALLOW_ONCE_OPTION_ID: "agent-defined-approval-id", + }), + ); + const adapter = yield* makeTestAdapter(wrapperPath); + const eventsFiber = yield* Stream.runForEach(adapter.streamEvents, (event) => + event.type === "request.opened" + ? adapter.respondToRequest( + threadId, + ApprovalRequestId.make(String(event.requestId)), + "accept", + ) + : Effect.void, + ).pipe(Effect.forkChild); + + yield* adapter.startSession({ + threadId, + provider: ProviderDriverKind.make("grok"), + cwd: process.cwd(), + runtimeMode: "approval-required", + }); + yield* adapter.sendTurn({ threadId, input: "approve this", attachments: [] }); + + const requests = yield* Effect.promise(() => readJsonLines(requestLogPath)); + assert.isTrue( + requests.some( + (entry) => + !("method" in entry) && + typeof entry.result === "object" && + entry.result !== null && + "outcome" in entry.result && + typeof entry.result.outcome === "object" && + entry.result.outcome !== null && + "optionId" in entry.result.outcome && + entry.result.outcome.optionId === "agent-defined-approval-id", + ), + ); + + yield* Fiber.interrupt(eventsFiber); + yield* adapter.stopSession(threadId); + }), + ); + + it.effect("handles xAI ask_user_question extension requests", () => + Effect.gen(function* () { + const threadId = ThreadId.make("grok-xai-ask-user-question"); + const wrapperPath = yield* Effect.promise(() => + makeMockGrokWrapper({ T3_ACP_EMIT_XAI_ASK_USER_QUESTION: "1" }), + ); + const adapter = yield* makeTestAdapter(wrapperPath); + const requested = + yield* Deferred.make>(); + const resolved = + yield* Deferred.make>(); + + const eventsFiber = yield* Stream.runForEach(adapter.streamEvents, (event) => { + if (String(event.threadId) !== String(threadId)) { + return Effect.void; + } + if (event.type === "user-input.requested") { + return Deferred.succeed(requested, event).pipe(Effect.ignore); + } + if (event.type === "user-input.resolved") { + return Deferred.succeed(resolved, event).pipe(Effect.ignore); + } + return Effect.void; + }).pipe(Effect.forkChild); + + yield* adapter.startSession({ + threadId, + provider: ProviderDriverKind.make("grok"), + cwd: process.cwd(), + runtimeMode: "full-access", + }); + + const sendTurnFiber = yield* adapter + .sendTurn({ threadId, input: "ask before continuing", attachments: [] }) + .pipe(Effect.forkChild); + + const requestedEvent = yield* Deferred.await(requested); + assert.equal(requestedEvent.payload.questions.length, 1); + assert.equal(requestedEvent.payload.questions[0]?.id, "Which scope should Grok use?"); + assert.equal(requestedEvent.payload.questions[0]?.question, "Which scope should Grok use?"); + assert.equal(requestedEvent.raw?.method, "_x.ai/ask_user_question"); + + yield* adapter.respondToUserInput( + threadId, + ApprovalRequestId.make(String(requestedEvent.requestId)), + { + "Which scope should Grok use?": "Workspace", + }, + ); + + const resolvedEvent = yield* Deferred.await(resolved); + assert.deepEqual(resolvedEvent.payload.answers, { + "Which scope should Grok use?": "Workspace", + }); + yield* Fiber.join(sendTurnFiber); + + yield* Fiber.interrupt(eventsFiber); + yield* adapter.stopSession(threadId); + }), + ); + + it.effect("continues streaming events when native notification logging fails", () => + Effect.gen(function* () { + const threadId = ThreadId.make("grok-native-log-failure"); + const wrapperPath = yield* Effect.promise(() => makeMockGrokWrapper()); + const adapter = yield* makeTestAdapter(wrapperPath, { + nativeEventLogger: { + filePath: "memory://grok-native-events", + write: (record: unknown) => + typeof record === "object" && + record !== null && + "event" in record && + typeof record.event === "object" && + record.event !== null && + "kind" in record.event && + record.event.kind === "notification" + ? Effect.die(new Error("native log write failed")) + : Effect.void, + close: () => Effect.void, + }, + }); + const contentDelta = yield* Deferred.make(); + const eventsFiber = yield* Stream.runForEach(adapter.streamEvents, (event) => + event.type === "content.delta" ? Deferred.succeed(contentDelta, undefined) : Effect.void, + ).pipe(Effect.forkChild); + + yield* adapter.startSession({ + threadId, + provider: ProviderDriverKind.make("grok"), + cwd: process.cwd(), + runtimeMode: "full-access", + }); + yield* adapter.sendTurn({ threadId, input: "keep streaming", attachments: [] }); + yield* Deferred.await(contentDelta); + + yield* Fiber.interrupt(eventsFiber); + yield* adapter.stopSession(threadId); + }), + ); +}); diff --git a/apps/server/src/provider/Layers/GrokAdapter.ts b/apps/server/src/provider/Layers/GrokAdapter.ts new file mode 100644 index 000000000000..3e18b724f181 --- /dev/null +++ b/apps/server/src/provider/Layers/GrokAdapter.ts @@ -0,0 +1,944 @@ +import { + ApprovalRequestId, + type GrokSettings, + EventId, + type ProviderApprovalDecision, + type ProviderRuntimeEvent, + type ProviderSession, + type ProviderUserInputAnswers, + ProviderDriverKind, + ProviderInstanceId, + RuntimeRequestId, + type ThreadId, + TurnId, +} from "@t3tools/contracts"; +import * as Crypto from "effect/Crypto"; +import * as DateTime from "effect/DateTime"; +import * as Deferred from "effect/Deferred"; +import * as Effect from "effect/Effect"; +import * as Exit from "effect/Exit"; +import * as Fiber from "effect/Fiber"; +import * as FileSystem from "effect/FileSystem"; +import * as Option from "effect/Option"; +import * as Path from "effect/Path"; +import * as PubSub from "effect/PubSub"; +import * as Schema from "effect/Schema"; +import * as Scope from "effect/Scope"; +import * as Semaphore from "effect/Semaphore"; +import * as Stream from "effect/Stream"; +import * as SynchronizedRef from "effect/SynchronizedRef"; +import { ChildProcessSpawner } from "effect/unstable/process"; +import * as EffectAcpErrors from "effect-acp/errors"; +import type * as EffectAcpSchema from "effect-acp/schema"; + +import { resolveAttachmentPath } from "../../attachmentStore.ts"; +import { ServerConfig } from "../../config.ts"; +import { + ProviderAdapterProcessError, + ProviderAdapterRequestError, + ProviderAdapterSessionNotFoundError, + ProviderAdapterValidationError, +} from "../Errors.ts"; +import { mapAcpToAdapterError } from "../acp/AcpAdapterSupport.ts"; +import { type AcpSessionRuntimeShape } from "../acp/AcpSessionRuntime.ts"; +import { + makeAcpAssistantItemEvent, + makeAcpContentDeltaEvent, + makeAcpPlanUpdatedEvent, + makeAcpRequestOpenedEvent, + makeAcpRequestResolvedEvent, + makeAcpToolCallEvent, +} from "../acp/AcpCoreRuntimeEvents.ts"; +import { parsePermissionRequest } from "../acp/AcpRuntimeModel.ts"; +import { makeAcpNativeLoggerFactory } from "../acp/AcpNativeLogging.ts"; +import { + applyGrokAcpModelSelection, + currentGrokModelIdFromSessionSetup, + makeGrokAcpRuntime, + resolveGrokAcpBaseModelId, +} from "../acp/GrokAcpSupport.ts"; +import { + extractXAiAskUserQuestions, + makeXAiAskUserQuestionCancelledResponse, + makeXAiAskUserQuestionResponse, + XAiAskUserQuestionRequest, +} from "../acp/XAiAcpExtension.ts"; +import { type GrokAdapterShape } from "../Services/GrokAdapter.ts"; +import { type EventNdjsonLogger, makeEventNdjsonLogger } from "./EventNdjsonLogger.ts"; + +const encodeUnknownJsonStringExit = Schema.encodeUnknownExit(Schema.UnknownFromJsonString); + +const PROVIDER = ProviderDriverKind.make("grok"); +const GROK_RESUME_VERSION = 1 as const; + +function encodeJsonStringForDiagnostics(input: unknown): string | undefined { + const result = encodeUnknownJsonStringExit(input); + return Exit.isSuccess(result) ? result.value : undefined; +} + +export interface GrokAdapterLiveOptions { + readonly environment?: NodeJS.ProcessEnv; + readonly nativeEventLogPath?: string; + readonly nativeEventLogger?: EventNdjsonLogger; + readonly instanceId?: ProviderInstanceId; +} + +interface PendingApproval { + readonly decision: Deferred.Deferred; +} + +type PendingUserInputResolution = + | { readonly _tag: "answered"; readonly answers: ProviderUserInputAnswers } + | { readonly _tag: "cancelled" }; + +interface PendingUserInput { + readonly resolution: Deferred.Deferred; +} + +interface GrokSessionContext { + readonly threadId: ThreadId; + readonly acpSessionId: string; + session: ProviderSession; + readonly scope: Scope.Closeable; + readonly acp: AcpSessionRuntimeShape; + notificationFiber: Fiber.Fiber | undefined; + readonly pendingApprovals: Map; + readonly pendingUserInputs: Map; + turns: Array<{ id: TurnId; items: Array }>; + lastPlanFingerprint: string | undefined; + activeTurnId: TurnId | undefined; + currentModelId: string | undefined; + stopped: boolean; +} + +function settlePendingApprovalsAsCancelled( + pendingApprovals: ReadonlyMap, +): Effect.Effect { + return Effect.forEach( + Array.from(pendingApprovals.values()), + (pending) => Deferred.succeed(pending.decision, "cancel").pipe(Effect.ignore), + { discard: true }, + ); +} + +function settlePendingUserInputsAsCancelled( + pendingUserInputs: ReadonlyMap, +): Effect.Effect { + return Effect.forEach( + Array.from(pendingUserInputs.values()), + (pending) => Deferred.succeed(pending.resolution, { _tag: "cancelled" }).pipe(Effect.ignore), + { discard: true }, + ); +} + +function isRecord(value: unknown): value is Record { + return typeof value === "object" && value !== null && !Array.isArray(value); +} + +function parseGrokResume(raw: unknown): { sessionId: string } | undefined { + if (!isRecord(raw)) return undefined; + if (raw.schemaVersion !== GROK_RESUME_VERSION) return undefined; + if (typeof raw.sessionId !== "string" || !raw.sessionId.trim()) return undefined; + return { sessionId: raw.sessionId.trim() }; +} + +function selectPermissionOptionId( + request: EffectAcpSchema.RequestPermissionRequest, + decision: Exclude, +): string | undefined { + const kind = + decision === "acceptForSession" + ? "allow_always" + : decision === "accept" + ? "allow_once" + : "reject_once"; + const option = request.options.find((entry) => entry.kind === kind); + return option?.optionId.trim() || undefined; +} + +function selectAutoApprovedPermissionOption( + request: EffectAcpSchema.RequestPermissionRequest, +): string | undefined { + return ( + selectPermissionOptionId(request, "acceptForSession") ?? + selectPermissionOptionId(request, "accept") + ); +} + +export function makeGrokAdapter(grokSettings: GrokSettings, options?: GrokAdapterLiveOptions) { + return Effect.gen(function* () { + const boundInstanceId = options?.instanceId ?? ProviderInstanceId.make("grok"); + const fileSystem = yield* FileSystem.FileSystem; + const path = yield* Path.Path; + const childProcessSpawner = yield* ChildProcessSpawner.ChildProcessSpawner; + const serverConfig = yield* Effect.service(ServerConfig); + const crypto = yield* Crypto.Crypto; + const nativeEventLogger = + options?.nativeEventLogger ?? + (options?.nativeEventLogPath !== undefined + ? yield* makeEventNdjsonLogger(options.nativeEventLogPath, { stream: "native" }) + : undefined); + const managedNativeEventLogger = + options?.nativeEventLogger === undefined ? nativeEventLogger : undefined; + const makeAcpNativeLoggers = yield* makeAcpNativeLoggerFactory(); + + const sessions = new Map(); + const threadLocksRef = yield* SynchronizedRef.make(new Map()); + const runtimeEventPubSub = yield* PubSub.unbounded(); + + const nowIso = Effect.map(DateTime.now, DateTime.formatIso); + const randomUUIDv4 = crypto.randomUUIDv4.pipe( + Effect.mapError( + (cause) => + new ProviderAdapterRequestError({ + provider: PROVIDER, + method: "crypto/randomUUIDv4", + detail: "Failed to generate Grok runtime identifier.", + cause, + }), + ), + ); + const nextEventId = Effect.map(randomUUIDv4, (id) => EventId.make(id)); + const makeEventStamp = () => Effect.all({ eventId: nextEventId, createdAt: nowIso }); + const mapAcpCallbackFailure = (effect: Effect.Effect) => + effect.pipe( + Effect.mapError( + (cause) => + new EffectAcpErrors.AcpTransportError({ + detail: "Failed to process Grok ACP callback.", + cause, + }), + ), + ); + + const offerRuntimeEvent = (event: ProviderRuntimeEvent) => + PubSub.publish(runtimeEventPubSub, event).pipe(Effect.asVoid); + + const getThreadSemaphore = (threadId: string) => + SynchronizedRef.modifyEffect(threadLocksRef, (current) => { + const existing: Option.Option = Option.fromNullishOr( + current.get(threadId), + ); + return Option.match(existing, { + onNone: () => + Semaphore.make(1).pipe( + Effect.map((semaphore) => { + const next = new Map(current); + next.set(threadId, semaphore); + return [semaphore, next] as const; + }), + ), + onSome: (semaphore) => Effect.succeed([semaphore, current] as const), + }); + }); + + const withThreadLock = (threadId: string, effect: Effect.Effect) => + Effect.flatMap(getThreadSemaphore(threadId), (semaphore) => semaphore.withPermit(effect)); + + const logNative = (threadId: ThreadId, method: string, payload: unknown) => + Effect.gen(function* () { + if (!nativeEventLogger) return; + const observedAt = yield* nowIso; + yield* nativeEventLogger.write( + { + observedAt, + event: { + id: yield* randomUUIDv4, + kind: "notification", + provider: PROVIDER, + createdAt: observedAt, + method, + threadId, + payload, + }, + }, + threadId, + ); + }).pipe( + Effect.catchCause((cause) => + Effect.logWarning("Failed to write native Grok notification log.", { + cause, + threadId, + method, + }), + ), + ); + + const emitPlanUpdate = ( + ctx: GrokSessionContext, + payload: { + readonly explanation?: string | null; + readonly plan: ReadonlyArray<{ + readonly step: string; + readonly status: "pending" | "inProgress" | "completed"; + }>; + }, + rawPayload: unknown, + method: string, + ) => + Effect.gen(function* () { + const fingerprint = `${ctx.activeTurnId ?? "no-turn"}:${encodeJsonStringForDiagnostics(payload) ?? "[unserializable payload]"}`; + if (ctx.lastPlanFingerprint === fingerprint) { + return; + } + ctx.lastPlanFingerprint = fingerprint; + yield* offerRuntimeEvent( + makeAcpPlanUpdatedEvent({ + stamp: yield* makeEventStamp(), + provider: PROVIDER, + threadId: ctx.threadId, + turnId: ctx.activeTurnId, + payload, + source: "acp.jsonrpc", + method, + rawPayload, + }), + ); + }); + + const requireSession = ( + threadId: ThreadId, + ): Effect.Effect => { + const ctx = sessions.get(threadId); + if (!ctx || ctx.stopped) { + return Effect.fail( + new ProviderAdapterSessionNotFoundError({ provider: PROVIDER, threadId }), + ); + } + return Effect.succeed(ctx); + }; + + const stopSessionInternal = (ctx: GrokSessionContext) => + Effect.gen(function* () { + if (ctx.stopped) return; + ctx.stopped = true; + yield* settlePendingApprovalsAsCancelled(ctx.pendingApprovals); + yield* settlePendingUserInputsAsCancelled(ctx.pendingUserInputs); + if (ctx.notificationFiber) { + yield* Fiber.interrupt(ctx.notificationFiber); + } + yield* Effect.ignore(Scope.close(ctx.scope, Exit.void)); + sessions.delete(ctx.threadId); + yield* offerRuntimeEvent({ + type: "session.exited", + ...(yield* makeEventStamp()), + provider: PROVIDER, + threadId: ctx.threadId, + payload: { exitKind: "graceful" }, + }); + }); + + const startSession: GrokAdapterShape["startSession"] = (input) => + withThreadLock( + input.threadId, + Effect.gen(function* () { + if (input.provider !== undefined && input.provider !== PROVIDER) { + return yield* new ProviderAdapterValidationError({ + provider: PROVIDER, + operation: "startSession", + issue: `Expected provider '${PROVIDER}' but received '${input.provider}'.`, + }); + } + if (!input.cwd?.trim()) { + return yield* new ProviderAdapterValidationError({ + provider: PROVIDER, + operation: "startSession", + issue: "cwd is required and must be non-empty.", + }); + } + + const cwd = path.resolve(input.cwd.trim()); + const grokModelSelection = + input.modelSelection?.instanceId === boundInstanceId ? input.modelSelection : undefined; + const existing = sessions.get(input.threadId); + if (existing && !existing.stopped) { + yield* stopSessionInternal(existing); + } + + const pendingApprovals = new Map(); + const pendingUserInputs = new Map(); + const sessionScope = yield* Scope.make("sequential"); + let sessionScopeTransferred = false; + yield* Effect.addFinalizer(() => + sessionScopeTransferred ? Effect.void : Scope.close(sessionScope, Exit.void), + ); + + const resumeSessionId = parseGrokResume(input.resumeCursor)?.sessionId; + const acpNativeLoggers = makeAcpNativeLoggers({ + nativeEventLogger, + provider: PROVIDER, + threadId: input.threadId, + }); + + const acp = yield* makeGrokAcpRuntime({ + grokSettings, + ...(options?.environment ? { environment: options.environment } : {}), + childProcessSpawner, + cwd, + ...(resumeSessionId ? { resumeSessionId } : {}), + clientInfo: { name: "t3-code", version: "0.0.0" }, + ...acpNativeLoggers, + }).pipe( + Effect.provideService(Scope.Scope, sessionScope), + Effect.mapError( + (cause) => + new ProviderAdapterProcessError({ + provider: PROVIDER, + threadId: input.threadId, + detail: cause.message, + cause, + }), + ), + ); + const started = yield* Effect.gen(function* () { + yield* Effect.forEach( + ["x.ai/ask_user_question", "_x.ai/ask_user_question"] as const, + (method) => + acp.handleExtRequest(method, XAiAskUserQuestionRequest, (params) => + mapAcpCallbackFailure( + Effect.gen(function* () { + yield* logNative(input.threadId, method, params); + const requestId = ApprovalRequestId.make(yield* randomUUIDv4); + const runtimeRequestId = RuntimeRequestId.make(requestId); + const resolution = yield* Deferred.make(); + pendingUserInputs.set(requestId, { resolution }); + yield* offerRuntimeEvent({ + type: "user-input.requested", + ...(yield* makeEventStamp()), + provider: PROVIDER, + threadId: input.threadId, + turnId: sessions.get(input.threadId)?.activeTurnId, + requestId: runtimeRequestId, + payload: { questions: extractXAiAskUserQuestions(params) }, + raw: { + source: "acp.grok.extension", + method, + payload: params, + }, + }); + const resolved = yield* Deferred.await(resolution); + pendingUserInputs.delete(requestId); + const resolvedAnswers = resolved._tag === "answered" ? resolved.answers : {}; + yield* offerRuntimeEvent({ + type: "user-input.resolved", + ...(yield* makeEventStamp()), + provider: PROVIDER, + threadId: input.threadId, + turnId: sessions.get(input.threadId)?.activeTurnId, + requestId: runtimeRequestId, + payload: { answers: resolvedAnswers }, + raw: { + source: "acp.grok.extension", + method, + payload: params, + }, + }); + switch (resolved._tag) { + case "answered": + return makeXAiAskUserQuestionResponse(params, resolved.answers); + case "cancelled": + return makeXAiAskUserQuestionCancelledResponse(); + } + }), + ), + ), + { discard: true }, + ); + yield* acp.handleRequestPermission((params) => + mapAcpCallbackFailure( + Effect.gen(function* () { + yield* logNative(input.threadId, "session/request_permission", params); + if (input.runtimeMode === "full-access") { + const autoApprovedOptionId = selectAutoApprovedPermissionOption(params); + if (autoApprovedOptionId !== undefined) { + return { + outcome: { + outcome: "selected" as const, + optionId: autoApprovedOptionId, + }, + }; + } + } + const permissionRequest = parsePermissionRequest(params); + const requestId = ApprovalRequestId.make(yield* randomUUIDv4); + const runtimeRequestId = RuntimeRequestId.make(requestId); + const decision = yield* Deferred.make(); + pendingApprovals.set(requestId, { decision }); + yield* offerRuntimeEvent( + makeAcpRequestOpenedEvent({ + stamp: yield* makeEventStamp(), + provider: PROVIDER, + threadId: input.threadId, + turnId: sessions.get(input.threadId)?.activeTurnId, + requestId: runtimeRequestId, + permissionRequest, + detail: + permissionRequest.detail ?? + encodeJsonStringForDiagnostics(params)?.slice(0, 2000) ?? + "[unserializable params]", + args: params, + source: "acp.jsonrpc", + method: "session/request_permission", + rawPayload: params, + }), + ); + const resolved = yield* Deferred.await(decision); + pendingApprovals.delete(requestId); + yield* offerRuntimeEvent( + makeAcpRequestResolvedEvent({ + stamp: yield* makeEventStamp(), + provider: PROVIDER, + threadId: input.threadId, + turnId: sessions.get(input.threadId)?.activeTurnId, + requestId: runtimeRequestId, + permissionRequest, + decision: resolved, + }), + ); + const selectedOptionId = + resolved === "cancel" ? undefined : selectPermissionOptionId(params, resolved); + return { + outcome: selectedOptionId + ? { + outcome: "selected" as const, + optionId: selectedOptionId, + } + : ({ outcome: "cancelled" } as const), + }; + }), + ), + ); + return yield* acp.start(); + }).pipe( + Effect.mapError((error) => + mapAcpToAdapterError(PROVIDER, input.threadId, "session/start", error), + ), + ); + + const requestedStartModelId = grokModelSelection?.model + ? resolveGrokAcpBaseModelId(grokModelSelection.model) + : undefined; + const boundModelId = yield* applyGrokAcpModelSelection({ + runtime: acp, + currentModelId: currentGrokModelIdFromSessionSetup(started.sessionSetupResult), + requestedModelId: requestedStartModelId, + mapError: (cause) => + mapAcpToAdapterError(PROVIDER, input.threadId, "session/set_model", cause), + }); + + const now = yield* nowIso; + const session: ProviderSession = { + provider: PROVIDER, + providerInstanceId: boundInstanceId, + status: "ready", + runtimeMode: input.runtimeMode, + cwd, + ...(boundModelId ? { model: resolveGrokAcpBaseModelId(boundModelId) } : {}), + threadId: input.threadId, + resumeCursor: { + schemaVersion: GROK_RESUME_VERSION, + sessionId: started.sessionId, + }, + createdAt: now, + updatedAt: now, + }; + + const ctx: GrokSessionContext = { + threadId: input.threadId, + acpSessionId: started.sessionId, + session, + scope: sessionScope, + acp, + notificationFiber: undefined, + pendingApprovals, + pendingUserInputs, + turns: [], + lastPlanFingerprint: undefined, + activeTurnId: undefined, + currentModelId: boundModelId, + stopped: false, + }; + + const nf = yield* Stream.runDrain( + Stream.mapEffect(acp.getEvents(), (event) => + Effect.gen(function* () { + switch (event._tag) { + case "AssistantItemStarted": + yield* offerRuntimeEvent( + makeAcpAssistantItemEvent({ + stamp: yield* makeEventStamp(), + provider: PROVIDER, + threadId: ctx.threadId, + turnId: ctx.activeTurnId, + itemId: event.itemId, + lifecycle: "item.started", + }), + ); + return; + case "AssistantItemCompleted": + yield* offerRuntimeEvent( + makeAcpAssistantItemEvent({ + stamp: yield* makeEventStamp(), + provider: PROVIDER, + threadId: ctx.threadId, + turnId: ctx.activeTurnId, + itemId: event.itemId, + lifecycle: "item.completed", + }), + ); + return; + case "PlanUpdated": + yield* logNative(ctx.threadId, "session/update", event.rawPayload); + yield* emitPlanUpdate(ctx, event.payload, event.rawPayload, "session/update"); + return; + case "ToolCallUpdated": + yield* logNative(ctx.threadId, "session/update", event.rawPayload); + yield* offerRuntimeEvent( + makeAcpToolCallEvent({ + stamp: yield* makeEventStamp(), + provider: PROVIDER, + threadId: ctx.threadId, + turnId: ctx.activeTurnId, + toolCall: event.toolCall, + rawPayload: event.rawPayload, + }), + ); + return; + case "ContentDelta": + yield* logNative(ctx.threadId, "session/update", event.rawPayload); + yield* offerRuntimeEvent( + makeAcpContentDeltaEvent({ + stamp: yield* makeEventStamp(), + provider: PROVIDER, + threadId: ctx.threadId, + turnId: ctx.activeTurnId, + ...(event.itemId ? { itemId: event.itemId } : {}), + text: event.text, + rawPayload: event.rawPayload, + }), + ); + return; + } + }), + ), + ).pipe( + Effect.catch((cause) => + Effect.logError("Failed to process Grok runtime notification.", { cause }), + ), + Effect.forkChild, + ); + + ctx.notificationFiber = nf; + sessions.set(input.threadId, ctx); + sessionScopeTransferred = true; + + yield* offerRuntimeEvent({ + type: "session.started", + ...(yield* makeEventStamp()), + provider: PROVIDER, + threadId: input.threadId, + payload: { resume: started.initializeResult }, + }); + yield* offerRuntimeEvent({ + type: "session.state.changed", + ...(yield* makeEventStamp()), + provider: PROVIDER, + threadId: input.threadId, + payload: { state: "ready", reason: "Grok ACP session ready" }, + }); + yield* offerRuntimeEvent({ + type: "thread.started", + ...(yield* makeEventStamp()), + provider: PROVIDER, + threadId: input.threadId, + payload: { providerThreadId: started.sessionId }, + }); + + return session; + }).pipe(Effect.scoped), + ); + + const sendTurn: GrokAdapterShape["sendTurn"] = (input) => + Effect.gen(function* () { + const prepared = yield* withThreadLock( + input.threadId, + Effect.gen(function* () { + const ctx = yield* requireSession(input.threadId); + const turnId = TurnId.make(yield* randomUUIDv4); + const turnModelSelection = + input.modelSelection?.instanceId === boundInstanceId + ? input.modelSelection + : undefined; + const requestedTurnModelId = turnModelSelection?.model + ? resolveGrokAcpBaseModelId(turnModelSelection.model) + : undefined; + const currentModelId = yield* applyGrokAcpModelSelection({ + runtime: ctx.acp, + currentModelId: ctx.currentModelId, + requestedModelId: requestedTurnModelId, + mapError: (cause) => + mapAcpToAdapterError(PROVIDER, input.threadId, "session/set_model", cause), + }); + + const text = input.input?.trim(); + const imagePromptParts = yield* Effect.forEach(input.attachments ?? [], (attachment) => + Effect.gen(function* () { + const attachmentPath = resolveAttachmentPath({ + attachmentsDir: serverConfig.attachmentsDir, + attachment, + }); + if (!attachmentPath) { + return yield* new ProviderAdapterRequestError({ + provider: PROVIDER, + method: "session/prompt", + detail: `Invalid attachment id '${attachment.id}'.`, + }); + } + const bytes = yield* fileSystem.readFile(attachmentPath).pipe( + Effect.mapError( + (cause) => + new ProviderAdapterRequestError({ + provider: PROVIDER, + method: "session/prompt", + detail: cause.message, + cause, + }), + ), + ); + return { + type: "image", + data: Buffer.from(bytes).toString("base64"), + mimeType: attachment.mimeType, + } satisfies EffectAcpSchema.ContentBlock; + }), + ); + const promptParts: Array = [ + ...(text ? [{ type: "text" as const, text }] : []), + ...imagePromptParts, + ]; + + if (promptParts.length === 0) { + return yield* new ProviderAdapterValidationError({ + provider: PROVIDER, + operation: "sendTurn", + issue: "Turn requires non-empty text or attachments.", + }); + } + + ctx.currentModelId = currentModelId; + const displayModel = currentModelId + ? resolveGrokAcpBaseModelId(currentModelId) + : undefined; + ctx.activeTurnId = turnId; + ctx.lastPlanFingerprint = undefined; + ctx.session = { + ...ctx.session, + activeTurnId: turnId, + updatedAt: yield* nowIso, + ...(displayModel ? { model: displayModel } : {}), + }; + + yield* offerRuntimeEvent({ + type: "turn.started", + ...(yield* makeEventStamp()), + provider: PROVIDER, + threadId: input.threadId, + turnId, + payload: displayModel ? { model: displayModel } : {}, + }); + + return { + acp: ctx.acp, + acpSessionId: ctx.acpSessionId, + displayModel, + promptParts, + turnId, + }; + }), + ); + + const result = yield* prepared.acp + .prompt({ + prompt: prepared.promptParts, + }) + .pipe( + Effect.mapError((error) => + mapAcpToAdapterError(PROVIDER, input.threadId, "session/prompt", error), + ), + ); + + return yield* withThreadLock( + input.threadId, + Effect.gen(function* () { + const ctx = yield* requireSession(input.threadId); + if (ctx.acpSessionId !== prepared.acpSessionId) { + return yield* new ProviderAdapterRequestError({ + provider: PROVIDER, + method: "session/prompt", + detail: "Grok session changed before the turn completed.", + }); + } + + ctx.turns = [ + ...ctx.turns, + { id: prepared.turnId, items: [{ prompt: prepared.promptParts, result }] }, + ]; + ctx.session = { + ...ctx.session, + activeTurnId: prepared.turnId, + updatedAt: yield* nowIso, + ...(prepared.displayModel ? { model: prepared.displayModel } : {}), + }; + + yield* offerRuntimeEvent({ + type: "turn.completed", + ...(yield* makeEventStamp()), + provider: PROVIDER, + threadId: input.threadId, + turnId: prepared.turnId, + payload: { + state: result.stopReason === "cancelled" ? "cancelled" : "completed", + stopReason: result.stopReason ?? null, + }, + }); + + return { + threadId: input.threadId, + turnId: prepared.turnId, + resumeCursor: ctx.session.resumeCursor, + }; + }), + ); + }); + + const interruptTurn: GrokAdapterShape["interruptTurn"] = (threadId) => + Effect.gen(function* () { + const ctx = yield* requireSession(threadId); + yield* settlePendingApprovalsAsCancelled(ctx.pendingApprovals); + yield* settlePendingUserInputsAsCancelled(ctx.pendingUserInputs); + yield* Effect.ignore( + ctx.acp.cancel.pipe( + Effect.mapError((error) => + mapAcpToAdapterError(PROVIDER, threadId, "session/cancel", error), + ), + ), + ); + }); + + const respondToRequest: GrokAdapterShape["respondToRequest"] = ( + threadId, + requestId, + decision, + ) => + Effect.gen(function* () { + const ctx = yield* requireSession(threadId); + const pending = ctx.pendingApprovals.get(requestId); + if (!pending) { + return yield* new ProviderAdapterRequestError({ + provider: PROVIDER, + method: "session/request_permission", + detail: `Unknown pending approval request: ${requestId}`, + }); + } + yield* Deferred.succeed(pending.decision, decision); + }); + + const respondToUserInput: GrokAdapterShape["respondToUserInput"] = ( + threadId, + requestId, + answers, + ) => + Effect.gen(function* () { + const ctx = yield* requireSession(threadId); + const pending = ctx.pendingUserInputs.get(requestId); + if (!pending) { + return yield* new ProviderAdapterRequestError({ + provider: PROVIDER, + method: "_x.ai/ask_user_question", + detail: `Unknown pending user-input request: ${requestId}`, + }); + } + yield* Deferred.succeed(pending.resolution, { _tag: "answered", answers }); + }); + + const readThread: GrokAdapterShape["readThread"] = (threadId) => + Effect.gen(function* () { + const ctx = yield* requireSession(threadId); + return { threadId, turns: ctx.turns }; + }); + + const rollbackThread: GrokAdapterShape["rollbackThread"] = (threadId, numTurns) => + Effect.gen(function* () { + yield* requireSession(threadId); + if (!Number.isInteger(numTurns) || numTurns < 1) { + return yield* new ProviderAdapterValidationError({ + provider: PROVIDER, + operation: "rollbackThread", + issue: "numTurns must be an integer >= 1.", + }); + } + return yield* new ProviderAdapterRequestError({ + provider: PROVIDER, + method: "thread/rollback", + detail: "Grok ACP sessions do not support provider-side rollback yet.", + }); + }); + + const compactThread: GrokAdapterShape["compactThread"] = (_threadId) => + Effect.fail( + new ProviderAdapterRequestError({ + provider: PROVIDER, + method: "thread/compact", + detail: "Grok ACP sessions do not support provider-side compaction.", + }), + ); + + const stopSession: GrokAdapterShape["stopSession"] = (threadId) => + withThreadLock( + threadId, + Effect.gen(function* () { + const ctx = yield* requireSession(threadId); + yield* stopSessionInternal(ctx); + }), + ); + + const listSessions: GrokAdapterShape["listSessions"] = () => + Effect.sync(() => Array.from(sessions.values(), (c) => ({ ...c.session }))); + + const hasSession: GrokAdapterShape["hasSession"] = (threadId) => + Effect.sync(() => { + const c = sessions.get(threadId); + return c !== undefined && !c.stopped; + }); + + const stopAll: GrokAdapterShape["stopAll"] = () => + Effect.forEach(Array.from(sessions.values()), stopSessionInternal, { discard: true }); + + yield* Effect.addFinalizer(() => + Effect.ignore(stopAll()).pipe( + Effect.tap(() => PubSub.shutdown(runtimeEventPubSub)), + Effect.tap(() => managedNativeEventLogger?.close() ?? Effect.void), + ), + ); + + const streamEvents = Stream.fromPubSub(runtimeEventPubSub); + + return { + provider: PROVIDER, + capabilities: { sessionModelSwitch: "in-session", supportsMcpToggle: false }, + startSession, + sendTurn, + interruptTurn, + readThread, + rollbackThread, + compactThread, + respondToRequest, + respondToUserInput, + stopSession, + listSessions, + hasSession, + stopAll, + streamEvents, + } satisfies GrokAdapterShape; + }); +} diff --git a/apps/server/src/provider/Layers/GrokProvider.test.ts b/apps/server/src/provider/Layers/GrokProvider.test.ts new file mode 100644 index 000000000000..75d0982565ed --- /dev/null +++ b/apps/server/src/provider/Layers/GrokProvider.test.ts @@ -0,0 +1,108 @@ +import * as NodeServices from "@effect/platform-node/NodeServices"; +import { describe, expect, it } from "@effect/vitest"; +import * as Effect from "effect/Effect"; +import * as FileSystem from "effect/FileSystem"; +import * as Path from "effect/Path"; +import * as Schema from "effect/Schema"; +import { GrokSettings } from "@t3tools/contracts"; + +import { buildInitialGrokProviderSnapshot, checkGrokProviderStatus } from "./GrokProvider.ts"; + +const decodeGrokSettings = Schema.decodeSync(GrokSettings); + +describe("buildInitialGrokProviderSnapshot", () => { + it.effect("returns a disabled snapshot when settings.enabled is false", () => + Effect.gen(function* () { + const snapshot = yield* buildInitialGrokProviderSnapshot( + decodeGrokSettings({ enabled: false }), + ); + expect(snapshot.enabled).toBe(false); + expect(snapshot.status).toBe("disabled"); + expect(snapshot.installed).toBe(false); + expect(snapshot.message).toContain("disabled"); + }), + ); + + it.effect("returns a pending snapshot by default", () => + Effect.gen(function* () { + const snapshot = yield* buildInitialGrokProviderSnapshot(decodeGrokSettings({})); + expect(snapshot.enabled).toBe(true); + expect(snapshot.installed).toBe(true); + expect(snapshot.status).toBe("warning"); + expect(snapshot.version).toBeNull(); + expect(snapshot.message).toContain("Checking Grok"); + expect(snapshot.requiresNewThreadForModelChange).toBe(true); + }), + ); +}); + +it.layer(NodeServices.layer)("checkGrokProviderStatus", (it) => { + it.effect("reports the binary as missing when the binary path does not resolve", () => + Effect.gen(function* () { + const snapshot = yield* checkGrokProviderStatus( + decodeGrokSettings({ + enabled: true, + binaryPath: "/definitely/not/installed/grok-binary", + }), + ); + expect(snapshot.enabled).toBe(true); + expect(snapshot.installed).toBe(false); + expect(snapshot.status).toBe("error"); + expect(snapshot.message).toMatch(/not installed|not on PATH|Failed to execute/); + }), + ); + + it.effect("reports an installed CLI as unhealthy when --version exits non-zero", () => + Effect.gen(function* () { + const snapshot = yield* Effect.scoped( + Effect.gen(function* () { + const fs = yield* FileSystem.FileSystem; + const path = yield* Path.Path; + const dir = yield* fs.makeTempDirectoryScoped({ prefix: "t3code-grok-version-" }); + const grokPath = path.join(dir, "grok"); + yield* fs.writeFileString( + grokPath, + ["#!/bin/sh", 'printf "%s\\n" "broken grok install" >&2', "exit 2", ""].join("\n"), + ); + yield* fs.chmod(grokPath, 0o755); + + return yield* checkGrokProviderStatus( + decodeGrokSettings({ enabled: true, binaryPath: grokPath }), + ); + }), + ); + + expect(snapshot.enabled).toBe(true); + expect(snapshot.installed).toBe(true); + expect(snapshot.status).toBe("error"); + expect(snapshot.message).toContain("broken grok install"); + }), + ); + + it.effect("reports an error when ACP model discovery is unavailable", () => + Effect.gen(function* () { + const snapshot = yield* Effect.scoped( + Effect.gen(function* () { + const fs = yield* FileSystem.FileSystem; + const path = yield* Path.Path; + const dir = yield* fs.makeTempDirectoryScoped({ prefix: "t3code-grok-success-" }); + const grokPath = path.join(dir, "grok"); + yield* fs.writeFileString( + grokPath, + ["#!/bin/sh", 'printf "grok-cli 0.0.99\\n"', "exit 0", ""].join("\n"), + ); + yield* fs.chmod(grokPath, 0o755); + + return yield* checkGrokProviderStatus( + decodeGrokSettings({ enabled: true, binaryPath: grokPath }), + ); + }), + ); + + expect(snapshot.status).toBe("error"); + expect(snapshot.installed).toBe(true); + expect(snapshot.models.map((model) => model.slug)).toEqual(["grok-build"]); + expect(snapshot.message).toContain("ACP startup failed"); + }), + ); +}); diff --git a/apps/server/src/provider/Layers/GrokProvider.ts b/apps/server/src/provider/Layers/GrokProvider.ts new file mode 100644 index 000000000000..bead8b1a4077 --- /dev/null +++ b/apps/server/src/provider/Layers/GrokProvider.ts @@ -0,0 +1,324 @@ +import { + type GrokSettings, + type ModelCapabilities, + ProviderDriverKind, + type ServerProvider, + type ServerProviderModel, +} from "@t3tools/contracts"; +import type * as EffectAcpSchema from "effect-acp/schema"; +import * as Cause from "effect/Cause"; +import * as DateTime from "effect/DateTime"; +import * as Effect from "effect/Effect"; +import * as Exit from "effect/Exit"; +import * as Option from "effect/Option"; +import * as Result from "effect/Result"; +import { HttpClient } from "effect/unstable/http"; +import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"; +import { createModelCapabilities } from "@t3tools/shared/model"; + +import { + buildServerProvider, + detailFromResult, + isCommandMissingCause, + parseGenericCliVersion, + providerModelsFromSettings, + spawnAndCollect, + type ServerProviderDraft, +} from "../providerSnapshot.ts"; +import { + enrichProviderSnapshotWithVersionAdvisory, + type ProviderMaintenanceCapabilities, +} from "../providerMaintenance.ts"; +import { makeGrokAcpRuntime, resolveGrokAcpBaseModelId } from "../acp/GrokAcpSupport.ts"; + +const GROK_PRESENTATION = { + displayName: "Grok", + badgeLabel: "Early Access", + showInteractionModeToggle: false, + requiresNewThreadForModelChange: true, +} as const; +const PROVIDER = ProviderDriverKind.make("grok"); +const EMPTY_CAPABILITIES: ModelCapabilities = createModelCapabilities({ + optionDescriptors: [], +}); + +const VERSION_PROBE_TIMEOUT_MS = 4_000; +const GROK_ACP_MODEL_DISCOVERY_TIMEOUT_MS = 15_000; + +const GROK_BUILT_IN_MODELS: ReadonlyArray = [ + { + slug: "grok-build", + name: "Grok Build", + isCustom: false, + capabilities: EMPTY_CAPABILITIES, + }, +]; + +export function buildInitialGrokProviderSnapshot( + grokSettings: GrokSettings, +): Effect.Effect { + return Effect.gen(function* () { + const checkedAt = yield* Effect.map(DateTime.now, DateTime.formatIso); + const models = grokModelsFromSettings(grokSettings.customModels); + + if (!grokSettings.enabled) { + return buildServerProvider({ + presentation: GROK_PRESENTATION, + enabled: false, + checkedAt, + models, + probe: { + installed: false, + version: null, + status: "warning", + auth: { status: "unknown" }, + message: "Grok is disabled in T3 Code settings.", + }, + }); + } + + return buildServerProvider({ + presentation: GROK_PRESENTATION, + enabled: true, + checkedAt, + models, + probe: { + installed: true, + version: null, + status: "warning", + auth: { status: "unknown" }, + message: "Checking Grok CLI availability...", + }, + }); + }); +} + +function grokModelsFromSettings( + customModels: ReadonlyArray | undefined, + builtInModels: ReadonlyArray = GROK_BUILT_IN_MODELS, +): ReadonlyArray { + return providerModelsFromSettings( + builtInModels, + PROVIDER, + customModels ?? [], + EMPTY_CAPABILITIES, + ); +} + +function buildGrokDiscoveredModelsFromSessionModelState( + modelState: EffectAcpSchema.SessionModelState | null | undefined, +): ReadonlyArray { + if (!modelState || modelState.availableModels.length === 0) { + return []; + } + const seen = new Set(); + return modelState.availableModels + .map((model): ServerProviderModel | undefined => { + const slug = resolveGrokAcpBaseModelId(model.modelId); + if (!slug || seen.has(slug)) { + return undefined; + } + seen.add(slug); + return { + slug, + name: model.name.trim() || slug, + isCustom: false, + capabilities: EMPTY_CAPABILITIES, + }; + }) + .filter((model): model is ServerProviderModel => model !== undefined); +} + +const discoverGrokModelsViaAcp = ( + grokSettings: GrokSettings, + environment: NodeJS.ProcessEnv = process.env, +) => + Effect.gen(function* () { + const childProcessSpawner = yield* ChildProcessSpawner.ChildProcessSpawner; + const acp = yield* makeGrokAcpRuntime({ + grokSettings, + environment, + childProcessSpawner, + cwd: process.cwd(), + clientInfo: { name: "t3-code-provider-probe", version: "0.0.0" }, + }); + const started = yield* acp.start(); + return buildGrokDiscoveredModelsFromSessionModelState(started.sessionSetupResult.models); + }).pipe(Effect.scoped); + +const runGrokVersionCommand = ( + grokSettings: GrokSettings, + environment: NodeJS.ProcessEnv = process.env, +) => { + const command = grokSettings.binaryPath || "grok"; + return spawnAndCollect( + command, + ChildProcess.make(command, ["--version"], { + env: environment, + shell: process.platform === "win32", + }), + ); +}; + +export const checkGrokProviderStatus = Effect.fn("checkGrokProviderStatus")(function* ( + grokSettings: GrokSettings, + environment: NodeJS.ProcessEnv = process.env, +): Effect.fn.Return { + const checkedAt = DateTime.formatIso(yield* DateTime.now); + const fallbackModels = grokModelsFromSettings(grokSettings.customModels); + + if (!grokSettings.enabled) { + return buildServerProvider({ + presentation: GROK_PRESENTATION, + enabled: false, + checkedAt, + models: fallbackModels, + probe: { + installed: false, + version: null, + status: "warning", + auth: { status: "unknown" }, + message: "Grok is disabled in T3 Code settings.", + }, + }); + } + + const versionResult = yield* runGrokVersionCommand(grokSettings, environment).pipe( + Effect.timeoutOption(VERSION_PROBE_TIMEOUT_MS), + Effect.result, + ); + + if (Result.isFailure(versionResult)) { + const error = versionResult.failure; + return buildServerProvider({ + presentation: GROK_PRESENTATION, + enabled: grokSettings.enabled, + checkedAt, + models: fallbackModels, + probe: { + installed: !isCommandMissingCause(error), + version: null, + status: "error", + auth: { status: "unknown" }, + message: isCommandMissingCause(error) + ? "Grok CLI (`grok`) is not installed or not on PATH." + : `Failed to execute Grok CLI health check: ${error instanceof Error ? error.message : String(error)}.`, + }, + }); + } + + if (Option.isNone(versionResult.success)) { + return buildServerProvider({ + presentation: GROK_PRESENTATION, + enabled: grokSettings.enabled, + checkedAt, + models: fallbackModels, + probe: { + installed: true, + version: null, + status: "error", + auth: { status: "unknown" }, + message: "Grok CLI is installed but timed out while running `grok --version`.", + }, + }); + } + + const versionOutput = versionResult.success.value; + const version = parseGenericCliVersion(`${versionOutput.stdout}\n${versionOutput.stderr}`); + if (versionOutput.code !== 0) { + const detail = detailFromResult(versionOutput); + return buildServerProvider({ + presentation: GROK_PRESENTATION, + enabled: grokSettings.enabled, + checkedAt, + models: fallbackModels, + probe: { + installed: true, + version, + status: "error", + auth: { status: "unknown" }, + message: detail + ? `Grok CLI is installed but failed to run. ${detail}` + : "Grok CLI is installed but failed to run.", + }, + }); + } + + const discoveryExit = yield* discoverGrokModelsViaAcp(grokSettings, environment).pipe( + Effect.timeoutOption(GROK_ACP_MODEL_DISCOVERY_TIMEOUT_MS), + Effect.exit, + ); + if (Exit.isFailure(discoveryExit)) { + const detail = Cause.pretty(discoveryExit.cause); + yield* Effect.logWarning("Grok ACP model discovery failed", { cause: detail }); + return buildServerProvider({ + presentation: GROK_PRESENTATION, + enabled: grokSettings.enabled, + checkedAt, + models: fallbackModels, + probe: { + installed: true, + version, + status: "error", + auth: { status: "unknown" }, + message: `Grok CLI is installed but ACP startup failed. ${detail}`, + }, + }); + } + if (Option.isNone(discoveryExit.value)) { + yield* Effect.logWarning( + `Grok ACP model discovery timed out after ${GROK_ACP_MODEL_DISCOVERY_TIMEOUT_MS}ms.`, + ); + return buildServerProvider({ + presentation: GROK_PRESENTATION, + enabled: grokSettings.enabled, + checkedAt, + models: fallbackModels, + probe: { + installed: true, + version, + status: "error", + auth: { status: "unknown" }, + message: `Grok CLI is installed but ACP startup timed out after ${GROK_ACP_MODEL_DISCOVERY_TIMEOUT_MS}ms.`, + }, + }); + } + const discoveredModels = discoveryExit.value.value; + const models = + discoveredModels.length > 0 + ? grokModelsFromSettings(grokSettings.customModels, discoveredModels) + : fallbackModels; + + return buildServerProvider({ + presentation: GROK_PRESENTATION, + enabled: grokSettings.enabled, + checkedAt, + models, + probe: { + installed: true, + version, + status: "ready", + auth: { status: "unknown" }, + }, + }); +}); + +export const enrichGrokSnapshot = (input: { + readonly snapshot: ServerProvider; + readonly maintenanceCapabilities: ProviderMaintenanceCapabilities; + readonly publishSnapshot: (snapshot: ServerProvider) => Effect.Effect; + readonly httpClient: HttpClient.HttpClient; +}): Effect.Effect => { + const { snapshot, publishSnapshot } = input; + + return enrichProviderSnapshotWithVersionAdvisory(snapshot, input.maintenanceCapabilities).pipe( + Effect.provideService(HttpClient.HttpClient, input.httpClient), + Effect.flatMap((enrichedSnapshot) => publishSnapshot(enrichedSnapshot)), + Effect.catchCause((cause) => + Effect.logWarning("Grok version advisory enrichment failed", { + cause: Cause.pretty(cause), + }), + ), + Effect.asVoid, + ); +}; diff --git a/apps/server/src/provider/Layers/ProviderInstanceRegistryLive.test.ts b/apps/server/src/provider/Layers/ProviderInstanceRegistryLive.test.ts index 1d444a2c34ae..57805459f239 100644 --- a/apps/server/src/provider/Layers/ProviderInstanceRegistryLive.test.ts +++ b/apps/server/src/provider/Layers/ProviderInstanceRegistryLive.test.ts @@ -10,7 +10,7 @@ * * 2. **Many drivers, one registry** — the "all drivers slice" describe * block below configures one instance of every shipped driver - * (`codex`, `claudeAgent`, `cursor`, `opencode`) in a single + * (`codex`, `claudeAgent`, `cursor`, `grok`, `opencode`) in a single * `ProviderInstanceConfigMap` and asserts the registry boots them all * without cross-contamination. This proves the driver SPI is uniform * across every provider — any driver plugs into the registry through @@ -18,7 +18,7 @@ * * Every instance in these tests is configured with `enabled: false` so the * provider-status checks short-circuit to pending/disabled snapshots - * without trying to spawn real `codex` / `claude` / `agent` / `opencode` + * without trying to spawn real `codex` / `claude` / `agent` / `grok` / `opencode` * binaries. That keeps the assertions focused on registry routing * behaviour rather than the runtime details of each provider. */ @@ -28,6 +28,7 @@ import { type ClaudeSettings, type CodexSettings, type CursorSettings, + type GrokSettings, type OpenCodeSettings, ProviderDriverKind, type ProviderInstanceConfigMap, @@ -40,12 +41,9 @@ import { HttpClient, HttpClientResponse } from "effect/unstable/http"; import { ServerConfig } from "../../config.ts"; import { ThreadMcpToggleRepository } from "../../persistence/Services/ThreadMcpToggles.ts"; import { ServerSettingsService } from "../../serverSettings.ts"; -import { ClaudeDriver, type ClaudeDriverEnv } from "../Drivers/ClaudeDriver.ts"; -import { CodexDriver, type CodexDriverEnv } from "../Drivers/CodexDriver.ts"; -import { CursorDriver, type CursorDriverEnv } from "../Drivers/CursorDriver.ts"; -import { OpenCodeDriver, type OpenCodeDriverEnv } from "../Drivers/OpenCodeDriver.ts"; +import { CodexDriver } from "../Drivers/CodexDriver.ts"; +import { BUILT_IN_DRIVERS } from "../builtInDrivers.ts"; import { OpenCodeRuntimeLive } from "../opencodeRuntime.ts"; -import type { AnyProviderDriver } from "../ProviderDriver.ts"; import { NoOpProviderEventLoggers, ProviderEventLoggers } from "./ProviderEventLoggers.ts"; import { makeProviderInstanceRegistry } from "./ProviderInstanceRegistryLive.ts"; @@ -88,6 +86,13 @@ const makeCursorConfig = (overrides: Partial): CursorSettings => ...overrides, }); +const makeGrokConfig = (overrides: Partial): GrokSettings => ({ + enabled: false, + binaryPath: "grok", + customModels: [], + ...overrides, +}); + const makeOpenCodeConfig = (overrides: Partial): OpenCodeSettings => ({ enabled: false, binaryPath: "opencode", @@ -228,7 +233,7 @@ describe("ProviderInstanceRegistryLive — multi-instance codex slice", () => { }); describe("ProviderInstanceRegistryLive — all drivers slice", () => { - // All four drivers need `NodeServices` (ChildProcessSpawner + FileSystem + + // All drivers need `NodeServices` (ChildProcessSpawner + FileSystem + // Path). `OpenCodeDriver.create` additionally yields `OpenCodeRuntime` // at construction time, so we wire `OpenCodeRuntimeLive` into the stack. // `OpenCodeRuntimeLive` bundles its own `NetService.layer` via @@ -256,11 +261,13 @@ describe("ProviderInstanceRegistryLive — all drivers slice", () => { const codexId = ProviderInstanceId.make("codex_default"); const claudeId = ProviderInstanceId.make("claude_default"); const cursorId = ProviderInstanceId.make("cursor_default"); + const grokId = ProviderInstanceId.make("grok_default"); const openCodeId = ProviderInstanceId.make("opencode_default"); const codexDriverKind = ProviderDriverKind.make("codex"); const claudeDriverKind = ProviderDriverKind.make("claudeAgent"); const cursorDriverKind = ProviderDriverKind.make("cursor"); + const grokDriverKind = ProviderDriverKind.make("grok"); const openCodeDriverKind = ProviderDriverKind.make("opencode"); const configMap: ProviderInstanceConfigMap = { @@ -285,6 +292,12 @@ describe("ProviderInstanceRegistryLive — all drivers slice", () => { enabled: false, config: makeCursorConfig({}), }, + [grokId]: { + driver: grokDriverKind, + displayName: "Grok", + enabled: false, + config: makeGrokConfig({}), + }, [openCodeId]: { driver: openCodeDriverKind, displayName: "OpenCode", @@ -292,12 +305,8 @@ describe("ProviderInstanceRegistryLive — all drivers slice", () => { config: makeOpenCodeConfig({}), }, }; - const drivers: ReadonlyArray< - AnyProviderDriver - > = [CodexDriver, ClaudeDriver, CursorDriver, OpenCodeDriver]; - const { registry } = yield* makeProviderInstanceRegistry({ - drivers, + drivers: BUILT_IN_DRIVERS, configMap, }); @@ -307,9 +316,9 @@ describe("ProviderInstanceRegistryLive — all drivers slice", () => { expect(unavailable).toEqual([]); const instances = yield* registry.listInstances; - expect(instances).toHaveLength(4); + expect(instances).toHaveLength(5); expect(instances.map((instance) => instance.instanceId).toSorted()).toEqual( - [codexId, claudeId, cursorId, openCodeId].toSorted(), + [codexId, claudeId, cursorId, grokId, openCodeId].toSorted(), ); // Instance lookup by id resolves each instance to its own bundle — @@ -318,14 +327,17 @@ describe("ProviderInstanceRegistryLive — all drivers slice", () => { const codex = yield* registry.getInstance(codexId); const claude = yield* registry.getInstance(claudeId); const cursor = yield* registry.getInstance(cursorId); + const grok = yield* registry.getInstance(grokId); const openCode = yield* registry.getInstance(openCodeId); expect(codex?.driverKind).toBe(codexDriverKind); expect(claude?.driverKind).toBe(claudeDriverKind); expect(cursor?.driverKind).toBe(cursorDriverKind); + expect(grok?.driverKind).toBe(grokDriverKind); expect(openCode?.driverKind).toBe(openCodeDriverKind); expect(codex?.displayName).toBe("Codex"); expect(claude?.displayName).toBe("Claude"); expect(cursor?.displayName).toBe("Cursor"); + expect(grok?.displayName).toBe("Grok"); expect(openCode?.displayName).toBe("OpenCode"); // Every instance owns its own set of closures — no sharing across @@ -333,16 +345,29 @@ describe("ProviderInstanceRegistryLive — all drivers slice", () => { // distinct references even when two instances happen to share a // trait (e.g. Cursor + others all use a stub-or-real // `textGeneration`; they must still be different object values). - const adapters = [codex!.adapter, claude!.adapter, cursor!.adapter, openCode!.adapter]; + const adapters = [ + codex!.adapter, + claude!.adapter, + cursor!.adapter, + grok!.adapter, + openCode!.adapter, + ]; expect(new Set(adapters).size).toBe(adapters.length); const textGenerations = [ codex!.textGeneration, claude!.textGeneration, cursor!.textGeneration, + grok!.textGeneration, openCode!.textGeneration, ]; expect(new Set(textGenerations).size).toBe(textGenerations.length); - const snapshots = [codex!.snapshot, claude!.snapshot, cursor!.snapshot, openCode!.snapshot]; + const snapshots = [ + codex!.snapshot, + claude!.snapshot, + cursor!.snapshot, + grok!.snapshot, + openCode!.snapshot, + ]; expect(new Set(snapshots).size).toBe(snapshots.length); // Snapshots identify themselves by `instanceId` + `driver` so @@ -371,6 +396,12 @@ describe("ProviderInstanceRegistryLive — all drivers slice", () => { `${cursorDriverKind}:instance:${cursorId}`, ); + const grokSnapshot = yield* grok!.snapshot.getSnapshot; + expect(grokSnapshot.instanceId).toBe(grokId); + expect(grokSnapshot.driver).toBe(grokDriverKind); + expect(grokSnapshot.enabled).toBe(false); + expect(grokSnapshot.continuation?.groupKey).toBe(`${grokDriverKind}:instance:${grokId}`); + const openCodeSnapshot = yield* openCode!.snapshot.getSnapshot; expect(openCodeSnapshot.instanceId).toBe(openCodeId); expect(openCodeSnapshot.driver).toBe(openCodeDriverKind); diff --git a/apps/server/src/provider/Layers/ProviderRegistry.test.ts b/apps/server/src/provider/Layers/ProviderRegistry.test.ts index 78f195450047..d469ccfe6ba9 100644 --- a/apps/server/src/provider/Layers/ProviderRegistry.test.ts +++ b/apps/server/src/provider/Layers/ProviderRegistry.test.ts @@ -43,9 +43,9 @@ import { selectProvidersByKind, } from "./ProviderRegistry.ts"; import { ServerConfig } from "../../config.ts"; -import { ThreadMcpToggleRepository } from "../../persistence/Services/ThreadMcpToggles.ts"; import { ServerSettingsService, type ServerSettingsShape } from "../../serverSettings.ts"; import { readProviderStatusCache, resolveProviderStatusCachePath } from "../providerStatusCache.ts"; +import { ThreadMcpToggleRepository } from "../../persistence/Services/ThreadMcpToggles.ts"; import type { ProviderInstance } from "../ProviderDriver.ts"; import { ProviderInstanceRegistry } from "../Services/ProviderInstanceRegistry.ts"; import { ProviderRegistry } from "../Services/ProviderRegistry.ts"; @@ -53,11 +53,6 @@ import { makeManualOnlyProviderMaintenanceCapabilities } from "../providerMainte const decodeServerSettings = Schema.decodeSync(ServerSettings); const encodeServerSettings = Schema.encodeSync(ServerSettings); const encodedDefaultServerSettings = encodeServerSettings(DEFAULT_SERVER_SETTINGS); -const noOpThreadMcpToggleRepositoryLayer = Layer.succeed(ThreadMcpToggleRepository, { - upsert: () => Effect.void, - listByThreadId: () => Effect.succeed([]), - deleteAllForThread: () => Effect.void, -}); const defaultClaudeSettings: ClaudeSettings = Schema.decodeSync(ClaudeSettings)({}); const defaultCodexSettings: CodexSettings = Schema.decodeSync(CodexSettings)({}); @@ -107,10 +102,7 @@ type TestClaudeCapabilities = { readonly subscriptionType: string | undefined; readonly tokenSource: string | undefined; readonly slashCommands: ReadonlyArray; - readonly mcpServers: ReadonlyArray<{ - readonly name: string; - readonly status: "connected" | "failed" | "needs-auth" | "pending" | "disabled"; - }>; + readonly mcpServers: ReadonlyArray; }; function claudeCapabilities(overrides: Partial = {}) { @@ -128,6 +120,12 @@ function claudeCapabilities(overrides: Partial = {}) { const noClaudeCapabilities = () => Effect.sync(() => undefined as TestClaudeCapabilities | undefined); +const NoOpThreadMcpToggleRepository = Layer.succeed(ThreadMcpToggleRepository, { + upsert: () => Effect.void, + listByThreadId: () => Effect.succeed([]), + deleteAllForThread: () => Effect.void, +}); + function mockHandle(result: { stdout: string; stderr: string; code: number }) { return ChildProcessSpawner.makeHandle({ pid: ChildProcessSpawner.ProcessId(1), @@ -309,305 +307,215 @@ function makeMutableServerSettingsService( }); } -it.layer( - Layer.mergeAll( - NodeServices.layer, - ServerSettingsService.layerTest(), - TestHttpClientLive, - noOpThreadMcpToggleRepositoryLayer, - ), -)("ProviderRegistry", (it) => { - describe("checkCodexProviderStatus", () => { - it.effect("uses the app-server account and model list for provider status", () => - Effect.gen(function* () { - const status = yield* checkCodexProviderStatus(defaultCodexSettings, () => - Effect.succeed( - makeCodexProbeSnapshot({ - skills: [ - { - name: "github:gh-fix-ci", - path: "/Users/test/.codex/skills/gh-fix-ci/SKILL.md", - enabled: true, - displayName: "CI Debug", - shortDescription: "Debug failing GitHub Actions checks", - }, - ], - }), - ), - ); - assert.strictEqual(status.status, "ready"); - assert.strictEqual(status.installed, true); - assert.strictEqual(status.version, "1.0.0"); - assert.strictEqual(status.auth.status, "authenticated"); - assert.strictEqual(status.auth.type, "chatgpt"); - assert.strictEqual(status.auth.label, "ChatGPT Pro 20x Subscription"); - assert.strictEqual(status.auth.email, "test@example.com"); - assert.deepStrictEqual(status.models, [ - { - slug: "gpt-live-codex", - name: "GPT Live Codex", - isCustom: false, - capabilities: codexModelCapabilities, - }, - ]); - assert.deepStrictEqual(status.skills, [ - { - name: "github:gh-fix-ci", - path: "/Users/test/.codex/skills/gh-fix-ci/SKILL.md", - enabled: true, - displayName: "CI Debug", - shortDescription: "Debug failing GitHub Actions checks", - }, - ]); - }), - ); - - it.effect("returns unauthenticated when app-server requires OpenAI auth", () => - Effect.gen(function* () { - const status = yield* checkCodexProviderStatus(defaultCodexSettings, () => - Effect.succeed( - makeCodexProbeSnapshot({ - account: { - account: null, - requiresOpenaiAuth: true, - }, - }), - ), - ); - - assert.strictEqual(status.status, "error"); - assert.strictEqual(status.auth.status, "unauthenticated"); - assert.strictEqual( - status.message, - "Codex CLI is not authenticated. Run `codex login` and try again.", - ); - }), - ); - - it.effect("returns ready with unknown auth when app-server does not require OpenAI auth", () => - Effect.gen(function* () { - const status = yield* checkCodexProviderStatus(defaultCodexSettings, () => - Effect.succeed( - makeCodexProbeSnapshot({ - account: { - account: null, - requiresOpenaiAuth: false, - }, - }), - ), - ); +it.layer(Layer.mergeAll(NodeServices.layer, ServerSettingsService.layerTest(), TestHttpClientLive))( + "ProviderRegistry", + (it) => { + describe("checkCodexProviderStatus", () => { + it.effect("uses the app-server account and model list for provider status", () => + Effect.gen(function* () { + const status = yield* checkCodexProviderStatus(defaultCodexSettings, () => + Effect.succeed( + makeCodexProbeSnapshot({ + skills: [ + { + name: "github:gh-fix-ci", + path: "/Users/test/.codex/skills/gh-fix-ci/SKILL.md", + enabled: true, + displayName: "CI Debug", + shortDescription: "Debug failing GitHub Actions checks", + }, + ], + }), + ), + ); + assert.strictEqual(status.status, "ready"); + assert.strictEqual(status.installed, true); + assert.strictEqual(status.version, "1.0.0"); + assert.strictEqual(status.auth.status, "authenticated"); + assert.strictEqual(status.auth.type, "chatgpt"); + assert.strictEqual(status.auth.label, "ChatGPT Pro 20x Subscription"); + assert.strictEqual(status.auth.email, "test@example.com"); + assert.deepStrictEqual(status.models, [ + { + slug: "gpt-live-codex", + name: "GPT Live Codex", + isCustom: false, + capabilities: codexModelCapabilities, + }, + ]); + assert.deepStrictEqual(status.skills, [ + { + name: "github:gh-fix-ci", + path: "/Users/test/.codex/skills/gh-fix-ci/SKILL.md", + enabled: true, + displayName: "CI Debug", + shortDescription: "Debug failing GitHub Actions checks", + }, + ]); + }), + ); - assert.strictEqual(status.status, "ready"); - assert.strictEqual(status.auth.status, "unknown"); - }), - ); + it.effect("returns unauthenticated when app-server requires OpenAI auth", () => + Effect.gen(function* () { + const status = yield* checkCodexProviderStatus(defaultCodexSettings, () => + Effect.succeed( + makeCodexProbeSnapshot({ + account: { + account: null, + requiresOpenaiAuth: true, + }, + }), + ), + ); - it.effect("returns an api key label for codex api key auth", () => - Effect.gen(function* () { - const status = yield* checkCodexProviderStatus(defaultCodexSettings, () => - Effect.succeed( - makeCodexProbeSnapshot({ - account: { - account: { type: "apiKey" }, - requiresOpenaiAuth: false, - }, - }), - ), - ); + assert.strictEqual(status.status, "error"); + assert.strictEqual(status.auth.status, "unauthenticated"); + assert.strictEqual( + status.message, + "Codex CLI is not authenticated. Run `codex login` and try again.", + ); + }), + ); - assert.strictEqual(status.status, "ready"); - assert.strictEqual(status.auth.status, "authenticated"); - assert.strictEqual(status.auth.type, "apiKey"); - assert.strictEqual(status.auth.label, "OpenAI API Key"); - }), - ); + it.effect( + "returns ready with unknown auth when app-server does not require OpenAI auth", + () => + Effect.gen(function* () { + const status = yield* checkCodexProviderStatus(defaultCodexSettings, () => + Effect.succeed( + makeCodexProbeSnapshot({ + account: { + account: null, + requiresOpenaiAuth: false, + }, + }), + ), + ); - it.effect("returns an Amazon Bedrock label for codex Bedrock auth", () => - Effect.gen(function* () { - const status = yield* checkCodexProviderStatus(defaultCodexSettings, () => - Effect.succeed( - makeCodexProbeSnapshot({ - account: { - account: { type: "amazonBedrock" }, - requiresOpenaiAuth: false, - }, - }), - ), - ); + assert.strictEqual(status.status, "ready"); + assert.strictEqual(status.auth.status, "unknown"); + }), + ); - assert.strictEqual(status.status, "ready"); - assert.strictEqual(status.auth.status, "authenticated"); - assert.strictEqual(status.auth.type, "amazonBedrock"); - assert.strictEqual(status.auth.label, "Amazon Bedrock"); - }), - ); + it.effect("returns an api key label for codex api key auth", () => + Effect.gen(function* () { + const status = yield* checkCodexProviderStatus(defaultCodexSettings, () => + Effect.succeed( + makeCodexProbeSnapshot({ + account: { + account: { type: "apiKey" }, + requiresOpenaiAuth: false, + }, + }), + ), + ); - it.effect("returns unavailable when codex is missing", () => - Effect.gen(function* () { - const status = yield* checkCodexProviderStatus(defaultCodexSettings, () => - Effect.fail( - new CodexErrors.CodexAppServerSpawnError({ - command: "codex app-server", - cause: new Error("spawn codex ENOENT"), - }), - ), - ); - assert.strictEqual(status.status, "error"); - assert.strictEqual(status.installed, false); - assert.strictEqual(status.auth.status, "unknown"); - assert.strictEqual(status.message, "Codex CLI (`codex`) is not installed or not on PATH."); - }), - ); + assert.strictEqual(status.status, "ready"); + assert.strictEqual(status.auth.status, "authenticated"); + assert.strictEqual(status.auth.type, "apiKey"); + assert.strictEqual(status.auth.label, "OpenAI API Key"); + }), + ); - it.effect("closes the app-server probe scope when provider status times out", () => - Effect.gen(function* () { - const killCalls = yield* Ref.make(0); - const statusFiber = yield* checkCodexProviderStatus(defaultCodexSettings).pipe( - Effect.provide(hangingScopedSpawnerLayer(killCalls)), - Effect.forkChild, - ); + it.effect("returns an Amazon Bedrock label for codex Bedrock auth", () => + Effect.gen(function* () { + const status = yield* checkCodexProviderStatus(defaultCodexSettings, () => + Effect.succeed( + makeCodexProbeSnapshot({ + account: { + account: { type: "amazonBedrock" }, + requiresOpenaiAuth: false, + }, + }), + ), + ); - yield* Effect.yieldNow; - yield* TestClock.adjust("11 seconds"); - yield* Effect.yieldNow; + assert.strictEqual(status.status, "ready"); + assert.strictEqual(status.auth.status, "authenticated"); + assert.strictEqual(status.auth.type, "amazonBedrock"); + assert.strictEqual(status.auth.label, "Amazon Bedrock"); + }), + ); - const status = yield* Fiber.join(statusFiber); - assert.strictEqual(status.status, "error"); - assert.strictEqual( - status.message, - "Timed out while checking Codex app-server provider status.", - ); - assert.strictEqual(yield* Ref.get(killCalls), 1); - }), - ); - }); + it.effect("returns unavailable when codex is missing", () => + Effect.gen(function* () { + const status = yield* checkCodexProviderStatus(defaultCodexSettings, () => + Effect.fail( + new CodexErrors.CodexAppServerSpawnError({ + command: "codex app-server", + cause: new Error("spawn codex ENOENT"), + }), + ), + ); + assert.strictEqual(status.status, "error"); + assert.strictEqual(status.installed, false); + assert.strictEqual(status.auth.status, "unknown"); + assert.strictEqual( + status.message, + "Codex CLI (`codex`) is not installed or not on PATH.", + ); + }), + ); - describe("ProviderRegistryLive", () => { - it("treats equal provider snapshots as unchanged", () => { - const providers = [ - { - instanceId: ProviderInstanceId.make("codex"), - driver: ProviderDriverKind.make("codex"), - status: "ready", - enabled: true, - installed: true, - auth: { status: "authenticated" }, - checkedAt: "2026-03-25T00:00:00.000Z", - version: "1.0.0", - models: [], - slashCommands: [], - skills: [], - }, - { - instanceId: ProviderInstanceId.make("claudeAgent"), - driver: ProviderDriverKind.make("claudeAgent"), - status: "warning", - enabled: true, - installed: true, - auth: { status: "unknown" }, - checkedAt: "2026-03-25T00:00:00.000Z", - version: "1.0.0", - models: [], - slashCommands: [], - skills: [], - }, - ] as const satisfies ReadonlyArray; + it.effect("closes the app-server probe scope when provider status times out", () => + Effect.gen(function* () { + const killCalls = yield* Ref.make(0); + const statusFiber = yield* checkCodexProviderStatus(defaultCodexSettings).pipe( + Effect.provide(hangingScopedSpawnerLayer(killCalls)), + Effect.forkChild, + ); - assert.strictEqual(haveProvidersChanged(providers, [...providers]), false); - }); + yield* Effect.yieldNow; + yield* TestClock.adjust("11 seconds"); + yield* Effect.yieldNow; - it("preserves previously discovered provider models when a refresh returns none", () => { - const previousProvider = { - instanceId: ProviderInstanceId.make("cursor"), - driver: ProviderDriverKind.make("cursor"), - status: "ready", - enabled: true, - installed: true, - auth: { status: "authenticated" }, - checkedAt: "2026-04-14T00:00:00.000Z", - version: "2026.04.09-f2b0fcd", - models: [ - { - slug: "claude-opus-4-6", - name: "Opus 4.6", - isCustom: false, - capabilities: createModelCapabilities({ - optionDescriptors: [ - selectDescriptor("reasoning", "Reasoning", [ - { id: "high", label: "High", isDefault: true }, - ]), - booleanDescriptor("fastMode", "Fast Mode"), - booleanDescriptor("thinking", "Thinking"), - ], - }), - }, - ], - slashCommands: [], - skills: [], - } as const satisfies ServerProvider; - const refreshedProvider = { - ...previousProvider, - checkedAt: "2026-04-14T00:01:00.000Z", - models: [], - } satisfies ServerProvider; - - assert.deepStrictEqual(mergeProviderSnapshot(previousProvider, refreshedProvider).models, [ - ...previousProvider.models, - ]); + const status = yield* Fiber.join(statusFiber); + assert.strictEqual(status.status, "error"); + assert.strictEqual( + status.message, + "Timed out while checking Codex app-server provider status.", + ); + assert.strictEqual(yield* Ref.get(killCalls), 1); + }), + ); }); - it("fills missing capabilities from the previous provider snapshot", () => { - const previousProvider = { - instanceId: ProviderInstanceId.make("cursor"), - driver: ProviderDriverKind.make("cursor"), - status: "ready", - enabled: true, - installed: true, - auth: { status: "authenticated" }, - checkedAt: "2026-04-14T00:00:00.000Z", - version: "2026.04.09-f2b0fcd", - models: [ + describe("ProviderRegistryLive", () => { + it("treats equal provider snapshots as unchanged", () => { + const providers = [ { - slug: "claude-opus-4-6", - name: "Opus 4.6", - isCustom: false, - capabilities: createModelCapabilities({ - optionDescriptors: [ - selectDescriptor("reasoning", "Reasoning", [ - { id: "high", label: "High", isDefault: true }, - ]), - booleanDescriptor("fastMode", "Fast Mode"), - booleanDescriptor("thinking", "Thinking"), - ], - }), + instanceId: ProviderInstanceId.make("codex"), + driver: ProviderDriverKind.make("codex"), + status: "ready", + enabled: true, + installed: true, + auth: { status: "authenticated" }, + checkedAt: "2026-03-25T00:00:00.000Z", + version: "1.0.0", + models: [], + slashCommands: [], + skills: [], }, - ], - slashCommands: [], - skills: [], - } as const satisfies ServerProvider; - const refreshedProvider = { - ...previousProvider, - checkedAt: "2026-04-14T00:01:00.000Z", - models: [ { - slug: "claude-opus-4-6", - name: "Opus 4.6", - isCustom: false, - capabilities: createModelCapabilities({ - optionDescriptors: [], - }), + instanceId: ProviderInstanceId.make("claudeAgent"), + driver: ProviderDriverKind.make("claudeAgent"), + status: "warning", + enabled: true, + installed: true, + auth: { status: "unknown" }, + checkedAt: "2026-03-25T00:00:00.000Z", + version: "1.0.0", + models: [], + slashCommands: [], + skills: [], }, - ], - } satisfies ServerProvider; + ] as const satisfies ReadonlyArray; - assert.deepStrictEqual(mergeProviderSnapshot(previousProvider, refreshedProvider).models, [ - ...previousProvider.models, - ]); - }); + assert.strictEqual(haveProvidersChanged(providers, [...providers]), false); + }); - it("persists merged provider snapshots for the providers that were refreshed", () => { - const previousProviders = [ - { + it("preserves previously discovered provider models when a refresh returns none", () => { + const previousProvider = { instanceId: ProviderInstanceId.make("cursor"), driver: ProviderDriverKind.make("cursor"), status: "ready", @@ -634,48 +542,22 @@ it.layer( ], slashCommands: [], skills: [], - }, - { - instanceId: ProviderInstanceId.make("codex"), - driver: ProviderDriverKind.make("codex"), - status: "ready", - enabled: true, - installed: true, - auth: { status: "authenticated" }, - checkedAt: "2026-04-14T00:00:00.000Z", - version: "1.0.0", + } as const satisfies ServerProvider; + const refreshedProvider = { + ...previousProvider, + checkedAt: "2026-04-14T00:01:00.000Z", models: [], - slashCommands: [], - skills: [], - }, - ] as const satisfies ReadonlyArray; - const refreshedCursor = { - ...previousProviders[0], - checkedAt: "2026-04-14T00:01:00.000Z", - models: [], - } satisfies ServerProvider; - - const mergedProviders = mergeProviderSnapshots(previousProviders, [refreshedCursor]); - const persistedProviders = selectProvidersByKind( - mergedProviders, - new Set([ProviderDriverKind.make("cursor")]), - ); + } satisfies ServerProvider; - assert.deepStrictEqual(persistedProviders, [ - { - ...refreshedCursor, - models: [...previousProviders[0].models], - }, - ]); - }); + assert.deepStrictEqual(mergeProviderSnapshot(previousProvider, refreshedProvider).models, [ + ...previousProvider.models, + ]); + }); - it.effect("persists the merged snapshot when a live update has empty models", () => - Effect.gen(function* () { - const cursorDriver = ProviderDriverKind.make("cursor"); - const cursorInstanceId = ProviderInstanceId.make("cursor"); - const initialProvider = { - instanceId: cursorInstanceId, - driver: cursorDriver, + it("fills missing capabilities from the previous provider snapshot", () => { + const previousProvider = { + instanceId: ProviderInstanceId.make("cursor"), + driver: ProviderDriverKind.make("cursor"), status: "ready", enabled: true, installed: true, @@ -692,6 +574,8 @@ it.layer( selectDescriptor("reasoning", "Reasoning", [ { id: "high", label: "High", isDefault: true }, ]), + booleanDescriptor("fastMode", "Fast Mode"), + booleanDescriptor("thinking", "Thinking"), ], }), }, @@ -700,695 +584,846 @@ it.layer( skills: [], } as const satisfies ServerProvider; const refreshedProvider = { - ...initialProvider, + ...previousProvider, checkedAt: "2026-04-14T00:01:00.000Z", - models: [], + models: [ + { + slug: "claude-opus-4-6", + name: "Opus 4.6", + isCustom: false, + capabilities: createModelCapabilities({ + optionDescriptors: [], + }), + }, + ], } satisfies ServerProvider; - const changes = yield* PubSub.unbounded(); - const instance = { - instanceId: cursorInstanceId, - driverKind: cursorDriver, - continuationIdentity: { - driverKind: cursorDriver, - continuationKey: "cursor:instance:cursor", + + assert.deepStrictEqual(mergeProviderSnapshot(previousProvider, refreshedProvider).models, [ + ...previousProvider.models, + ]); + }); + + it("persists merged provider snapshots for the providers that were refreshed", () => { + const previousProviders = [ + { + instanceId: ProviderInstanceId.make("cursor"), + driver: ProviderDriverKind.make("cursor"), + status: "ready", + enabled: true, + installed: true, + auth: { status: "authenticated" }, + checkedAt: "2026-04-14T00:00:00.000Z", + version: "2026.04.09-f2b0fcd", + models: [ + { + slug: "claude-opus-4-6", + name: "Opus 4.6", + isCustom: false, + capabilities: createModelCapabilities({ + optionDescriptors: [ + selectDescriptor("reasoning", "Reasoning", [ + { id: "high", label: "High", isDefault: true }, + ]), + booleanDescriptor("fastMode", "Fast Mode"), + booleanDescriptor("thinking", "Thinking"), + ], + }), + }, + ], + slashCommands: [], + skills: [], }, - displayName: undefined, - enabled: true, - snapshot: { - maintenanceCapabilities: makeManualOnlyProviderMaintenanceCapabilities({ - provider: cursorDriver, - packageName: null, - }), - getSnapshot: Effect.succeed(initialProvider), - refresh: Effect.succeed(refreshedProvider), - streamChanges: Stream.fromPubSub(changes), + { + instanceId: ProviderInstanceId.make("codex"), + driver: ProviderDriverKind.make("codex"), + status: "ready", + enabled: true, + installed: true, + auth: { status: "authenticated" }, + checkedAt: "2026-04-14T00:00:00.000Z", + version: "1.0.0", + models: [], + slashCommands: [], + skills: [], }, - adapter: {} as ProviderInstance["adapter"], - textGeneration: {} as ProviderInstance["textGeneration"], - } satisfies ProviderInstance; - const instanceRegistryLayer = Layer.succeed(ProviderInstanceRegistry, { - getInstance: (instanceId) => - Effect.succeed(instanceId === cursorInstanceId ? instance : undefined), - listInstances: Effect.succeed([instance]), - listUnavailable: Effect.succeed([]), - streamChanges: Stream.empty, - subscribeChanges: Effect.flatMap(PubSub.unbounded(), (pubsub) => - PubSub.subscribe(pubsub), - ), - }); - const scope = yield* Scope.make(); - yield* Effect.addFinalizer(() => Scope.close(scope, Exit.void)); - const runtimeServices = yield* Layer.build( - ProviderRegistryLive.pipe( - Layer.provideMerge(instanceRegistryLayer), - Layer.provideMerge( - ServerConfig.layerTest(process.cwd(), { - prefix: "t3-provider-registry-merged-persist-", - }), - ), - Layer.provideMerge(NodeServices.layer), - ), - ).pipe(Scope.provide(scope)); + ] as const satisfies ReadonlyArray; + const refreshedCursor = { + ...previousProviders[0], + checkedAt: "2026-04-14T00:01:00.000Z", + models: [], + } satisfies ServerProvider; + + const mergedProviders = mergeProviderSnapshots(previousProviders, [refreshedCursor]); + const persistedProviders = selectProvidersByKind( + mergedProviders, + new Set([ProviderDriverKind.make("cursor")]), + ); + + assert.deepStrictEqual(persistedProviders, [ + { + ...refreshedCursor, + models: [...previousProviders[0].models], + }, + ]); + }); - yield* Effect.gen(function* () { - const registry = yield* ProviderRegistry; - const config = yield* ServerConfig; - const filePath = yield* resolveProviderStatusCachePath({ - cacheDir: config.providerStatusCacheDir, + it.effect("persists the merged snapshot when a live update has empty models", () => + Effect.gen(function* () { + const cursorDriver = ProviderDriverKind.make("cursor"); + const cursorInstanceId = ProviderInstanceId.make("cursor"); + const initialProvider = { + instanceId: cursorInstanceId, + driver: cursorDriver, + status: "ready", + enabled: true, + installed: true, + auth: { status: "authenticated" }, + checkedAt: "2026-04-14T00:00:00.000Z", + version: "2026.04.09-f2b0fcd", + models: [ + { + slug: "claude-opus-4-6", + name: "Opus 4.6", + isCustom: false, + capabilities: createModelCapabilities({ + optionDescriptors: [ + selectDescriptor("reasoning", "Reasoning", [ + { id: "high", label: "High", isDefault: true }, + ]), + ], + }), + }, + ], + slashCommands: [], + skills: [], + } as const satisfies ServerProvider; + const refreshedProvider = { + ...initialProvider, + checkedAt: "2026-04-14T00:01:00.000Z", + models: [], + } satisfies ServerProvider; + const changes = yield* PubSub.unbounded(); + const instance = { instanceId: cursorInstanceId, + driverKind: cursorDriver, + continuationIdentity: { + driverKind: cursorDriver, + continuationKey: "cursor:instance:cursor", + }, + displayName: undefined, + enabled: true, + snapshot: { + maintenanceCapabilities: makeManualOnlyProviderMaintenanceCapabilities({ + provider: cursorDriver, + packageName: null, + }), + getSnapshot: Effect.succeed(initialProvider), + refresh: Effect.succeed(refreshedProvider), + streamChanges: Stream.fromPubSub(changes), + }, + adapter: {} as ProviderInstance["adapter"], + textGeneration: {} as ProviderInstance["textGeneration"], + } satisfies ProviderInstance; + const instanceRegistryLayer = Layer.succeed(ProviderInstanceRegistry, { + getInstance: (instanceId) => + Effect.succeed(instanceId === cursorInstanceId ? instance : undefined), + listInstances: Effect.succeed([instance]), + listUnavailable: Effect.succeed([]), + streamChanges: Stream.empty, + subscribeChanges: Effect.flatMap(PubSub.unbounded(), (pubsub) => + PubSub.subscribe(pubsub), + ), }); + const scope = yield* Scope.make(); + yield* Effect.addFinalizer(() => Scope.close(scope, Exit.void)); + const runtimeServices = yield* Layer.build( + ProviderRegistryLive.pipe( + Layer.provideMerge(instanceRegistryLayer), + Layer.provideMerge( + ServerConfig.layerTest(process.cwd(), { + prefix: "t3-provider-registry-merged-persist-", + }), + ), + Layer.provideMerge(NodeServices.layer), + ), + ).pipe(Scope.provide(scope)); + + yield* Effect.gen(function* () { + const registry = yield* ProviderRegistry; + const config = yield* ServerConfig; + const filePath = yield* resolveProviderStatusCachePath({ + cacheDir: config.providerStatusCacheDir, + instanceId: cursorInstanceId, + }); + + assert.deepStrictEqual((yield* registry.getProviders)[0]?.models, [ + ...initialProvider.models, + ]); + yield* PubSub.publish(changes, refreshedProvider); + + let cachedProvider = yield* readProviderStatusCache(filePath); + for ( + let attempt = 0; + attempt < 50 && cachedProvider?.checkedAt !== refreshedProvider.checkedAt; + attempt += 1 + ) { + yield* TestClock.adjust("10 millis"); + yield* Effect.yieldNow; + cachedProvider = yield* readProviderStatusCache(filePath); + } - assert.deepStrictEqual((yield* registry.getProviders)[0]?.models, [ - ...initialProvider.models, - ]); - yield* PubSub.publish(changes, refreshedProvider); - - let cachedProvider = yield* readProviderStatusCache(filePath); - for ( - let attempt = 0; - attempt < 50 && cachedProvider?.checkedAt !== refreshedProvider.checkedAt; - attempt += 1 - ) { - yield* TestClock.adjust("10 millis"); - yield* Effect.yieldNow; - cachedProvider = yield* readProviderStatusCache(filePath); - } - - assert.deepStrictEqual(cachedProvider, { - ...refreshedProvider, - models: [...initialProvider.models], - }); - }).pipe(Effect.provide(runtimeServices)); - }), - ); + assert.deepStrictEqual(cachedProvider, { + ...refreshedProvider, + models: [...initialProvider.models], + }); + }).pipe(Effect.provide(runtimeServices)); + }), + ); - it.effect("returns the cached provider list when a manual refresh fails", () => - Effect.gen(function* () { - const codexDriver = ProviderDriverKind.make("codex"); - const codexInstanceId = ProviderInstanceId.make("codex"); - const cachedProvider = { - instanceId: codexInstanceId, - driver: codexDriver, - status: "ready", - enabled: true, - installed: true, - auth: { status: "authenticated" }, - checkedAt: "2026-04-29T10:00:00.000Z", - version: "1.0.0", - models: [], - slashCommands: [], - skills: [], - } as const satisfies ServerProvider; - const instance = { - instanceId: codexInstanceId, - driverKind: codexDriver, - continuationIdentity: { + it.effect("returns the cached provider list when a manual refresh fails", () => + Effect.gen(function* () { + const codexDriver = ProviderDriverKind.make("codex"); + const codexInstanceId = ProviderInstanceId.make("codex"); + const cachedProvider = { + instanceId: codexInstanceId, + driver: codexDriver, + status: "ready", + enabled: true, + installed: true, + auth: { status: "authenticated" }, + checkedAt: "2026-04-29T10:00:00.000Z", + version: "1.0.0", + models: [], + slashCommands: [], + skills: [], + } as const satisfies ServerProvider; + const instance = { + instanceId: codexInstanceId, driverKind: codexDriver, - continuationKey: "codex:instance:codex", - }, - displayName: undefined, - enabled: true, - snapshot: { - maintenanceCapabilities: makeManualOnlyProviderMaintenanceCapabilities({ - provider: codexDriver, - packageName: null, - }), - getSnapshot: Effect.succeed(cachedProvider), - refresh: Effect.die(new Error("simulated refresh failure")), - streamChanges: Stream.empty, - }, - adapter: {} as ProviderInstance["adapter"], - textGeneration: {} as ProviderInstance["textGeneration"], - } satisfies ProviderInstance; - const instanceRegistryLayer = Layer.succeed(ProviderInstanceRegistry, { - getInstance: (instanceId) => - Effect.succeed(instanceId === codexInstanceId ? instance : undefined), - listInstances: Effect.succeed([instance]), - listUnavailable: Effect.succeed([]), - streamChanges: Stream.empty, - subscribeChanges: Effect.flatMap(PubSub.unbounded(), (pubsub) => - PubSub.subscribe(pubsub), - ), - }); - const scope = yield* Scope.make(); - yield* Effect.addFinalizer(() => Scope.close(scope, Exit.void)); - const runtimeServices = yield* Layer.build( - ProviderRegistryLive.pipe( - Layer.provideMerge(instanceRegistryLayer), - Layer.provideMerge( - ServerConfig.layerTest(process.cwd(), { - prefix: "t3-provider-registry-refresh-failure-", + continuationIdentity: { + driverKind: codexDriver, + continuationKey: "codex:instance:codex", + }, + displayName: undefined, + enabled: true, + snapshot: { + maintenanceCapabilities: makeManualOnlyProviderMaintenanceCapabilities({ + provider: codexDriver, + packageName: null, }), + getSnapshot: Effect.succeed(cachedProvider), + refresh: Effect.die(new Error("simulated refresh failure")), + streamChanges: Stream.empty, + }, + adapter: {} as ProviderInstance["adapter"], + textGeneration: {} as ProviderInstance["textGeneration"], + } satisfies ProviderInstance; + const instanceRegistryLayer = Layer.succeed(ProviderInstanceRegistry, { + getInstance: (instanceId) => + Effect.succeed(instanceId === codexInstanceId ? instance : undefined), + listInstances: Effect.succeed([instance]), + listUnavailable: Effect.succeed([]), + streamChanges: Stream.empty, + subscribeChanges: Effect.flatMap(PubSub.unbounded(), (pubsub) => + PubSub.subscribe(pubsub), ), - Layer.provideMerge(NodeServices.layer), - ), - ).pipe(Scope.provide(scope)); + }); + const scope = yield* Scope.make(); + yield* Effect.addFinalizer(() => Scope.close(scope, Exit.void)); + const runtimeServices = yield* Layer.build( + ProviderRegistryLive.pipe( + Layer.provideMerge(instanceRegistryLayer), + Layer.provideMerge( + ServerConfig.layerTest(process.cwd(), { + prefix: "t3-provider-registry-refresh-failure-", + }), + ), + Layer.provideMerge(NodeServices.layer), + ), + ).pipe(Scope.provide(scope)); - yield* Effect.gen(function* () { - const registry = yield* ProviderRegistry; + yield* Effect.gen(function* () { + const registry = yield* ProviderRegistry; - assert.deepStrictEqual(yield* registry.getProviders, [cachedProvider]); - assert.deepStrictEqual(yield* registry.refresh(codexDriver), [cachedProvider]); - assert.deepStrictEqual(yield* registry.refreshInstance(codexInstanceId), [ - cachedProvider, - ]); - }).pipe(Effect.provide(runtimeServices)); - }), - ); + assert.deepStrictEqual(yield* registry.getProviders, [cachedProvider]); + assert.deepStrictEqual(yield* registry.refresh(codexDriver), [cachedProvider]); + assert.deepStrictEqual(yield* registry.refreshInstance(codexInstanceId), [ + cachedProvider, + ]); + }).pipe(Effect.provide(runtimeServices)); + }), + ); - it.effect("keeps consuming registry changes after one sync fails", () => - Effect.gen(function* () { - const codexDriver = ProviderDriverKind.make("codex"); - const codexInstanceId = ProviderInstanceId.make("codex"); - const claudeDriver = ProviderDriverKind.make("claudeAgent"); - const claudeInstanceId = ProviderInstanceId.make("claudeAgent"); - const codexProvider = { - instanceId: codexInstanceId, - driver: codexDriver, - status: "ready", - enabled: true, - installed: true, - auth: { status: "authenticated" }, - checkedAt: "2026-04-29T10:00:00.000Z", - version: "1.0.0", - models: [], - slashCommands: [], - skills: [], - } as const satisfies ServerProvider; - const claudeProvider = { - instanceId: claudeInstanceId, - driver: claudeDriver, - status: "ready", - enabled: true, - installed: true, - auth: { status: "authenticated" }, - checkedAt: "2026-04-29T10:01:00.000Z", - version: "1.0.0", - models: [], - slashCommands: [], - skills: [], - } as const satisfies ServerProvider; - const makeInstance = (provider: ServerProvider): ProviderInstance => ({ - instanceId: provider.instanceId, - driverKind: provider.driver, - continuationIdentity: { + it.effect("keeps consuming registry changes after one sync fails", () => + Effect.gen(function* () { + const codexDriver = ProviderDriverKind.make("codex"); + const codexInstanceId = ProviderInstanceId.make("codex"); + const claudeDriver = ProviderDriverKind.make("claudeAgent"); + const claudeInstanceId = ProviderInstanceId.make("claudeAgent"); + const codexProvider = { + instanceId: codexInstanceId, + driver: codexDriver, + status: "ready", + enabled: true, + installed: true, + auth: { status: "authenticated" }, + checkedAt: "2026-04-29T10:00:00.000Z", + version: "1.0.0", + models: [], + slashCommands: [], + skills: [], + } as const satisfies ServerProvider; + const claudeProvider = { + instanceId: claudeInstanceId, + driver: claudeDriver, + status: "ready", + enabled: true, + installed: true, + auth: { status: "authenticated" }, + checkedAt: "2026-04-29T10:01:00.000Z", + version: "1.0.0", + models: [], + slashCommands: [], + skills: [], + } as const satisfies ServerProvider; + const makeInstance = (provider: ServerProvider): ProviderInstance => ({ + instanceId: provider.instanceId, driverKind: provider.driver, - continuationKey: `${provider.driver}:instance:${provider.instanceId}`, - }, - displayName: undefined, - enabled: true, - snapshot: { - maintenanceCapabilities: makeManualOnlyProviderMaintenanceCapabilities({ - provider: provider.driver, - packageName: null, + continuationIdentity: { + driverKind: provider.driver, + continuationKey: `${provider.driver}:instance:${provider.instanceId}`, + }, + displayName: undefined, + enabled: true, + snapshot: { + maintenanceCapabilities: makeManualOnlyProviderMaintenanceCapabilities({ + provider: provider.driver, + packageName: null, + }), + getSnapshot: Effect.succeed(provider), + refresh: Effect.succeed(provider), + streamChanges: Stream.empty, + }, + adapter: {} as ProviderInstance["adapter"], + textGeneration: {} as ProviderInstance["textGeneration"], + }); + const codexInstance = makeInstance(codexProvider); + const claudeInstance = makeInstance(claudeProvider); + const changes = yield* PubSub.unbounded(); + const instancesRef = yield* Ref.make>([codexInstance]); + const failNextList = yield* Ref.make(false); + const wait = () => Effect.yieldNow; + const instanceRegistryLayer = Layer.succeed(ProviderInstanceRegistry, { + getInstance: (instanceId) => + Ref.get(instancesRef).pipe( + Effect.map((instances) => + instances.find((instance) => instance.instanceId === instanceId), + ), + ), + listInstances: Effect.gen(function* () { + const shouldFail = yield* Ref.get(failNextList); + if (shouldFail) { + yield* Ref.set(failNextList, false); + return yield* Effect.die(new Error("simulated registry list failure")); + } + return yield* Ref.get(instancesRef); }), - getSnapshot: Effect.succeed(provider), - refresh: Effect.succeed(provider), - streamChanges: Stream.empty, - }, - adapter: {} as ProviderInstance["adapter"], - textGeneration: {} as ProviderInstance["textGeneration"], - }); - const codexInstance = makeInstance(codexProvider); - const claudeInstance = makeInstance(claudeProvider); - const changes = yield* PubSub.unbounded(); - const instancesRef = yield* Ref.make>([codexInstance]); - const failNextList = yield* Ref.make(false); - const wait = () => Effect.yieldNow; - const instanceRegistryLayer = Layer.succeed(ProviderInstanceRegistry, { - getInstance: (instanceId) => - Ref.get(instancesRef).pipe( - Effect.map((instances) => - instances.find((instance) => instance.instanceId === instanceId), + listUnavailable: Effect.succeed([]), + streamChanges: Stream.fromPubSub(changes), + subscribeChanges: PubSub.subscribe(changes), + }); + const scope = yield* Scope.make(); + yield* Effect.addFinalizer(() => Scope.close(scope, Exit.void)); + const runtimeServices = yield* Layer.build( + ProviderRegistryLive.pipe( + Layer.provideMerge(instanceRegistryLayer), + Layer.provideMerge( + ServerConfig.layerTest(process.cwd(), { + prefix: "t3-provider-registry-sync-failure-", + }), ), + Layer.provideMerge(NodeServices.layer), ), - listInstances: Effect.gen(function* () { - const shouldFail = yield* Ref.get(failNextList); - if (shouldFail) { - yield* Ref.set(failNextList, false); - return yield* Effect.die(new Error("simulated registry list failure")); + ).pipe(Scope.provide(scope)); + + yield* Effect.gen(function* () { + const registry = yield* ProviderRegistry; + assert.deepStrictEqual(yield* registry.getProviders, [codexProvider]); + + yield* Ref.set(failNextList, true); + yield* PubSub.publish(changes, undefined); + + yield* Ref.set(instancesRef, [codexInstance, claudeInstance]); + yield* PubSub.publish(changes, undefined); + + let providers = yield* registry.getProviders; + for ( + let attempt = 0; + attempt < 50 && + !providers.some((provider) => provider.instanceId === claudeInstanceId); + attempt += 1 + ) { + yield* wait(); + providers = yield* registry.getProviders; } - return yield* Ref.get(instancesRef); - }), - listUnavailable: Effect.succeed([]), - streamChanges: Stream.fromPubSub(changes), - subscribeChanges: PubSub.subscribe(changes), - }); - const scope = yield* Scope.make(); - yield* Effect.addFinalizer(() => Scope.close(scope, Exit.void)); - const runtimeServices = yield* Layer.build( - ProviderRegistryLive.pipe( - Layer.provideMerge(instanceRegistryLayer), + + assert.deepStrictEqual( + providers.map((provider) => provider.instanceId).toSorted(), + [codexInstanceId, claudeInstanceId].toSorted(), + ); + }).pipe(Effect.provide(runtimeServices)); + }), + ); + + // This test intentionally avoids `mockCommandSpawnerLayer` so the real + // `probeCodexAppServerProvider` path runs — including the full + // `codex app-server` RPC handshake via `CodexClient.layerCommand`. + // We point `binaryPath` at a name that cannot exist on any machine so + // the real `ChildProcessSpawner` deterministically returns ENOENT; the + // probe wraps that as `CodexAppServerSpawnError` and + // `checkCodexProviderStatus` turns it into the user-visible "not + // installed" error snapshot. If the aggregator's `syncLiveSources` + // breaks — the `codex_personal`-never-probes bug we are guarding + // against — that snapshot never lands in `getProviders` and the + // assertions below fail. + it.effect("propagates real Codex probe failures to the aggregator at boot", () => + Effect.gen(function* () { + const missingBinary = `t3code_codex_missing_`; + const serverSettings = yield* makeMutableServerSettingsService( + decodeServerSettings( + deepMerge(encodedDefaultServerSettings, { + providers: { + // Disable every built-in probe that would otherwise spawn + // on the CI host. `enabled: false` short-circuits each + // driver's probe *before* it touches the spawner, so the + // test environment stays isolated from the dev + // machine's PATH. + codex: { enabled: false }, + claudeAgent: { enabled: false }, + cursor: { enabled: false }, + grok: { enabled: false }, + opencode: { enabled: false }, + }, + // `providerInstances` keys are branded `ProviderInstanceId`; + // the branded index signature rejects plain string literals + // at the TS level even though the runtime schema happily + // accepts + decodes them. Cast the patch to `unknown` so + // the `Schema.decodeSync` below does the real validation. + providerInstances: { + // Matches the shape the user had in `.t3/dev/settings.json` + // when the bug was reported: a custom enabled Codex instance + // pointing at a binary the server has to actually spawn. + codex_personal: { + driver: "codex", + displayName: "Codex Personal", + enabled: true, + config: { + binaryPath: missingBinary, + homePath: `/tmp/${missingBinary}_home`, + }, + }, + } as unknown as ContractServerSettings["providerInstances"], + }), + ), + ); + const scope = yield* Scope.make(); + yield* Effect.addFinalizer(() => Scope.close(scope, Exit.void)); + const providerRegistryLayer = ProviderRegistryLive.pipe( + Layer.provideMerge(ProviderInstanceRegistryHydrationLive), + Layer.provideMerge(NoOpThreadMcpToggleRepository), + Layer.provideMerge(Layer.succeed(ServerSettingsService, serverSettings)), Layer.provideMerge( ServerConfig.layerTest(process.cwd(), { - prefix: "t3-provider-registry-sync-failure-", + prefix: "t3-provider-registry-", }), ), - Layer.provideMerge(NodeServices.layer), - ), - ).pipe(Scope.provide(scope)); - - yield* Effect.gen(function* () { - const registry = yield* ProviderRegistry; - assert.deepStrictEqual(yield* registry.getProviders, [codexProvider]); - - yield* Ref.set(failNextList, true); - yield* PubSub.publish(changes, undefined); - - yield* Ref.set(instancesRef, [codexInstance, claudeInstance]); - yield* PubSub.publish(changes, undefined); + Layer.provideMerge(TestHttpClientLive), + Layer.provideMerge(Layer.succeed(ProviderEventLoggers, NoOpProviderEventLoggers)), + Layer.provideMerge(OpenCodeRuntimeLive), + // NO spawner mock — `ChildProcessSpawner` is supplied by the + // outer `NodeServices.layer` on `it.layer(...)` and will + // genuinely spawn a subprocess. The missing-binary ENOENT is + // what exercises the same failure mode as a misconfigured + // production `binaryPath`. + ); + const runtimeServices = yield* Layer.build(providerRegistryLayer).pipe( + Scope.provide(scope), + ); - let providers = yield* registry.getProviders; - for ( - let attempt = 0; - attempt < 50 && !providers.some((provider) => provider.instanceId === claudeInstanceId); - attempt += 1 - ) { - yield* wait(); - providers = yield* registry.getProviders; - } + yield* Effect.gen(function* () { + const registry = yield* ProviderRegistry; + const providers = yield* registry.getProviders; + const codexPersonal = providers.find( + (provider) => provider.instanceId === "codex_personal", + ); + assert.notStrictEqual( + codexPersonal, + undefined, + `Expected the aggregator to know about codex_personal; instead saw: ${providers + .map((provider) => provider.instanceId) + .join(", ")}`, + ); + assert.strictEqual( + codexPersonal?.status, + "error", + "Real Codex probe against a missing binary should surface as 'error' in the aggregator", + ); + assert.strictEqual(codexPersonal?.installed, false); + assert.strictEqual( + codexPersonal?.message, + "Codex CLI (`codex`) is not installed or not on PATH.", + ); + }).pipe(Effect.provide(runtimeServices)); + }), + ); - assert.deepStrictEqual( - providers.map((provider) => provider.instanceId).toSorted(), - [codexInstanceId, claudeInstanceId].toSorted(), + // Guards the second half of the reported bug: changing + // `providers.codex.binaryPath` in settings must tear down the live + // instance and rebuild it so a fresh probe runs with the new binary. + // This test drives the real settings stream → registry reconcile → + // aggregator sync pipeline and asserts that `getProviders` reflects + // the new probe's outcome. If `syncLiveSources` stops awaiting the + // rebuilt instance's refresh (previous bug mode), the aggregator + // keeps the old snapshot and this test fails. + // + it.effect("re-probes when settings change the codex binaryPath", () => + Effect.gen(function* () { + const firstMissing = `t3code_codex_first_`; + const secondMissing = `t3code_codex_second_`; + const serverSettings = yield* makeMutableServerSettingsService( + decodeServerSettings( + deepMerge(encodedDefaultServerSettings, { + providers: { + codex: { enabled: true, binaryPath: firstMissing }, + claudeAgent: { enabled: false }, + cursor: { enabled: false }, + grok: { enabled: false }, + opencode: { enabled: false }, + }, + }), + ), ); - }).pipe(Effect.provide(runtimeServices)); - }), - ); - - // This test intentionally avoids `mockCommandSpawnerLayer` so the real - // `probeCodexAppServerProvider` path runs — including the full - // `codex app-server` RPC handshake via `CodexClient.layerCommand`. - // We point `binaryPath` at a name that cannot exist on any machine so - // the real `ChildProcessSpawner` deterministically returns ENOENT; the - // probe wraps that as `CodexAppServerSpawnError` and - // `checkCodexProviderStatus` turns it into the user-visible "not - // installed" error snapshot. If the aggregator's `syncLiveSources` - // breaks — the `codex_personal`-never-probes bug we are guarding - // against — that snapshot never lands in `getProviders` and the - // assertions below fail. - it.effect("propagates real Codex probe failures to the aggregator at boot", () => - Effect.gen(function* () { - const missingBinary = `t3code_codex_missing_`; - const serverSettings = yield* makeMutableServerSettingsService( - decodeServerSettings( - deepMerge(encodedDefaultServerSettings, { + const scope = yield* Scope.make(); + yield* Effect.addFinalizer(() => Scope.close(scope, Exit.void)); + const providerRegistryLayer = ProviderRegistryLive.pipe( + Layer.provideMerge(ProviderInstanceRegistryHydrationLive), + Layer.provideMerge(NoOpThreadMcpToggleRepository), + Layer.provideMerge(Layer.succeed(ServerSettingsService, serverSettings)), + Layer.provideMerge( + ServerConfig.layerTest(process.cwd(), { + prefix: "t3-provider-registry-", + }), + ), + Layer.provideMerge(TestHttpClientLive), + Layer.provideMerge(Layer.succeed(ProviderEventLoggers, NoOpProviderEventLoggers)), + Layer.provideMerge(OpenCodeRuntimeLive), + // `it.live` does not inherit layers from the outer `it.layer` + // wrapper, so provide `NodeServices.layer` inline. This is the + // same real `ChildProcessSpawner` + `FileSystem` + `Path` + // services that production uses. + Layer.provideMerge(NodeServices.layer), + ); + const runtimeServices = yield* Layer.build(providerRegistryLayer).pipe( + Scope.provide(scope), + ); + + yield* Effect.gen(function* () { + const registry = yield* ProviderRegistry; + // Boot-time probe: the default codex instance is enabled with + // `firstMissing`, so the real spawner yields ENOENT and the + // snapshot should be `status: "error"`. What *distinguishes* + // the two probe runs is `checkedAt` — each probe stamps a + // fresh DateTime, so we capture it and assert it advances + // after the settings mutation. + const initialProviders = yield* registry.getProviders; + const initialCodex = initialProviders.find( + (provider) => provider.instanceId === "codex", + ); + assert.strictEqual(initialCodex?.status, "error"); + assert.strictEqual(initialCodex?.installed, false); + const initialCheckedAt = initialCodex?.checkedAt; + assert.notStrictEqual(initialCheckedAt, undefined); + + // The rebuilt instance may re-probe synchronously during the + // settings update. Advance the TestClock first so `checkedAt` + // can safely act as the fresh-probe marker this assertion uses. + yield* TestClock.adjust("1 second"); + + // Drive a settings change. The Hydration layer's + // `SettingsWatcherLive` consumes this via `streamChanges`, + // calls `reconcile`, which rebuilds the codex instance (the + // envelope changed because `binaryPath` differs → `entryEqual` + // is false). The registry's `Stream.runForEach( + // instanceRegistry.streamChanges, () => syncLiveSources)` + // fires `syncLiveSources`, which subscribes + awaits a fresh + // refresh on the rebuilt instance. + yield* serverSettings.updateSettings({ providers: { - // Disable every built-in probe that would otherwise spawn - // on the CI host. `enabled: false` short-circuits each - // driver's probe *before* it touches the spawner, so the - // test environment stays isolated from the dev - // machine's PATH. - codex: { enabled: false }, - claudeAgent: { enabled: false }, - cursor: { enabled: false }, - opencode: { enabled: false }, + codex: { enabled: true, binaryPath: secondMissing }, }, - // `providerInstances` keys are branded `ProviderInstanceId`; - // the branded index signature rejects plain string literals - // at the TS level even though the runtime schema happily - // accepts + decodes them. Cast the patch to `unknown` so - // the `Schema.decodeSync` below does the real validation. - providerInstances: { - // Matches the shape the user had in `.t3/dev/settings.json` - // when the bug was reported: a custom enabled Codex instance - // pointing at a binary the server has to actually spawn. - codex_personal: { - driver: "codex", - displayName: "Codex Personal", - enabled: true, - config: { - binaryPath: missingBinary, - homePath: `/tmp/${missingBinary}_home`, - }, - }, - } as unknown as ContractServerSettings["providerInstances"], - }), - ), - ); - const scope = yield* Scope.make(); - yield* Effect.addFinalizer(() => Scope.close(scope, Exit.void)); - const providerRegistryLayer = ProviderRegistryLive.pipe( - Layer.provideMerge(ProviderInstanceRegistryHydrationLive), - Layer.provideMerge(Layer.succeed(ServerSettingsService, serverSettings)), - Layer.provideMerge( - ServerConfig.layerTest(process.cwd(), { - prefix: "t3-provider-registry-", - }), - ), - Layer.provideMerge(TestHttpClientLive), - Layer.provideMerge(Layer.succeed(ProviderEventLoggers, NoOpProviderEventLoggers)), - Layer.provideMerge(OpenCodeRuntimeLive), - // NO spawner mock — `ChildProcessSpawner` is supplied by the - // outer `NodeServices.layer` on `it.layer(...)` and will - // genuinely spawn a subprocess. The missing-binary ENOENT is - // what exercises the same failure mode as a misconfigured - // production `binaryPath`. - ); - const runtimeServices = yield* Layer.build(providerRegistryLayer).pipe( - Scope.provide(scope), - ); + }); + + // Poll with TestClock until `checkedAt` advances or we hit a + // generous virtual 3-second ceiling. + const refreshed = yield* Effect.gen(function* () { + for (let attempts = 0; attempts < 60; attempts += 1) { + const providers = yield* registry.getProviders; + const codex = providers.find((provider) => provider.instanceId === "codex"); + if (codex !== undefined && codex.checkedAt !== initialCheckedAt) { + return providers; + } + yield* TestClock.adjust("50 millis"); + yield* Effect.yieldNow; + } + return yield* registry.getProviders; + }); + + const reprobedCodex = refreshed.find((provider) => provider.instanceId === "codex"); + assert.notStrictEqual( + reprobedCodex?.checkedAt, + initialCheckedAt, + "Expected a fresh probe after settings change, got the stale snapshot", + ); + assert.strictEqual(reprobedCodex?.status, "error"); + assert.strictEqual(reprobedCodex?.installed, false); + }).pipe(Effect.provide(runtimeServices)); + }), + ); - yield* Effect.gen(function* () { - const registry = yield* ProviderRegistry; - const providers = yield* registry.getProviders; - const codexPersonal = providers.find( - (provider) => provider.instanceId === "codex_personal", - ); - assert.notStrictEqual( - codexPersonal, - undefined, - `Expected the aggregator to know about codex_personal; instead saw: ${providers - .map((provider) => provider.instanceId) - .join(", ")}`, + it.effect("includes unavailable instance snapshots in getProviders", () => + Effect.gen(function* () { + const serverSettings = yield* makeMutableServerSettingsService( + decodeServerSettings( + deepMerge(encodedDefaultServerSettings, { + providers: { + codex: { enabled: false }, + claudeAgent: { enabled: false }, + cursor: { enabled: false }, + grok: { enabled: false }, + opencode: { enabled: false }, + }, + providerInstances: { + ghost_main: { + driver: "ghostDriver", + displayName: "A fork-only driver we don't ship", + enabled: false, + config: { arbitrary: "payload" }, + }, + } as unknown as ContractServerSettings["providerInstances"], + }), + ), ); - assert.strictEqual( - codexPersonal?.status, - "error", - "Real Codex probe against a missing binary should surface as 'error' in the aggregator", + const scope = yield* Scope.make(); + yield* Effect.addFinalizer(() => Scope.close(scope, Exit.void)); + const providerRegistryLayer = ProviderRegistryLive.pipe( + Layer.provideMerge(ProviderInstanceRegistryHydrationLive), + Layer.provideMerge(NoOpThreadMcpToggleRepository), + Layer.provideMerge(Layer.succeed(ServerSettingsService, serverSettings)), + Layer.provideMerge( + ServerConfig.layerTest(process.cwd(), { + prefix: "t3-provider-registry-", + }), + ), + Layer.provideMerge(TestHttpClientLive), + Layer.provideMerge(Layer.succeed(ProviderEventLoggers, NoOpProviderEventLoggers)), + Layer.provideMerge(OpenCodeRuntimeLive), + Layer.provideMerge(NodeServices.layer), ); - assert.strictEqual(codexPersonal?.installed, false); - assert.strictEqual( - codexPersonal?.message, - "Codex CLI (`codex`) is not installed or not on PATH.", + const runtimeServices = yield* Layer.build(providerRegistryLayer).pipe( + Scope.provide(scope), ); - }).pipe(Effect.provide(runtimeServices)); - }), - ); - - // Guards the second half of the reported bug: changing - // `providers.codex.binaryPath` in settings must tear down the live - // instance and rebuild it so a fresh probe runs with the new binary. - // This test drives the real settings stream → registry reconcile → - // aggregator sync pipeline and asserts that `getProviders` reflects - // the new probe's outcome. If `syncLiveSources` stops awaiting the - // rebuilt instance's refresh (previous bug mode), the aggregator - // keeps the old snapshot and this test fails. - // - it.effect("re-probes when settings change the codex binaryPath", () => - Effect.gen(function* () { - const firstMissing = `t3code_codex_first_`; - const secondMissing = `t3code_codex_second_`; - const serverSettings = yield* makeMutableServerSettingsService( - decodeServerSettings( - deepMerge(encodedDefaultServerSettings, { - providers: { - codex: { enabled: true, binaryPath: firstMissing }, - claudeAgent: { enabled: false }, - cursor: { enabled: false }, - opencode: { enabled: false }, - }, - }), - ), - ); - const scope = yield* Scope.make(); - yield* Effect.addFinalizer(() => Scope.close(scope, Exit.void)); - const providerRegistryLayer = ProviderRegistryLive.pipe( - Layer.provideMerge(ProviderInstanceRegistryHydrationLive), - Layer.provideMerge(Layer.succeed(ServerSettingsService, serverSettings)), - Layer.provideMerge( - ServerConfig.layerTest(process.cwd(), { - prefix: "t3-provider-registry-", - }), - ), - Layer.provideMerge(TestHttpClientLive), - Layer.provideMerge(Layer.succeed(ProviderEventLoggers, NoOpProviderEventLoggers)), - Layer.provideMerge(OpenCodeRuntimeLive), - // `it.live` does not inherit layers from the outer `it.layer` - // wrapper, so provide `NodeServices.layer` inline. This is the - // same real `ChildProcessSpawner` + `FileSystem` + `Path` - // services that production uses. - Layer.provideMerge(NodeServices.layer), - ); - const runtimeServices = yield* Layer.build(providerRegistryLayer).pipe( - Scope.provide(scope), - ); - yield* Effect.gen(function* () { - const registry = yield* ProviderRegistry; - // Boot-time probe: the default codex instance is enabled with - // `firstMissing`, so the real spawner yields ENOENT and the - // snapshot should be `status: "error"`. What *distinguishes* - // the two probe runs is `checkedAt` — each probe stamps a - // fresh DateTime, so we capture it and assert it advances - // after the settings mutation. - const initialProviders = yield* registry.getProviders; - const initialCodex = initialProviders.find((provider) => provider.instanceId === "codex"); - assert.strictEqual(initialCodex?.status, "error"); - assert.strictEqual(initialCodex?.installed, false); - const initialCheckedAt = initialCodex?.checkedAt; - assert.notStrictEqual(initialCheckedAt, undefined); - - // Drive a settings change. The Hydration layer's - // `SettingsWatcherLive` consumes this via `streamChanges`, - // calls `reconcile`, which rebuilds the codex instance (the - // envelope changed because `binaryPath` differs → `entryEqual` - // is false). The registry's `Stream.runForEach( - // instanceRegistry.streamChanges, () => syncLiveSources)` - // fires `syncLiveSources`, which subscribes + awaits a fresh - // refresh on the rebuilt instance. - yield* serverSettings.updateSettings({ - providers: { - codex: { enabled: true, binaryPath: secondMissing }, - }, - }); + yield* Effect.gen(function* () { + const registry = yield* ProviderRegistry; + const providers = yield* registry.getProviders; + const ghost = providers.find((provider) => provider.instanceId === "ghost_main"); - // Poll with TestClock until `checkedAt` advances or we hit a - // generous virtual 3-second ceiling. - const refreshed = yield* Effect.gen(function* () { - for (let attempts = 0; attempts < 60; attempts += 1) { - const providers = yield* registry.getProviders; - const codex = providers.find((provider) => provider.instanceId === "codex"); - if (codex !== undefined && codex.checkedAt !== initialCheckedAt) { - return providers; - } - yield* TestClock.adjust("50 millis"); - yield* Effect.yieldNow; - } - return yield* registry.getProviders; - }); + assert.notStrictEqual(ghost, undefined); + assert.strictEqual(ghost?.driver, "ghostDriver"); + assert.strictEqual(ghost?.availability, "unavailable"); + assert.match(ghost?.unavailableReason ?? "", /ghostDriver/); + }).pipe(Effect.provide(runtimeServices)); + }), + ); - const reprobedCodex = refreshed.find((provider) => provider.instanceId === "codex"); - assert.notStrictEqual( - reprobedCodex?.checkedAt, - initialCheckedAt, - "Expected a fresh probe after settings change, got the stale snapshot", - ); - assert.strictEqual(reprobedCodex?.status, "error"); - assert.strictEqual(reprobedCodex?.installed, false); - }).pipe(Effect.provide(runtimeServices)); - }), - ); + it.effect( + "keeps cursor disabled and skips probing when the provider setting is disabled", + () => + Effect.gen(function* () { + const serverSettings = yield* makeMutableServerSettingsService( + decodeServerSettings( + deepMerge(encodedDefaultServerSettings, { + providers: { + codex: { + enabled: false, + }, + cursor: { + enabled: false, + }, + grok: { + enabled: false, + }, + }, + }), + ), + ); + let cursorSpawned = false; + const scope = yield* Scope.make(); + yield* Effect.addFinalizer(() => Scope.close(scope, Exit.void)); + const providerRegistryLayer = ProviderRegistryLive.pipe( + Layer.provideMerge(ProviderInstanceRegistryHydrationLive), + Layer.provideMerge(NoOpThreadMcpToggleRepository), + Layer.provideMerge(Layer.succeed(ServerSettingsService, serverSettings)), + Layer.provideMerge( + ServerConfig.layerTest(process.cwd(), { + prefix: "t3-provider-registry-", + }), + ), + Layer.provideMerge(TestHttpClientLive), + Layer.provideMerge(Layer.succeed(ProviderEventLoggers, NoOpProviderEventLoggers)), + Layer.provideMerge(OpenCodeRuntimeLive), + Layer.provideMerge( + mockCommandSpawnerLayer((command, args) => { + if (command === "agent") { + cursorSpawned = true; + } + const joined = args.join(" "); + if (joined === "--version") { + return { + stdout: `${command} 1.0.0\n`, + stderr: "", + code: 0, + }; + } + if (joined === "auth status") { + return { + stdout: '{"authenticated":true}\n', + stderr: "", + code: 0, + }; + } + throw new Error(`Unexpected args: ${command} ${joined}`); + }), + ), + ); + const runtimeServices = yield* Layer.build( + Layer.mergeAll( + Layer.succeed(ServerSettingsService, serverSettings), + providerRegistryLayer, + ), + ).pipe(Scope.provide(scope)); - it.effect("includes unavailable instance snapshots in getProviders", () => - Effect.gen(function* () { - const serverSettings = yield* makeMutableServerSettingsService( - decodeServerSettings( - deepMerge(encodedDefaultServerSettings, { - providers: { - codex: { enabled: false }, - claudeAgent: { enabled: false }, - cursor: { enabled: false }, - opencode: { enabled: false }, - }, - providerInstances: { - ghost_main: { - driver: "ghostDriver", - displayName: "A fork-only driver we don't ship", - enabled: false, - config: { arbitrary: "payload" }, - }, - } as unknown as ContractServerSettings["providerInstances"], - }), - ), - ); - const scope = yield* Scope.make(); - yield* Effect.addFinalizer(() => Scope.close(scope, Exit.void)); - const providerRegistryLayer = ProviderRegistryLive.pipe( - Layer.provideMerge(ProviderInstanceRegistryHydrationLive), - Layer.provideMerge(Layer.succeed(ServerSettingsService, serverSettings)), - Layer.provideMerge( - ServerConfig.layerTest(process.cwd(), { - prefix: "t3-provider-registry-", - }), - ), - Layer.provideMerge(TestHttpClientLive), - Layer.provideMerge(Layer.succeed(ProviderEventLoggers, NoOpProviderEventLoggers)), - Layer.provideMerge(OpenCodeRuntimeLive), - Layer.provideMerge(NodeServices.layer), - ); - const runtimeServices = yield* Layer.build(providerRegistryLayer).pipe( - Scope.provide(scope), - ); + yield* Effect.gen(function* () { + const registry = yield* ProviderRegistry; + const providers = yield* registry.getProviders; + const cursorProvider = providers.find( + (provider) => provider.instanceId === ProviderInstanceId.make("cursor"), + ); + + assert.deepStrictEqual(providers.map((provider) => provider.instanceId).toSorted(), [ + "claudeAgent", + "codex", + "cursor", + "grok", + "opencode", + ]); + assert.strictEqual(cursorProvider?.enabled, false); + assert.strictEqual(cursorProvider?.status, "disabled"); + assert.strictEqual( + cursorProvider?.message, + "Cursor is disabled in T3 Code settings.", + ); + assert.strictEqual(cursorSpawned, false); + }).pipe(Effect.provide(runtimeServices)); + }), + ); - yield* Effect.gen(function* () { - const registry = yield* ProviderRegistry; - const providers = yield* registry.getProviders; - const ghost = providers.find((provider) => provider.instanceId === "ghost_main"); + it.effect("skips codex probes entirely when the provider is disabled", () => + Effect.gen(function* () { + const status = yield* checkCodexProviderStatus(disabledCodexSettings).pipe( + Effect.provide(failingSpawnerLayer("spawn codex ENOENT")), + ); + assert.strictEqual(status.enabled, false); + assert.strictEqual(status.status, "disabled"); + assert.strictEqual(status.installed, false); + assert.strictEqual(status.message, "Codex is disabled in T3 Code settings."); + }), + ); + }); - assert.notStrictEqual(ghost, undefined); - assert.strictEqual(ghost?.driver, "ghostDriver"); - assert.strictEqual(ghost?.availability, "unavailable"); - assert.match(ghost?.unavailableReason ?? "", /ghostDriver/); - }).pipe(Effect.provide(runtimeServices)); - }), - ); + // ── checkClaudeProviderStatus tests ────────────────────────── - it.effect("keeps cursor disabled and skips probing when the provider setting is disabled", () => - Effect.gen(function* () { - const serverSettings = yield* makeMutableServerSettingsService( - decodeServerSettings( - deepMerge(encodedDefaultServerSettings, { - providers: { - codex: { - enabled: false, - }, - cursor: { - enabled: false, - }, - }, - }), - ), - ); - let cursorSpawned = false; - const scope = yield* Scope.make(); - yield* Effect.addFinalizer(() => Scope.close(scope, Exit.void)); - const providerRegistryLayer = ProviderRegistryLive.pipe( - Layer.provideMerge(ProviderInstanceRegistryHydrationLive), - Layer.provideMerge(Layer.succeed(ServerSettingsService, serverSettings)), - Layer.provideMerge( - ServerConfig.layerTest(process.cwd(), { - prefix: "t3-provider-registry-", - }), - ), - Layer.provideMerge(TestHttpClientLive), - Layer.provideMerge(Layer.succeed(ProviderEventLoggers, NoOpProviderEventLoggers)), - Layer.provideMerge(OpenCodeRuntimeLive), - Layer.provideMerge( - mockCommandSpawnerLayer((command, args) => { - if (command === "agent") { - cursorSpawned = true; - } + describe("checkClaudeProviderStatus", () => { + it.effect("returns ready when claude is installed and authenticated", () => + Effect.gen(function* () { + const status = yield* checkClaudeProviderStatus( + defaultClaudeSettings, + claudeCapabilities(), + ); + assert.strictEqual(status.status, "ready"); + assert.strictEqual(status.installed, true); + assert.strictEqual(status.auth.status, "authenticated"); + }).pipe( + Effect.provide( + mockSpawnerLayer((args) => { const joined = args.join(" "); - if (joined === "--version") { + if (joined === "--version") return { stdout: "1.0.0\n", stderr: "", code: 0 }; + if (joined === "auth status") return { - stdout: `${command} 1.0.0\n`, + stdout: '{"loggedIn":true,"authMethod":"claude.ai"}\n', stderr: "", code: 0, }; - } - if (joined === "auth status") { + throw new Error(`Unexpected args: ${joined}`); + }), + ), + ), + ); + + it.effect("includes Claude Fable 5 on supported Claude Code versions", () => + Effect.gen(function* () { + const status = yield* checkClaudeProviderStatus( + defaultClaudeSettings, + claudeCapabilities(), + ); + const fable5 = status.models.find((model) => model.slug === "claude-fable-5"); + assert.strictEqual(fable5?.name, "Claude Fable 5"); + }).pipe( + Effect.provide( + mockSpawnerLayer((args) => { + const joined = args.join(" "); + if (joined === "--version") return { stdout: "2.1.169\n", stderr: "", code: 0 }; + if (joined === "auth status") return { - stdout: '{"authenticated":true}\n', + stdout: '{"loggedIn":true,"authMethod":"claude.ai"}\n', stderr: "", code: 0, }; - } - throw new Error(`Unexpected args: ${command} ${joined}`); + throw new Error(`Unexpected args: ${joined}`); }), ), - ); - const runtimeServices = yield* Layer.build( - Layer.mergeAll( - Layer.succeed(ServerSettingsService, serverSettings), - providerRegistryLayer, - ), - ).pipe(Scope.provide(scope)); - - yield* Effect.gen(function* () { - const registry = yield* ProviderRegistry; - const providers = yield* registry.getProviders; - const cursorProvider = providers.find( - (provider) => provider.instanceId === ProviderInstanceId.make("cursor"), - ); - - assert.deepStrictEqual(providers.map((provider) => provider.instanceId).toSorted(), [ - "claudeAgent", - "codex", - "cursor", - "opencode", - ]); - assert.strictEqual(cursorProvider?.enabled, false); - assert.strictEqual(cursorProvider?.status, "disabled"); - assert.strictEqual(cursorProvider?.message, "Cursor is disabled in T3 Code settings."); - assert.strictEqual(cursorSpawned, false); - }).pipe(Effect.provide(runtimeServices)); - }), - ); - - it.effect("skips codex probes entirely when the provider is disabled", () => - Effect.gen(function* () { - const status = yield* checkCodexProviderStatus(disabledCodexSettings).pipe( - Effect.provide(failingSpawnerLayer("spawn codex ENOENT")), - ); - assert.strictEqual(status.enabled, false); - assert.strictEqual(status.status, "disabled"); - assert.strictEqual(status.installed, false); - assert.strictEqual(status.message, "Codex is disabled in T3 Code settings."); - }), - ); - }); - - // ── checkClaudeProviderStatus tests ────────────────────────── - - describe("checkClaudeProviderStatus", () => { - it.effect("returns ready when claude is installed and authenticated", () => - Effect.gen(function* () { - const status = yield* checkClaudeProviderStatus( - defaultClaudeSettings, - claudeCapabilities(), - ); - assert.strictEqual(status.status, "ready"); - assert.strictEqual(status.installed, true); - assert.strictEqual(status.auth.status, "authenticated"); - }).pipe( - Effect.provide( - mockSpawnerLayer((args) => { - const joined = args.join(" "); - if (joined === "--version") return { stdout: "1.0.0\n", stderr: "", code: 0 }; - if (joined === "auth status") - return { - stdout: '{"loggedIn":true,"authMethod":"claude.ai"}\n', - stderr: "", - code: 0, - }; - throw new Error(`Unexpected args: ${joined}`); - }), ), - ), - ); + ); - it.effect( - "includes Claude Opus 4.7 with xhigh as the default effort on supported versions", - () => + it.effect("hides Claude Fable 5 on older Claude Code versions", () => Effect.gen(function* () { const status = yield* checkClaudeProviderStatus( defaultClaudeSettings, claudeCapabilities(), ); - const opus47 = status.models.find((model) => model.slug === "claude-opus-4-7"); - if (!opus47) { - assert.fail("Expected Claude Opus 4.7 to be present for Claude Code v2.1.111."); - } - if (!opus47.capabilities) { - assert.fail( - "Expected Claude Opus 4.7 capabilities to be present for Claude Code v2.1.111.", - ); - } - const effortDescriptor = opus47.capabilities.optionDescriptors?.find( - (descriptor) => descriptor.type === "select" && descriptor.id === "effort", + assert.strictEqual( + status.models.some((model) => model.slug === "claude-fable-5"), + false, ); - assert.deepStrictEqual( - effortDescriptor?.type === "select" - ? effortDescriptor.options.find((option) => option.isDefault) - : undefined, - { id: "xhigh", label: "Extra High", isDefault: true }, + assert.strictEqual( + status.message, + "Claude Code v2.1.168 is too old for Claude Fable 5. Upgrade to v2.1.169 or newer to access it.", ); }).pipe( Effect.provide( mockSpawnerLayer((args) => { const joined = args.join(" "); - if (joined === "--version") return { stdout: "2.1.111\n", stderr: "", code: 0 }; + if (joined === "--version") return { stdout: "2.1.168\n", stderr: "", code: 0 }; if (joined === "auth status") return { stdout: '{"loggedIn":true,"authMethod":"claude.ai"}\n', @@ -1399,344 +1434,388 @@ it.layer( }), ), ), - ); - - it.effect("hides Claude Opus 4.7 on older Claude Code versions", () => - Effect.gen(function* () { - const status = yield* checkClaudeProviderStatus( - defaultClaudeSettings, - claudeCapabilities(), - ); - assert.strictEqual( - status.models.some((model) => model.slug === "claude-opus-4-7"), - false, - ); - assert.strictEqual( - status.message, - "Claude Code v2.1.110 is too old for Claude Opus 4.7. Upgrade to v2.1.111 or newer to access it.", - ); - }).pipe( - Effect.provide( - mockSpawnerLayer((args) => { - const joined = args.join(" "); - if (joined === "--version") return { stdout: "2.1.110\n", stderr: "", code: 0 }; - if (joined === "auth status") - return { - stdout: '{"loggedIn":true,"authMethod":"claude.ai"}\n', - stderr: "", - code: 0, - }; - throw new Error(`Unexpected args: ${joined}`); - }), - ), - ), - ); - - it.effect("returns a display label for claude subscription types", () => - Effect.gen(function* () { - const status = yield* checkClaudeProviderStatus( - defaultClaudeSettings, - claudeCapabilities({ subscriptionType: "maxplan" }), - ); - assert.strictEqual(status.status, "ready"); - assert.strictEqual(status.auth.status, "authenticated"); - assert.strictEqual(status.auth.type, "maxplan"); - assert.strictEqual(status.auth.label, "Claude Max Subscription"); - }).pipe( - Effect.provide( - mockSpawnerLayer((args) => { - const joined = args.join(" "); - if (joined === "--version") return { stdout: "1.0.0\n", stderr: "", code: 0 }; - if (joined === "auth status") - return { - stdout: '{"loggedIn":true,"authMethod":"claude.ai"}\n', - stderr: "", - code: 0, - }; - throw new Error(`Unexpected args: ${joined}`); - }), - ), - ), - ); + ); - it.effect("does not duplicate Claude in full subscription labels", () => - Effect.gen(function* () { - const status = yield* checkClaudeProviderStatus( - defaultClaudeSettings, - claudeCapabilities({ - subscriptionType: "Claude Max Subscription", - }), - ); - assert.strictEqual(status.auth.status, "authenticated"); - assert.strictEqual(status.auth.type, "Claude Max Subscription"); - assert.strictEqual(status.auth.label, "Claude Max Subscription"); - }).pipe( - Effect.provide( - mockSpawnerLayer((args) => { - const joined = args.join(" "); - if (joined === "--version") return { stdout: "1.0.0\n", stderr: "", code: 0 }; - throw new Error(`Unexpected args: ${joined}`); - }), - ), - ), - ); + it.effect( + "includes Claude Opus 4.7 with xhigh as the default effort on supported versions", + () => + Effect.gen(function* () { + const status = yield* checkClaudeProviderStatus( + defaultClaudeSettings, + claudeCapabilities(), + ); + const opus47 = status.models.find((model) => model.slug === "claude-opus-4-7"); + if (!opus47) { + assert.fail("Expected Claude Opus 4.7 to be present for Claude Code v2.1.111."); + } + if (!opus47.capabilities) { + assert.fail( + "Expected Claude Opus 4.7 capabilities to be present for Claude Code v2.1.111.", + ); + } + const effortDescriptor = opus47.capabilities.optionDescriptors?.find( + (descriptor) => descriptor.type === "select" && descriptor.id === "effort", + ); + assert.deepStrictEqual( + effortDescriptor?.type === "select" + ? effortDescriptor.options.find((option) => option.isDefault) + : undefined, + { id: "xhigh", label: "Extra High", isDefault: true }, + ); + }).pipe( + Effect.provide( + mockSpawnerLayer((args) => { + const joined = args.join(" "); + if (joined === "--version") return { stdout: "2.1.111\n", stderr: "", code: 0 }; + if (joined === "auth status") + return { + stdout: '{"loggedIn":true,"authMethod":"claude.ai"}\n', + stderr: "", + code: 0, + }; + throw new Error(`Unexpected args: ${joined}`); + }), + ), + ), + ); - it.effect("does not duplicate Claude in provider-prefixed subscription names", () => - Effect.gen(function* () { - const status = yield* checkClaudeProviderStatus( - defaultClaudeSettings, - claudeCapabilities({ - subscriptionType: "Claude Max", - }), - ); - assert.strictEqual(status.auth.status, "authenticated"); - assert.strictEqual(status.auth.type, "Claude Max"); - assert.strictEqual(status.auth.label, "Claude Max Subscription"); - }).pipe( - Effect.provide( - mockSpawnerLayer((args) => { - const joined = args.join(" "); - if (joined === "--version") return { stdout: "1.0.0\n", stderr: "", code: 0 }; - throw new Error(`Unexpected args: ${joined}`); - }), + it.effect("hides Claude Opus 4.7 on older Claude Code versions", () => + Effect.gen(function* () { + const status = yield* checkClaudeProviderStatus( + defaultClaudeSettings, + claudeCapabilities(), + ); + assert.strictEqual( + status.models.some((model) => model.slug === "claude-opus-4-7"), + false, + ); + assert.strictEqual( + status.message, + "Claude Code v2.1.110 is too old for Claude Opus 4.7. Upgrade to v2.1.111 or newer to access it.", + ); + }).pipe( + Effect.provide( + mockSpawnerLayer((args) => { + const joined = args.join(" "); + if (joined === "--version") return { stdout: "2.1.110\n", stderr: "", code: 0 }; + if (joined === "auth status") + return { + stdout: '{"loggedIn":true,"authMethod":"claude.ai"}\n', + stderr: "", + code: 0, + }; + throw new Error(`Unexpected args: ${joined}`); + }), + ), ), - ), - ); + ); - it.effect("returns claude auth email from initialization result", () => - Effect.gen(function* () { - const status = yield* checkClaudeProviderStatus( - defaultClaudeSettings, - claudeCapabilities({ email: "claude@example.com" }), - ); - assert.strictEqual(status.auth.status, "authenticated"); - assert.strictEqual(status.auth.email, "claude@example.com"); - }).pipe( - Effect.provide( - mockSpawnerLayer((args) => { - const joined = args.join(" "); - if (joined === "--version") return { stdout: "1.0.0\n", stderr: "", code: 0 }; - if (joined === "auth status") - return { - stdout: - '{"loggedIn":true,"authMethod":"claude.ai","account":{"email":"claude@example.com"}}\n', - stderr: "", - code: 0, - }; - throw new Error(`Unexpected args: ${joined}`); - }), + it.effect("returns a display label for claude subscription types", () => + Effect.gen(function* () { + const status = yield* checkClaudeProviderStatus( + defaultClaudeSettings, + claudeCapabilities({ subscriptionType: "maxplan" }), + ); + assert.strictEqual(status.status, "ready"); + assert.strictEqual(status.auth.status, "authenticated"); + assert.strictEqual(status.auth.type, "maxplan"); + assert.strictEqual(status.auth.label, "Claude Max Subscription"); + }).pipe( + Effect.provide( + mockSpawnerLayer((args) => { + const joined = args.join(" "); + if (joined === "--version") return { stdout: "1.0.0\n", stderr: "", code: 0 }; + if (joined === "auth status") + return { + stdout: '{"loggedIn":true,"authMethod":"claude.ai"}\n', + stderr: "", + code: 0, + }; + throw new Error(`Unexpected args: ${joined}`); + }), + ), ), - ), - ); - - it.effect("runs Claude status probes with the configured Claude HOME", () => { - const claudeHome = "/tmp/t3code-claude-home"; - const recorded = recordingMockSpawnerLayer((args) => { - const joined = args.join(" "); - if (joined === "--version") return { stdout: "1.0.0\n", stderr: "", code: 0 }; - if (joined === "auth status") - return { - stdout: '{"loggedIn":true,"authMethod":"claude.ai"}\n', - stderr: "", - code: 0, - }; - throw new Error(`Unexpected args: ${joined}`); - }); + ); - return Effect.gen(function* () { - const status = yield* checkClaudeProviderStatus( - { - ...defaultClaudeSettings, - homePath: claudeHome, - }, - claudeCapabilities(), - ); - assert.strictEqual(status.status, "ready"); - assert.deepStrictEqual( - recorded.commands.map((command) => command.env?.HOME), - [claudeHome], - ); - }).pipe(Effect.provide(recorded.layer)); - }); + it.effect("does not duplicate Claude in full subscription labels", () => + Effect.gen(function* () { + const status = yield* checkClaudeProviderStatus( + defaultClaudeSettings, + claudeCapabilities({ + subscriptionType: "Claude Max Subscription", + }), + ); + assert.strictEqual(status.auth.status, "authenticated"); + assert.strictEqual(status.auth.type, "Claude Max Subscription"); + assert.strictEqual(status.auth.label, "Claude Max Subscription"); + }).pipe( + Effect.provide( + mockSpawnerLayer((args) => { + const joined = args.join(" "); + if (joined === "--version") return { stdout: "1.0.0\n", stderr: "", code: 0 }; + throw new Error(`Unexpected args: ${joined}`); + }), + ), + ), + ); - it.effect("includes probed claude slash commands in the provider snapshot", () => - Effect.gen(function* () { - const status = yield* checkClaudeProviderStatus( - defaultClaudeSettings, - claudeCapabilities({ - subscriptionType: "maxplan", - slashCommands: [ - { - name: "review", - description: "Review a pull request", - input: { hint: "pr-or-branch" }, - }, - ], - }), - ); + it.effect("does not duplicate Claude in provider-prefixed subscription names", () => + Effect.gen(function* () { + const status = yield* checkClaudeProviderStatus( + defaultClaudeSettings, + claudeCapabilities({ + subscriptionType: "Claude Max", + }), + ); + assert.strictEqual(status.auth.status, "authenticated"); + assert.strictEqual(status.auth.type, "Claude Max"); + assert.strictEqual(status.auth.label, "Claude Max Subscription"); + }).pipe( + Effect.provide( + mockSpawnerLayer((args) => { + const joined = args.join(" "); + if (joined === "--version") return { stdout: "1.0.0\n", stderr: "", code: 0 }; + throw new Error(`Unexpected args: ${joined}`); + }), + ), + ), + ); - assert.deepStrictEqual(status.slashCommands, [ - { - name: "review", - description: "Review a pull request", - input: { hint: "pr-or-branch" }, - }, - ]); - }).pipe( - Effect.provide( - mockSpawnerLayer((args) => { - const joined = args.join(" "); - if (joined === "--version") return { stdout: "1.0.0\n", stderr: "", code: 0 }; - if (joined === "auth status") - return { - stdout: '{"loggedIn":true,"authMethod":"claude.ai"}\n', - stderr: "", - code: 0, - }; - throw new Error(`Unexpected args: ${joined}`); - }), + it.effect("returns claude auth email from initialization result", () => + Effect.gen(function* () { + const status = yield* checkClaudeProviderStatus( + defaultClaudeSettings, + claudeCapabilities({ email: "claude@example.com" }), + ); + assert.strictEqual(status.auth.status, "authenticated"); + assert.strictEqual(status.auth.email, "claude@example.com"); + }).pipe( + Effect.provide( + mockSpawnerLayer((args) => { + const joined = args.join(" "); + if (joined === "--version") return { stdout: "1.0.0\n", stderr: "", code: 0 }; + if (joined === "auth status") + return { + stdout: + '{"loggedIn":true,"authMethod":"claude.ai","account":{"email":"claude@example.com"}}\n', + stderr: "", + code: 0, + }; + throw new Error(`Unexpected args: ${joined}`); + }), + ), ), - ), - ); + ); - it.effect("deduplicates probed claude slash commands by name", () => - Effect.gen(function* () { - const status = yield* checkClaudeProviderStatus( - defaultClaudeSettings, - claudeCapabilities({ - subscriptionType: "maxplan", - slashCommands: [ - { - name: "ui", - description: "Explore and refine UI", - }, - { - name: "ui", - input: { hint: "component-or-screen" }, - }, - ], - }), - ); + it.effect("runs Claude status probes with the configured Claude HOME", () => { + const claudeHome = "/tmp/t3code-claude-home"; + const recorded = recordingMockSpawnerLayer((args) => { + const joined = args.join(" "); + if (joined === "--version") return { stdout: "1.0.0\n", stderr: "", code: 0 }; + if (joined === "auth status") + return { + stdout: '{"loggedIn":true,"authMethod":"claude.ai"}\n', + stderr: "", + code: 0, + }; + throw new Error(`Unexpected args: ${joined}`); + }); - assert.deepStrictEqual(status.slashCommands, [ - { - name: "ui", - description: "Explore and refine UI", - input: { hint: "component-or-screen" }, - }, - ]); - }).pipe( - Effect.provide( - mockSpawnerLayer((args) => { - const joined = args.join(" "); - if (joined === "--version") return { stdout: "1.0.0\n", stderr: "", code: 0 }; - if (joined === "auth status") - return { - stdout: '{"loggedIn":true,"authMethod":"claude.ai"}\n', - stderr: "", - code: 0, - }; - throw new Error(`Unexpected args: ${joined}`); - }), + return Effect.gen(function* () { + const status = yield* checkClaudeProviderStatus( + { + ...defaultClaudeSettings, + homePath: claudeHome, + }, + claudeCapabilities(), + ); + assert.strictEqual(status.status, "ready"); + assert.deepStrictEqual( + recorded.commands.map((command) => command.env?.HOME), + [claudeHome], + ); + }).pipe(Effect.provide(recorded.layer)); + }); + + it.effect("includes probed claude slash commands in the provider snapshot", () => + Effect.gen(function* () { + const status = yield* checkClaudeProviderStatus( + defaultClaudeSettings, + claudeCapabilities({ + subscriptionType: "maxplan", + slashCommands: [ + { + name: "review", + description: "Review a pull request", + input: { hint: "pr-or-branch" }, + }, + ], + }), + ); + + assert.deepStrictEqual(status.slashCommands, [ + { + name: "review", + description: "Review a pull request", + input: { hint: "pr-or-branch" }, + }, + ]); + }).pipe( + Effect.provide( + mockSpawnerLayer((args) => { + const joined = args.join(" "); + if (joined === "--version") return { stdout: "1.0.0\n", stderr: "", code: 0 }; + if (joined === "auth status") + return { + stdout: '{"loggedIn":true,"authMethod":"claude.ai"}\n', + stderr: "", + code: 0, + }; + throw new Error(`Unexpected args: ${joined}`); + }), + ), ), - ), - ); + ); - it.effect("returns an api key label for claude api key auth", () => - Effect.gen(function* () { - const status = yield* checkClaudeProviderStatus( - defaultClaudeSettings, - claudeCapabilities({ tokenSource: "ANTHROPIC_AUTH_TOKEN" }), - ); - assert.strictEqual(status.status, "ready"); - assert.strictEqual(status.auth.status, "authenticated"); - assert.strictEqual(status.auth.type, "apiKey"); - assert.strictEqual(status.auth.label, "Claude API Key"); - }).pipe( - Effect.provide( - mockSpawnerLayer((args) => { - const joined = args.join(" "); - if (joined === "--version") return { stdout: "1.0.0\n", stderr: "", code: 0 }; - if (joined === "auth status") - return { - stdout: '{"loggedIn":true,"authMethod":"api-key"}\n', - stderr: "", - code: 0, - }; - throw new Error(`Unexpected args: ${joined}`); - }), + it.effect("deduplicates probed claude slash commands by name", () => + Effect.gen(function* () { + const status = yield* checkClaudeProviderStatus( + defaultClaudeSettings, + claudeCapabilities({ + subscriptionType: "maxplan", + slashCommands: [ + { + name: "ui", + description: "Explore and refine UI", + }, + { + name: "ui", + input: { hint: "component-or-screen" }, + }, + ], + }), + ); + + assert.deepStrictEqual(status.slashCommands, [ + { + name: "ui", + description: "Explore and refine UI", + input: { hint: "component-or-screen" }, + }, + ]); + }).pipe( + Effect.provide( + mockSpawnerLayer((args) => { + const joined = args.join(" "); + if (joined === "--version") return { stdout: "1.0.0\n", stderr: "", code: 0 }; + if (joined === "auth status") + return { + stdout: '{"loggedIn":true,"authMethod":"claude.ai"}\n', + stderr: "", + code: 0, + }; + throw new Error(`Unexpected args: ${joined}`); + }), + ), ), - ), - ); + ); - it.effect("returns unavailable when claude is missing", () => - Effect.gen(function* () { - const status = yield* checkClaudeProviderStatus( - defaultClaudeSettings, - claudeCapabilities(), - ); - assert.strictEqual(status.status, "error"); - assert.strictEqual(status.installed, false); - assert.strictEqual(status.auth.status, "unknown"); - assert.strictEqual( - status.message, - "Claude Agent CLI (`claude`) is not installed or not on PATH.", - ); - }).pipe(Effect.provide(failingSpawnerLayer("spawn claude ENOENT"))), - ); + it.effect("returns an api key label for claude api key auth", () => + Effect.gen(function* () { + const status = yield* checkClaudeProviderStatus( + defaultClaudeSettings, + claudeCapabilities({ tokenSource: "ANTHROPIC_AUTH_TOKEN" }), + ); + assert.strictEqual(status.status, "ready"); + assert.strictEqual(status.auth.status, "authenticated"); + assert.strictEqual(status.auth.type, "apiKey"); + assert.strictEqual(status.auth.label, "Claude API Key"); + }).pipe( + Effect.provide( + mockSpawnerLayer((args) => { + const joined = args.join(" "); + if (joined === "--version") return { stdout: "1.0.0\n", stderr: "", code: 0 }; + if (joined === "auth status") + return { + stdout: '{"loggedIn":true,"authMethod":"api-key"}\n', + stderr: "", + code: 0, + }; + throw new Error(`Unexpected args: ${joined}`); + }), + ), + ), + ); - it.effect("returns error when version check fails with non-zero exit code", () => - Effect.gen(function* () { - const status = yield* checkClaudeProviderStatus( - defaultClaudeSettings, - claudeCapabilities(), - ); - assert.strictEqual(status.status, "error"); - assert.strictEqual(status.installed, true); - }).pipe( - Effect.provide( - mockSpawnerLayer((args) => { - const joined = args.join(" "); - if (joined === "--version") - return { - stdout: "", - stderr: "Something went wrong", - code: 1, - }; - throw new Error(`Unexpected args: ${joined}`); - }), + it.effect("returns unavailable when claude is missing", () => + Effect.gen(function* () { + const status = yield* checkClaudeProviderStatus( + defaultClaudeSettings, + claudeCapabilities(), + ); + assert.strictEqual(status.status, "error"); + assert.strictEqual(status.installed, false); + assert.strictEqual(status.auth.status, "unknown"); + assert.strictEqual( + status.message, + "Claude Agent CLI (`claude`) is not installed or not on PATH.", + ); + }).pipe(Effect.provide(failingSpawnerLayer("spawn claude ENOENT"))), + ); + + it.effect("returns error when version check fails with non-zero exit code", () => + Effect.gen(function* () { + const status = yield* checkClaudeProviderStatus( + defaultClaudeSettings, + claudeCapabilities(), + ); + assert.strictEqual(status.status, "error"); + assert.strictEqual(status.installed, true); + }).pipe( + Effect.provide( + mockSpawnerLayer((args) => { + const joined = args.join(" "); + if (joined === "--version") + return { + stdout: "", + stderr: "Something went wrong", + code: 1, + }; + throw new Error(`Unexpected args: ${joined}`); + }), + ), ), - ), - ); + ); - it.effect("returns warning when the Claude initialization result is unavailable", () => - Effect.gen(function* () { - const status = yield* checkClaudeProviderStatus( - defaultClaudeSettings, - noClaudeCapabilities, - ); - assert.strictEqual(status.status, "warning"); - assert.strictEqual(status.installed, true); - assert.strictEqual(status.auth.status, "unknown"); - assert.strictEqual( - status.message, - "Could not verify Claude authentication status from initialization result.", - ); - }).pipe( - Effect.provide( - mockSpawnerLayer((args) => { - const joined = args.join(" "); - if (joined === "--version") return { stdout: "1.0.0\n", stderr: "", code: 0 }; - if (joined === "auth status") - return { - stdout: '{"loggedIn":false}\n', - stderr: "", - code: 1, - }; - throw new Error(`Unexpected args: ${joined}`); - }), + it.effect("returns warning when the Claude initialization result is unavailable", () => + Effect.gen(function* () { + const status = yield* checkClaudeProviderStatus( + defaultClaudeSettings, + noClaudeCapabilities, + ); + assert.strictEqual(status.status, "warning"); + assert.strictEqual(status.installed, true); + assert.strictEqual(status.auth.status, "unknown"); + assert.strictEqual( + status.message, + "Could not verify Claude authentication status from initialization result.", + ); + }).pipe( + Effect.provide( + mockSpawnerLayer((args) => { + const joined = args.join(" "); + if (joined === "--version") return { stdout: "1.0.0\n", stderr: "", code: 0 }; + if (joined === "auth status") + return { + stdout: '{"loggedIn":false}\n', + stderr: "", + code: 1, + }; + throw new Error(`Unexpected args: ${joined}`); + }), + ), ), - ), - ); - }); -}); + ); + }); + }, +); diff --git a/apps/server/src/provider/Services/GrokAdapter.ts b/apps/server/src/provider/Services/GrokAdapter.ts new file mode 100644 index 000000000000..73254cefe393 --- /dev/null +++ b/apps/server/src/provider/Services/GrokAdapter.ts @@ -0,0 +1,16 @@ +/** + * GrokAdapter — shape type for the Grok provider adapter. + * + * The driver model ({@link ../Drivers/GrokDriver}) bundles one adapter per + * instance as a captured closure, so this module only retains the shape + * interface as a naming anchor for the driver bundle. + * + * @module GrokAdapter + */ +import type { ProviderAdapterError } from "../Errors.ts"; +import type { ProviderAdapterShape } from "./ProviderAdapter.ts"; + +/** + * GrokAdapterShape — per-instance Grok adapter contract. + */ +export interface GrokAdapterShape extends ProviderAdapterShape {} diff --git a/apps/server/src/provider/acp/AcpSessionRuntime.ts b/apps/server/src/provider/acp/AcpSessionRuntime.ts index 8652b2cfeaf4..4ed64890fc3e 100644 --- a/apps/server/src/provider/acp/AcpSessionRuntime.ts +++ b/apps/server/src/provider/acp/AcpSessionRuntime.ts @@ -105,6 +105,9 @@ export interface AcpSessionRuntimeShape { value: string | boolean, ) => Effect.Effect; readonly setModel: (model: string) => Effect.Effect; + readonly setSessionModel: ( + modelId: string, + ) => Effect.Effect; readonly request: ( method: string, payload: unknown, @@ -546,6 +549,20 @@ const makeAcpSessionRuntime = ( Effect.flatMap((started) => setConfigOption(started.modelConfigId ?? "model", model)), Effect.asVoid, ), + setSessionModel: (modelId) => + getStartedState.pipe( + Effect.flatMap((started) => { + const requestPayload = { + sessionId: started.sessionId, + modelId, + } satisfies EffectAcpSchema.SetSessionModelRequest; + return runLoggedRequest( + "session/set_model", + requestPayload, + acp.agent.setSessionModel(requestPayload), + ); + }), + ), request: (method, payload) => runLoggedRequest(method, payload, acp.raw.request(method, payload)), notify: acp.raw.notify, diff --git a/apps/server/src/provider/acp/GrokAcpCliProbe.test.ts b/apps/server/src/provider/acp/GrokAcpCliProbe.test.ts new file mode 100644 index 000000000000..222fc4a12d5b --- /dev/null +++ b/apps/server/src/provider/acp/GrokAcpCliProbe.test.ts @@ -0,0 +1,69 @@ +/** + * Optional integration check against a real `grok agent stdio` install. + * Enable with: T3_GROK_ACP_PROBE=1 bun run test GrokAcpCliProbe + * + * The probe assumes either `XAI_API_KEY` is set in the environment or + * the user has previously run `grok login`. Without credentials the + * agent's `authenticate` request will fail and the test will surface + * the error. + */ +import * as NodeServices from "@effect/platform-node/NodeServices"; +import { it } from "@effect/vitest"; +import * as Effect from "effect/Effect"; +import { ChildProcessSpawner } from "effect/unstable/process"; +import { describe, expect } from "vite-plus/test"; + +import { makeGrokAcpRuntime } from "./GrokAcpSupport.ts"; + +const makeProbeRuntime = Effect.gen(function* () { + const childProcessSpawner = yield* ChildProcessSpawner.ChildProcessSpawner; + return yield* makeGrokAcpRuntime({ + grokSettings: { binaryPath: "grok" }, + environment: process.env, + childProcessSpawner, + cwd: process.cwd(), + clientInfo: { name: "t3-grok-probe", version: "0.0.0" }, + }); +}); + +describe.runIf(process.env.T3_GROK_ACP_PROBE === "1")("Grok ACP CLI probe", () => { + it.effect("initialize and authenticate against real grok agent stdio", () => + Effect.gen(function* () { + const runtime = yield* makeProbeRuntime; + const started = yield* runtime.start(); + expect(started.initializeResult).toBeDefined(); + }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)), + ); + + it.effect("session/new advertises typed SessionModelState with at least one model", () => + Effect.gen(function* () { + const runtime = yield* makeProbeRuntime; + const started = yield* runtime.start(); + const result = started.sessionSetupResult; + + expect(typeof started.sessionId).toBe("string"); + + // Modern grok-shell advertises models through the typed + // `SessionModelState` field, not via a `configOptions` entry. + // If this assertion fails the upstream surface has regressed. + const models = result.models; + expect(models).toBeDefined(); + expect(typeof models?.currentModelId).toBe("string"); + expect(models?.availableModels.length ?? 0).toBeGreaterThan(0); + }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)), + ); + + it.effect("session/set_model accepts a no-op switch to the current model", () => + Effect.gen(function* () { + const runtime = yield* makeProbeRuntime; + const started = yield* runtime.start(); + const currentModelId = started.sessionSetupResult.models?.currentModelId?.trim(); + expect(currentModelId).toBeDefined(); + if (!currentModelId) return; + + // No-op switch — selecting the model the session already runs on must + // succeed against every Grok build that implements `session/set_model`. + yield* runtime.setSessionModel(currentModelId); + }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)), + ); +}); diff --git a/apps/server/src/provider/acp/GrokAcpSupport.test.ts b/apps/server/src/provider/acp/GrokAcpSupport.test.ts new file mode 100644 index 000000000000..02d60976b24c --- /dev/null +++ b/apps/server/src/provider/acp/GrokAcpSupport.test.ts @@ -0,0 +1,109 @@ +import { describe, expect, it } from "@effect/vitest"; +import * as Effect from "effect/Effect"; +import * as EffectAcpErrors from "effect-acp/errors"; + +import { + applyGrokAcpModelSelection, + buildGrokAcpSpawnInput, + resolveGrokAcpBaseModelId, +} from "./GrokAcpSupport.ts"; + +describe("resolveGrokAcpBaseModelId", () => { + it("normalizes empty and custom Grok model ids", () => { + expect(resolveGrokAcpBaseModelId(undefined)).toBe("grok-build"); + expect(resolveGrokAcpBaseModelId(" ")).toBe("grok-build"); + expect(resolveGrokAcpBaseModelId(" grok-test-custom-model ")).toBe("grok-test-custom-model"); + }); +}); + +describe("buildGrokAcpSpawnInput", () => { + it("passes the T3 Code referrer through Grok OAuth env", () => { + const spawn = buildGrokAcpSpawnInput({ binaryPath: "/usr/local/bin/grok" }, "/tmp/project", { + XAI_API_KEY: "secret", + GROK_OAUTH2_REFERRER: "other-client", + }); + + expect(spawn).toEqual({ + command: "/usr/local/bin/grok", + args: ["agent", "stdio"], + cwd: "/tmp/project", + env: { + XAI_API_KEY: "secret", + GROK_OAUTH2_REFERRER: "t3code", + }, + }); + }); +}); + +describe("applyGrokAcpModelSelection", () => { + const makeRecordingRuntime = (failure?: EffectAcpErrors.AcpError) => { + const modelCalls: Array = []; + const runtime = { + setSessionModel: (modelId: string) => + Effect.gen(function* () { + modelCalls.push(modelId); + if (failure) return yield* failure; + return {}; + }), + }; + return { runtime, modelCalls }; + }; + + it.effect("calls session/set_model when the requested model differs from current", () => + Effect.gen(function* () { + const { runtime, modelCalls } = makeRecordingRuntime(); + const result = yield* applyGrokAcpModelSelection({ + runtime, + currentModelId: "grok-build", + requestedModelId: "grok-mock-alt", + mapError: (cause) => cause.message, + }); + expect(modelCalls).toEqual(["grok-mock-alt"]); + expect(result).toBe("grok-mock-alt"); + }), + ); + + it.effect("skips set_model when requested matches current", () => + Effect.gen(function* () { + const { runtime, modelCalls } = makeRecordingRuntime(); + const result = yield* applyGrokAcpModelSelection({ + runtime, + currentModelId: "grok-build", + requestedModelId: "grok-build", + mapError: (cause) => cause.message, + }); + expect(modelCalls).toEqual([]); + expect(result).toBe("grok-build"); + }), + ); + + it.effect("skips set_model when no model is requested", () => + Effect.gen(function* () { + const { runtime, modelCalls } = makeRecordingRuntime(); + const result = yield* applyGrokAcpModelSelection({ + runtime, + currentModelId: "grok-build", + requestedModelId: undefined, + mapError: (cause) => cause.message, + }); + expect(modelCalls).toEqual([]); + expect(result).toBe("grok-build"); + }), + ); + + it.effect("propagates session/set_model failures via mapError", () => + Effect.gen(function* () { + const failure = EffectAcpErrors.AcpRequestError.invalidParams("session id not known"); + const { runtime } = makeRecordingRuntime(failure); + const error = yield* Effect.flip( + applyGrokAcpModelSelection({ + runtime, + currentModelId: "grok-build", + requestedModelId: "grok-mock-alt", + mapError: (cause) => cause.message, + }), + ); + expect(error).toBe(failure.message); + }), + ); +}); diff --git a/apps/server/src/provider/acp/GrokAcpSupport.ts b/apps/server/src/provider/acp/GrokAcpSupport.ts new file mode 100644 index 000000000000..642548832fa0 --- /dev/null +++ b/apps/server/src/provider/acp/GrokAcpSupport.ts @@ -0,0 +1,104 @@ +import { type GrokSettings, ProviderDriverKind } from "@t3tools/contracts"; +import * as Effect from "effect/Effect"; +import * as Layer from "effect/Layer"; +import * as Scope from "effect/Scope"; +import { ChildProcessSpawner } from "effect/unstable/process"; +import * as EffectAcpErrors from "effect-acp/errors"; +import type * as EffectAcpSchema from "effect-acp/schema"; +import { normalizeModelSlug } from "@t3tools/shared/model"; + +import { + AcpSessionRuntime, + type AcpSessionRuntimeOptions, + type AcpSessionRuntimeShape, + type AcpSpawnInput, +} from "./AcpSessionRuntime.ts"; + +const GROK_API_KEY_ENV = "XAI_API_KEY"; +const GROK_OAUTH2_REFERRER_ENV = "GROK_OAUTH2_REFERRER"; +const T3_CODE_OAUTH_REFERRER = "t3code"; +const GROK_AUTH_METHOD_API_KEY = "xai.api_key"; +const GROK_AUTH_METHOD_CACHED_TOKEN = "cached_token"; +const GROK_DRIVER_KIND = ProviderDriverKind.make("grok"); + +type GrokAcpRuntimeGrokSettings = Pick; + +interface GrokAcpRuntimeInput extends Omit< + AcpSessionRuntimeOptions, + "authMethodId" | "clientCapabilities" | "spawn" +> { + readonly childProcessSpawner: ChildProcessSpawner.ChildProcessSpawner["Service"]; + readonly grokSettings: GrokAcpRuntimeGrokSettings | null | undefined; + readonly environment?: NodeJS.ProcessEnv; +} + +export function buildGrokAcpSpawnInput( + grokSettings: GrokAcpRuntimeGrokSettings | null | undefined, + cwd: string, + environment?: NodeJS.ProcessEnv, +): AcpSpawnInput { + return { + command: grokSettings?.binaryPath || "grok", + args: ["agent", "stdio"], + cwd, + env: { + ...environment, + [GROK_OAUTH2_REFERRER_ENV]: T3_CODE_OAUTH_REFERRER, + }, + }; +} + +function resolveGrokAuthMethodId(environment: NodeJS.ProcessEnv | undefined): string { + return environment?.[GROK_API_KEY_ENV]?.trim() + ? GROK_AUTH_METHOD_API_KEY + : GROK_AUTH_METHOD_CACHED_TOKEN; +} + +export const makeGrokAcpRuntime = ( + input: GrokAcpRuntimeInput, +): Effect.Effect => + Effect.gen(function* () { + const acpContext = yield* Layer.build( + AcpSessionRuntime.layer({ + ...input, + spawn: buildGrokAcpSpawnInput(input.grokSettings, input.cwd, input.environment), + authMethodId: resolveGrokAuthMethodId(input.environment), + }).pipe( + Layer.provide( + Layer.succeed(ChildProcessSpawner.ChildProcessSpawner, input.childProcessSpawner), + ), + ), + ); + return yield* Effect.service(AcpSessionRuntime).pipe(Effect.provide(acpContext)); + }); + +export function resolveGrokAcpBaseModelId(model: string | null | undefined): string { + const trimmed = model?.trim(); + const base = trimmed && trimmed.length > 0 ? trimmed : "grok-build"; + return normalizeModelSlug(base, GROK_DRIVER_KIND) ?? "grok-build"; +} + +export function currentGrokModelIdFromSessionSetup( + sessionSetupResult: + | EffectAcpSchema.LoadSessionResponse + | EffectAcpSchema.NewSessionResponse + | EffectAcpSchema.ResumeSessionResponse, +): string | undefined { + return sessionSetupResult.models?.currentModelId?.trim() || undefined; +} + +export function applyGrokAcpModelSelection(input: { + readonly runtime: Pick; + readonly currentModelId: string | undefined; + readonly requestedModelId: string | undefined; + readonly mapError: (cause: EffectAcpErrors.AcpError) => E; +}): Effect.Effect { + const shouldSwitchModel = + input.requestedModelId !== undefined && input.requestedModelId !== input.currentModelId; + if (!shouldSwitchModel) { + return Effect.succeed(input.currentModelId); + } + return input.runtime + .setSessionModel(input.requestedModelId) + .pipe(Effect.mapError(input.mapError), Effect.as(input.requestedModelId)); +} diff --git a/apps/server/src/provider/acp/XAiAcpExtension.test.ts b/apps/server/src/provider/acp/XAiAcpExtension.test.ts new file mode 100644 index 000000000000..a42561d9ae2d --- /dev/null +++ b/apps/server/src/provider/acp/XAiAcpExtension.test.ts @@ -0,0 +1,250 @@ +import { describe, expect, it } from "vite-plus/test"; +import * as Schema from "effect/Schema"; + +import { + extractXAiAskUserQuestions, + makeXAiAskUserQuestionCancelledResponse, + makeXAiAskUserQuestionResponse, + XAiAskUserQuestionRequest, +} from "./XAiAcpExtension.ts"; + +const decodeXAiAskUserQuestionRequest = Schema.decodeUnknownSync(XAiAskUserQuestionRequest); + +describe("XAiAcpExtension", () => { + it("extracts questions from the real xAI ask_user_question payload shape", () => { + const questions = extractXAiAskUserQuestions({ + sessionId: "session-1", + toolCallId: "tool-call-1", + mode: "default", + questions: [ + { + id: "scope", + question: "Which scope should Grok use?", + options: [ + { label: "Workspace", description: "Use the current workspace" }, + { label: "Session", description: "Only use this session" }, + ], + }, + ], + }); + + expect(questions).toEqual([ + { + id: "scope", + header: "Question", + question: "Which scope should Grok use?", + multiSelect: false, + options: [ + { label: "Workspace", description: "Use the current workspace" }, + { label: "Session", description: "Only use this session" }, + ], + }, + ]); + }); + + it("extracts questions from wrapped _x.ai extension payloads", () => { + const payload = { + method: "_x.ai/ask_user_question", + params: { + sessionId: "session-1", + toolCallId: "tool-call-1", + mode: "plan", + questions: [ + { + question: "Which changes should be included?", + multiSelect: true, + options: [{ label: "Tests" }, { label: "Docs" }], + }, + ], + }, + }; + const decoded = decodeXAiAskUserQuestionRequest(payload); + const questions = extractXAiAskUserQuestions(decoded); + + expect(questions).toEqual([ + { + id: "Which changes should be included?", + header: "Question", + question: "Which changes should be included?", + multiSelect: true, + options: [ + { label: "Tests", description: "Tests" }, + { label: "Docs", description: "Docs" }, + ], + }, + ]); + }); + + it("treats nullable multiSelect from Grok as single-select", () => { + const questions = extractXAiAskUserQuestions({ + sessionId: "session-1", + toolCallId: "tool-call-1", + mode: "default", + questions: [ + { + question: "Which label should Grok use?", + multiSelect: null, + options: [ + { label: "Alpha", description: "Use the Alpha label" }, + { label: "Beta", description: "Use the Beta label" }, + { label: "Other", description: "Use the Other label" }, + ], + }, + ], + }); + + expect(questions).toEqual([ + { + id: "Which label should Grok use?", + header: "Question", + question: "Which label should Grok use?", + multiSelect: false, + options: [ + { label: "Alpha", description: "Use the Alpha label" }, + { label: "Beta", description: "Use the Beta label" }, + { label: "Other", description: "Use the Other label" }, + ], + }, + ]); + }); + + it("maps UI question ids back to xAI question text in accepted responses", () => { + const response = makeXAiAskUserQuestionResponse( + { + sessionId: "session-1", + toolCallId: "tool-call-1", + mode: "default", + questions: [ + { + id: "scope", + question: "Which scope should Grok use?", + options: [ + { label: "workspace", description: "Use the current workspace" }, + { label: "session", description: "Only use this session" }, + ], + }, + ], + }, + { scope: "workspace" }, + ); + + expect(response).toEqual({ + outcome: "accepted", + answers: { + "Which scope should Grok use?": ["workspace"], + }, + }); + }); + + it("orders accepted answers by the original xAI question order", () => { + const response = makeXAiAskUserQuestionResponse( + { + sessionId: "session-1", + toolCallId: "tool-call-1", + mode: "default", + questions: [ + { + id: "first", + question: "First question?", + options: [{ label: "A", description: "A" }], + }, + { + id: "second", + question: "Second question?", + options: [{ label: "B", description: "B" }], + }, + ], + }, + { + second: "B", + first: "A", + }, + ); + + expect(Object.keys(response.answers)).toEqual(["First question?", "Second question?"]); + expect(response).toMatchObject({ + outcome: "accepted", + answers: { + "First question?": ["A"], + "Second question?": ["B"], + }, + }); + }); + + it("encodes typed custom answers as xAI Other annotations", () => { + const response = makeXAiAskUserQuestionResponse( + { + method: "x.ai/ask_user_question", + params: { + sessionId: "session-1", + toolCallId: "tool-call-1", + mode: "default", + questions: [ + { + question: "Which ice cream flavor?", + options: [ + { label: "vanilla", description: "Vanilla flavor" }, + { label: "chocolate", description: "Chocolate flavor" }, + ], + }, + ], + }, + }, + { "Which ice cream flavor?": "pistachio" }, + ); + + expect(response).toEqual({ + outcome: "accepted", + answers: { + "Which ice cream flavor?": ["Other"], + }, + annotations: { + "Which ice cream flavor?": { + notes: "pistachio", + }, + }, + }); + }); + + it("encodes interrupted dialogs as xAI cancelled responses", () => { + expect(makeXAiAskUserQuestionCancelledResponse()).toEqual({ + outcome: "cancelled", + }); + }); + + it("does not echo preview annotations for multi-select answers", () => { + const response = makeXAiAskUserQuestionResponse( + { + sessionId: "session-1", + toolCallId: "tool-call-1", + mode: "default", + questions: [ + { + question: "Which files should Grok touch?", + multiSelect: true, + options: [ + { + label: "Tests", + description: "Update tests", + preview: "test preview", + }, + { + label: "Docs", + description: "Update docs", + preview: "docs preview", + }, + ], + }, + ], + }, + { "Which files should Grok touch?": ["Tests", "Docs"] }, + ); + + expect(response).toEqual({ + outcome: "accepted", + answers: { + "Which files should Grok touch?": ["Tests", "Docs"], + }, + }); + }); +}); diff --git a/apps/server/src/provider/acp/XAiAcpExtension.ts b/apps/server/src/provider/acp/XAiAcpExtension.ts new file mode 100644 index 000000000000..6c774c7f8d5a --- /dev/null +++ b/apps/server/src/provider/acp/XAiAcpExtension.ts @@ -0,0 +1,173 @@ +import type { ProviderUserInputAnswers, UserInputQuestion } from "@t3tools/contracts"; +import * as Schema from "effect/Schema"; + +const XAiAskUserQuestionOption = Schema.Struct({ + label: Schema.String, + description: Schema.optional(Schema.String), + preview: Schema.optional(Schema.String), + id: Schema.optional(Schema.String), +}); + +const XAiAskUserQuestion = Schema.Struct({ + id: Schema.optional(Schema.String), + question: Schema.String, + options: Schema.Array(XAiAskUserQuestionOption), + multiSelect: Schema.optional(Schema.NullOr(Schema.Boolean)), +}); + +const XAiAskUserQuestionParams = Schema.Struct({ + sessionId: Schema.String, + toolCallId: Schema.String, + questions: Schema.Array(XAiAskUserQuestion), + mode: Schema.Literals(["default", "plan"]), +}); + +const XAiWrappedAskUserQuestionParams = Schema.Struct({ + method: Schema.Literals(["x.ai/ask_user_question", "_x.ai/ask_user_question"]), + params: XAiAskUserQuestionParams, +}); + +export const XAiAskUserQuestionRequest = Schema.Union([ + XAiAskUserQuestionParams, + XAiWrappedAskUserQuestionParams, +]); + +type XAiAskUserQuestionRequestParams = typeof XAiAskUserQuestionParams.Type; +type XAiAskUserQuestionRequest = typeof XAiAskUserQuestionRequest.Type; + +function trimmed(value: string | undefined): string | undefined { + const text = value?.trim(); + return text && text.length > 0 ? text : undefined; +} + +function unwrapAskUserQuestionParams( + params: XAiAskUserQuestionRequest, +): XAiAskUserQuestionRequestParams { + return "params" in params ? params.params : params; +} + +export function extractXAiAskUserQuestions( + params: XAiAskUserQuestionRequest, +): ReadonlyArray { + return unwrapAskUserQuestionParams(params).questions.map((question) => ({ + id: question.id ?? question.question, + header: "Question", + question: question.question, + multiSelect: question.multiSelect === true, + options: + question.options.length > 0 + ? question.options.map((option) => ({ + label: option.label, + description: option.description ?? option.label, + })) + : [{ label: "OK", description: "Continue" }], + })); +} + +interface XAiAskUserQuestionAnnotation { + readonly preview?: string; + readonly notes?: string; +} + +interface XAiAskUserQuestionAcceptedResponse { + readonly outcome: "accepted"; + readonly answers: Record>; + readonly annotations?: Record; +} + +interface XAiAskUserQuestionCancelledResponse { + readonly outcome: "cancelled"; +} + +export type XAiAskUserQuestionResponse = + | XAiAskUserQuestionAcceptedResponse + | XAiAskUserQuestionCancelledResponse; + +interface NormalizedXAiAnswer { + readonly questionText: string; + readonly selectedLabels: ReadonlyArray; + readonly annotation?: XAiAskUserQuestionAnnotation; +} + +function answerValues(answer: unknown): ReadonlyArray { + if (Array.isArray(answer)) { + return answer.flatMap((entry) => { + const text = typeof entry === "string" ? trimmed(entry) : undefined; + return text ? [text] : []; + }); + } + const text = typeof answer === "string" ? trimmed(answer) : undefined; + return text ? [text] : []; +} + +function normalizeAnswerForXAi( + question: XAiAskUserQuestionRequestParams["questions"][number], + answer: unknown, +): NormalizedXAiAnswer | undefined { + const values = answerValues(answer); + if (values.length === 0) { + return undefined; + } + + const optionByLabel = new Map(question.options.map((option) => [option.label, option])); + const resolvedValues = values.map((value) => ({ + value, + option: optionByLabel.get(value), + })); + const selectedLabels = resolvedValues.flatMap(({ option }) => (option ? [option.label] : [])); + const notes = resolvedValues.flatMap(({ option, value }) => (option ? [] : [value])); + const preview = + question.multiSelect === true + ? undefined + : resolvedValues.map(({ option }) => trimmed(option?.preview)).find((value) => value); + + const annotation = + preview || notes.length > 0 + ? { + ...(preview ? { preview } : {}), + ...(notes.length > 0 ? { notes: notes.join("\n") } : {}), + } + : undefined; + + return { + questionText: question.question, + selectedLabels: selectedLabels.length > 0 ? selectedLabels : ["Other"], + ...(annotation ? { annotation } : {}), + }; +} + +function findQuestionAnswer( + answers: ProviderUserInputAnswers, + question: XAiAskUserQuestionRequestParams["questions"][number], +): unknown { + const key = question.id ?? question.question; + return answers[key] ?? answers[question.question]; +} + +export function makeXAiAskUserQuestionResponse( + params: XAiAskUserQuestionRequest, + answers: ProviderUserInputAnswers, +): XAiAskUserQuestionAcceptedResponse { + const questions = unwrapAskUserQuestionParams(params).questions; + const normalized = questions.flatMap((question) => { + const entry = normalizeAnswerForXAi(question, findQuestionAnswer(answers, question)); + return entry ? [entry] : []; + }); + const annotations = Object.fromEntries( + normalized.flatMap((entry) => + entry.annotation ? [[entry.questionText, entry.annotation] as const] : [], + ), + ); + + return { + outcome: "accepted", + answers: Object.fromEntries( + normalized.map((entry) => [entry.questionText, entry.selectedLabels]), + ), + ...(Object.keys(annotations).length > 0 ? { annotations } : {}), + }; +} + +export function makeXAiAskUserQuestionCancelledResponse(): XAiAskUserQuestionCancelledResponse { + return { outcome: "cancelled" }; +} diff --git a/apps/server/src/provider/builtInDrivers.ts b/apps/server/src/provider/builtInDrivers.ts index 5af56dc6b0e8..791a96e1da3c 100644 --- a/apps/server/src/provider/builtInDrivers.ts +++ b/apps/server/src/provider/builtInDrivers.ts @@ -23,6 +23,7 @@ import { ClaudeDriver, type ClaudeDriverEnv } from "./Drivers/ClaudeDriver.ts"; import { CodexDriver, type CodexDriverEnv } from "./Drivers/CodexDriver.ts"; import { CursorDriver, type CursorDriverEnv } from "./Drivers/CursorDriver.ts"; +import { GrokDriver, type GrokDriverEnv } from "./Drivers/GrokDriver.ts"; import { OpenCodeDriver, type OpenCodeDriverEnv } from "./Drivers/OpenCodeDriver.ts"; import type { AnyProviderDriver } from "./ProviderDriver.ts"; @@ -35,6 +36,7 @@ export type BuiltInDriversEnv = | ClaudeDriverEnv | CodexDriverEnv | CursorDriverEnv + | GrokDriverEnv | OpenCodeDriverEnv; /** @@ -46,5 +48,6 @@ export const BUILT_IN_DRIVERS: ReadonlyArray) => runProviderMaintenanceCommandWithSpawner({ spawner, diff --git a/apps/server/src/provider/providerSnapshot.ts b/apps/server/src/provider/providerSnapshot.ts index c40903e1b45f..ce43c5e6eab7 100644 --- a/apps/server/src/provider/providerSnapshot.ts +++ b/apps/server/src/provider/providerSnapshot.ts @@ -45,6 +45,7 @@ export interface ServerProviderPresentation { readonly displayName: string; readonly badgeLabel?: string; readonly showInteractionModeToggle?: boolean; + readonly requiresNewThreadForModelChange?: boolean; } export type ServerProviderDraft = Omit; @@ -214,6 +215,9 @@ export function buildServerProvider(input: { ...(typeof input.presentation.showInteractionModeToggle === "boolean" ? { showInteractionModeToggle: input.presentation.showInteractionModeToggle } : {}), + ...(typeof input.presentation.requiresNewThreadForModelChange === "boolean" + ? { requiresNewThreadForModelChange: input.presentation.requiresNewThreadForModelChange } + : {}), enabled: input.enabled, installed: input.probe.installed, version: input.probe.version, diff --git a/apps/server/src/provider/testUtils/providerRegistryMock.ts b/apps/server/src/provider/testUtils/providerRegistryMock.ts new file mode 100644 index 000000000000..36598b059009 --- /dev/null +++ b/apps/server/src/provider/testUtils/providerRegistryMock.ts @@ -0,0 +1,21 @@ +import { ProviderRegistry, type ProviderRegistryShape } from "../Services/ProviderRegistry.ts"; +import type { ServerProvider } from "@t3tools/contracts"; +import * as Effect from "effect/Effect"; +import * as Layer from "effect/Layer"; +import * as Stream from "effect/Stream"; +import { makeManualOnlyProviderMaintenanceCapabilities } from "../providerMaintenance.ts"; + +export const makeProviderRegistryMock = ( + providers: ReadonlyArray = [], +): ProviderRegistryShape => ({ + getProviders: Effect.succeed(providers), + refresh: () => Effect.succeed(providers), + refreshInstance: () => Effect.succeed(providers), + getProviderMaintenanceCapabilitiesForInstance: (_instanceId, provider) => + Effect.succeed(makeManualOnlyProviderMaintenanceCapabilities({ provider, packageName: null })), + setProviderMaintenanceActionState: () => Effect.succeed(providers), + streamChanges: Stream.empty, +}); + +export const makeProviderRegistryLayer = (providers: ReadonlyArray = []) => + Layer.succeed(ProviderRegistry, makeProviderRegistryMock(providers)); diff --git a/apps/server/src/relay/AgentAwarenessRelay.ts b/apps/server/src/relay/AgentAwarenessRelay.ts index 6266a39b798b..960f27e752bb 100644 --- a/apps/server/src/relay/AgentAwarenessRelay.ts +++ b/apps/server/src/relay/AgentAwarenessRelay.ts @@ -303,7 +303,7 @@ const make = Effect.gen(function* () { } const relayConfig = yield* readRelayConfig.pipe(Effect.orElseSucceed(() => null)); if (!relayConfig) { - yield* Effect.logDebug("agent activity publish skipped; T3 Cloud config missing", { + yield* Effect.logDebug("agent activity publish skipped; T3 Connect config missing", { threadId, }); return; @@ -421,7 +421,7 @@ const make = Effect.gen(function* () { } const relayConfig = yield* readRelayConfig.pipe(Effect.orElseSucceed(() => null)); if (!relayConfig) { - yield* Effect.logDebug("agent activity snapshot skipped; T3 Cloud config missing"); + yield* Effect.logDebug("agent activity snapshot skipped; T3 Connect config missing"); return false; } const environmentId = yield* serverEnvironment.getEnvironmentId; @@ -459,7 +459,7 @@ const make = Effect.gen(function* () { function* () { const relayConfig = yield* readRelayConfig.pipe(Effect.orElseSucceed(() => null)); if (!relayConfig) { - yield* Effect.logInfo("agent activity publishing standby; T3 Cloud config missing"); + yield* Effect.logInfo("agent activity publishing standby; T3 Connect config missing"); } else { yield* Effect.logInfo("agent activity publishing enabled", { relayUrl: relayConfig.url, diff --git a/apps/server/src/review/BackgroundAgentService.test.ts b/apps/server/src/review/BackgroundAgentService.test.ts deleted file mode 100644 index de9f31fd318c..000000000000 --- a/apps/server/src/review/BackgroundAgentService.test.ts +++ /dev/null @@ -1,851 +0,0 @@ -import { describe, it, expect, vi, beforeEach, afterEach } from "vite-plus/test"; -import * as Effect from "effect/Effect"; -import * as Layer from "effect/Layer"; -import * as Stream from "effect/Stream"; -import type { BackgroundAgentResponseEvent } from "@t3tools/contracts"; - -import { - BackgroundAgentService, - type BackgroundAgentServiceShape, - DEFAULT_MAX_CONCURRENT_AGENTS, -} from "./BackgroundAgentService.ts"; -import { GitWorkflowService } from "../git/GitWorkflowService.ts"; -import { - GitVcsDriver, - type ExecuteGitInput, - type ExecuteGitResult, - type GitVcsDriverShape, -} from "../vcs/GitVcsDriver.ts"; -import { ReviewService } from "./ReviewService.ts"; - -vi.mock("node:fs/promises", () => ({ - writeFile: vi.fn().mockResolvedValue(undefined), -})); - -vi.mock("node:child_process", () => ({ - spawn: vi.fn(), -})); - -// @effect-diagnostics-next-line nodeBuiltinImport:off -import * as fs from "node:fs/promises"; -// @effect-diagnostics-next-line nodeBuiltinImport:off -import * as child_process from "node:child_process"; - -function makeFakeChildProcess() { - const listeners: Record void>> = {}; - return { - stdout: { on: vi.fn() }, - stderr: { on: vi.fn() }, - on: vi.fn((event: string, cb: (...args: unknown[]) => void) => { - if (!listeners[event]) listeners[event] = []; - listeners[event]!.push(cb); - }), - _emitClose: (code: number) => { - for (const cb of listeners.close ?? []) cb(code); - }, - _emitError: () => { - for (const cb of listeners.error ?? []) cb(new Error("spawn error")); - }, - }; -} - -function makeBaseGitWorkflow(options: { - readonly createWorktreePath: string; - readonly createWorktreeRefName: string; - readonly createWorktreeError?: Error; -}) { - return GitWorkflowService.of({ - status: () => Effect.die("unexpected"), - localStatus: () => Effect.die("unexpected"), - remoteStatus: () => Effect.die("unexpected"), - invalidateLocalStatus: () => Effect.void, - invalidateRemoteStatus: () => Effect.void, - invalidateStatus: () => Effect.void, - pullCurrentBranch: () => Effect.die("unexpected"), - runStackedAction: () => Effect.die("unexpected"), - resolvePullRequest: () => Effect.die("unexpected"), - preparePullRequestThread: () => Effect.die("unexpected"), - listRefs: () => Effect.die("unexpected"), - createWorktree: () => { - if (options.createWorktreeError) { - return Effect.fail(options.createWorktreeError as never); - } - return Effect.succeed({ - worktree: { - path: options.createWorktreePath, - refName: options.createWorktreeRefName, - }, - }); - }, - removeWorktree: () => Effect.void, - createRef: () => Effect.die("unexpected"), - switchRef: () => Effect.die("unexpected"), - renameBranch: () => Effect.die("unexpected"), - }); -} - -function makeBaseGit(gitDiff: string, gitStatus: string) { - return GitVcsDriver.of({ - execute: (args: ExecuteGitInput) => { - const argStr = args.args.join(" "); - if (argStr.includes("status --porcelain")) { - return Effect.succeed({ - stdout: gitStatus, - stderr: "", - exitCode: 0, - stdoutTruncated: false, - stderrTruncated: false, - } as ExecuteGitResult); - } - return Effect.succeed({ - stdout: "", - stderr: "", - exitCode: 0, - stdoutTruncated: false, - stderrTruncated: false, - } as ExecuteGitResult); - }, - getPrDiff: () => Effect.succeed(gitDiff), - getReviewDiffPreview: () => Effect.die("unexpected"), - listRefs: () => Effect.die("unexpected"), - createWorktree: () => Effect.die("unexpected"), - removeWorktree: () => Effect.die("unexpected"), - createRef: () => Effect.die("unexpected"), - switchRef: () => Effect.die("unexpected"), - pullCurrentBranch: () => Effect.die("unexpected"), - renameBranch: () => Effect.die("unexpected"), - } as unknown as GitVcsDriverShape); -} - -function makeBaseReview(updateMutation: ReturnType = vi.fn()) { - updateMutation.mockReturnValue(Effect.succeed(null)); - return ReviewService.of({ - getDiffPreview: () => Effect.die("unexpected"), - getReviewDraft: () => Effect.die("unexpected"), - upsertReviewComment: () => Effect.die("unexpected"), - deleteReviewComment: () => Effect.die("unexpected"), - submitReview: () => Effect.die("unexpected"), - updateCommentAgentStatus: updateMutation as never, - }); -} - -function makeLayer(options: { - readonly gitDiff: string; - readonly gitStatus: string; - readonly createWorktreePath: string; - readonly createWorktreeRefName: string; - readonly createWorktreeError?: Error; - readonly updateMutation?: ReturnType; -}) { - const updateMutation = options.updateMutation ?? vi.fn(); - return { - layer: Layer.mergeAll( - Layer.succeed( - GitWorkflowService, - makeBaseGitWorkflow({ - createWorktreePath: options.createWorktreePath, - createWorktreeRefName: options.createWorktreeRefName, - ...("createWorktreeError" in options - ? { createWorktreeError: options.createWorktreeError } - : {}), - }), - ), - Layer.succeed(GitVcsDriver, makeBaseGit(options.gitDiff, options.gitStatus)), - Layer.succeed(ReviewService, makeBaseReview(updateMutation)), - ), - updateMutation, - }; -} - -/** Collect stream events and close the fake child process, all within Effect */ -function runAndCollect(options: { - readonly service: BackgroundAgentServiceShape; - readonly input: Parameters[0]; - readonly fakeChild: ReturnType; - readonly exitCode: number; -}): Effect.Effect, never> { - return Effect.gen(function* () { - // @effect-diagnostics-next-line runEffectInsideEffect:off - const collectEffect = Effect.runPromise( - options.service.runBackgroundAgent(options.input).pipe(Stream.runCollect), - ); - - // Let microtasks drain so the spawn callback fires - // @effect-diagnostics-next-line globalTimers:off - yield* Effect.promise(() => new Promise((r) => setTimeout(r, 10))); - options.fakeChild._emitClose(options.exitCode); - - const events = yield* Effect.promise>( - () => collectEffect, - ); - return Array.from(events); - }); -} - -describe("BackgroundAgentService", () => { - beforeEach(() => { - vi.clearAllMocks(); - }); - - afterEach(() => { - vi.clearAllMocks(); - }); - - it("runs agent on success path, commits changes, and completes", () => - Effect.gen(function* () { - const fakeChild = makeFakeChildProcess(); - vi.mocked(child_process.spawn).mockReturnValue( - fakeChild as unknown as ReturnType, - ); - - const { layer } = makeLayer({ - gitDiff: "diff --git a/test.ts b/test.ts\n+test change", - gitStatus: "M test.ts\n", - createWorktreePath: "/tmp/t3-test-worktree", - createWorktreeRefName: "t3/agent-response-abc12345", - }); - - const service = yield* (BackgroundAgentService as any).make.pipe(Effect.provide(layer)); - - const eventsArray = yield* runAndCollect({ - service, - input: { - threadId: "thread-1", - prNumber: 1, - commentId: "comment-1", - cwd: "/test/repo", - prHeadRef: "refs/t3/pr/1/head", - commentFile: "test.ts", - commentLine: 42, - commentBody: "Fix this", - }, - fakeChild, - exitCode: 0, - }); - - expect(eventsArray.length).toBeGreaterThan(0); - - const statusEvents = eventsArray.filter((e) => e.type === "status"); - expect(statusEvents.length).toBeGreaterThanOrEqual(2); - - const firstStatus = statusEvents[0]; - expect(firstStatus?.agentStatus).toBe("running"); - - const lastStatus = statusEvents[statusEvents.length - 1]; - expect(lastStatus?.agentStatus).toBe("completed"); - - const doneEvents = eventsArray.filter((e) => e.type === "done"); - expect(doneEvents.length).toBe(1); - - const titles = eventsArray.filter((e) => e.type === "detail").map((e) => e.title); - - expect(titles).toContain("PR Diff Context"); - expect(titles).toContain("Agent Prompt"); - expect(titles).toContain("Worktree Created"); - expect(titles).toContain("Changes Detected"); - expect(titles).toContain("Pushed"); - - expect(fs.writeFile).toHaveBeenCalled(); - }).pipe( - Effect.provide( - makeLayer({ - gitDiff: "diff --git a/test.ts b/test.ts\n+test change", - gitStatus: "M test.ts\n", - createWorktreePath: "/tmp/t3-test-worktree", - createWorktreeRefName: "t3/agent-response-abc12345", - }).layer, - ), - )); - - it("updates agentStatus to completed on success", () => - Effect.gen(function* () { - const fakeChild = makeFakeChildProcess(); - vi.mocked(child_process.spawn).mockReturnValue( - fakeChild as unknown as ReturnType, - ); - - const updateMutation = vi.fn(); - const { layer } = makeLayer({ - gitDiff: "test diff", - gitStatus: "M test.ts\n", - createWorktreePath: "/tmp/test", - createWorktreeRefName: "test-branch", - updateMutation, - }); - - const service = yield* (BackgroundAgentService as any).make.pipe(Effect.provide(layer)); - - yield* runAndCollect({ - service, - input: { - threadId: "thread-1", - prNumber: 1, - commentId: "comment-1", - cwd: "/test/repo", - prHeadRef: "refs/heads/main", - commentFile: "test.ts", - commentLine: 42, - commentBody: "Fix this", - }, - fakeChild, - exitCode: 0, - }); - - expect(updateMutation).toHaveBeenCalledWith( - expect.objectContaining({ agentStatus: "running" }), - ); - expect(updateMutation).toHaveBeenCalledWith( - expect.objectContaining({ agentStatus: "completed" }), - ); - expect(updateMutation).toHaveBeenCalledTimes(2); - }).pipe( - Effect.provide( - makeLayer({ - gitDiff: "test diff", - gitStatus: "M test.ts\n", - createWorktreePath: "/tmp/test", - createWorktreeRefName: "test-branch", - }).layer, - ), - )); - - it("handles no changes from agent (no commits)", () => - Effect.gen(function* () { - const fakeChild = makeFakeChildProcess(); - vi.mocked(child_process.spawn).mockReturnValue( - fakeChild as unknown as ReturnType, - ); - - const updateMutation = vi.fn(); - const { layer } = makeLayer({ - gitDiff: "test diff", - gitStatus: "", - createWorktreePath: "/tmp/test", - createWorktreeRefName: "test-branch", - updateMutation, - }); - - const service = yield* (BackgroundAgentService as any).make.pipe(Effect.provide(layer)); - - const eventsArray = yield* runAndCollect({ - service, - input: { - threadId: "thread-1", - prNumber: 1, - commentId: "comment-1", - cwd: "/test/repo", - prHeadRef: "refs/heads/main", - commentFile: "test.ts", - commentLine: 42, - commentBody: "Fix this", - }, - fakeChild, - exitCode: 0, - }); - - const titles = eventsArray.filter((e) => e.type === "detail").map((e) => e.title); - - expect(titles).toContain("No Changes"); - expect(titles).not.toContain("Changes Detected"); - expect(titles).not.toContain("Pushed"); - - expect(updateMutation).toHaveBeenCalledWith( - expect.objectContaining({ agentStatus: "completed" }), - ); - }).pipe( - Effect.provide( - makeLayer({ - gitDiff: "test diff", - gitStatus: "", - createWorktreePath: "/tmp/test", - createWorktreeRefName: "test-branch", - }).layer, - ), - )); - - it("updates agentStatus to failed on createWorktree error", () => - Effect.gen(function* () { - const fakeChild = makeFakeChildProcess(); - vi.mocked(child_process.spawn).mockReturnValue( - fakeChild as unknown as ReturnType, - ); - - const updateMutation = vi.fn(); - const { layer } = makeLayer({ - gitDiff: "test diff", - gitStatus: "M test.ts\n", - createWorktreePath: "/tmp/test", - createWorktreeRefName: "test-branch", - createWorktreeError: new Error("Failed to create worktree"), - updateMutation, - }); - - const service = yield* (BackgroundAgentService as any).make.pipe(Effect.provide(layer)); - - const eventsArray = yield* runAndCollect({ - service, - input: { - threadId: "thread-1", - prNumber: 1, - commentId: "comment-1", - cwd: "/test/repo", - prHeadRef: "refs/heads/main", - commentFile: "test.ts", - commentLine: 42, - commentBody: "Fix this", - }, - fakeChild, - exitCode: 0, - }); - - const failedStatus = eventsArray.find( - (e) => e.type === "status" && e.agentStatus === "failed", - ); - expect(failedStatus).toBeDefined(); - - // Should not reach spawn since createWorktree failed - expect(child_process.spawn).not.toHaveBeenCalled(); - - expect(updateMutation).toHaveBeenCalledWith( - expect.objectContaining({ agentStatus: "running" }), - ); - expect(updateMutation).toHaveBeenCalledWith( - expect.objectContaining({ agentStatus: "failed" }), - ); - }).pipe( - Effect.provide( - makeLayer({ - gitDiff: "test diff", - gitStatus: "M test.ts\n", - createWorktreePath: "/tmp/test", - createWorktreeRefName: "test-branch", - createWorktreeError: new Error("Failed to create worktree"), - }).layer, - ), - )); - - it("updates agentStatus to failed when agent exits with non-zero code", () => - Effect.gen(function* () { - const fakeChild = makeFakeChildProcess(); - vi.mocked(child_process.spawn).mockReturnValue( - fakeChild as unknown as ReturnType, - ); - - const updateMutation = vi.fn(); - const { layer } = makeLayer({ - gitDiff: "test diff", - gitStatus: "", - createWorktreePath: "/tmp/test", - createWorktreeRefName: "test-branch", - updateMutation, - }); - - const service = yield* (BackgroundAgentService as any).make.pipe(Effect.provide(layer)); - - yield* runAndCollect({ - service, - input: { - threadId: "thread-1", - prNumber: 1, - commentId: "comment-1", - cwd: "/test/repo", - prHeadRef: "refs/heads/main", - commentFile: "test.ts", - commentLine: 42, - commentBody: "Fix this", - }, - fakeChild, - exitCode: 1, - }); - - expect(child_process.spawn).toHaveBeenCalled(); - expect(updateMutation).toHaveBeenCalledWith( - expect.objectContaining({ agentStatus: "running" }), - ); - }).pipe( - Effect.provide( - makeLayer({ - gitDiff: "test diff", - gitStatus: "", - createWorktreePath: "/tmp/test", - createWorktreeRefName: "test-branch", - }).layer, - ), - )); - - it("uses origin/HEAD as base ref for PR diff", () => - Effect.gen(function* () { - const fakeChild = makeFakeChildProcess(); - vi.mocked(child_process.spawn).mockReturnValue( - fakeChild as unknown as ReturnType, - ); - - let capturedBaseRef = ""; - let capturedHeadRef = ""; - - const gitWithSpy = GitVcsDriver.of({ - execute: () => - Effect.succeed({ - stdout: "", - stderr: "", - exitCode: 0, - stdoutTruncated: false, - stderrTruncated: false, - } as ExecuteGitResult), - getPrDiff: (cwd: string, baseRef: string, headRef: string) => { - capturedBaseRef = baseRef; - capturedHeadRef = headRef; - return Effect.succeed("test diff"); - }, - getReviewDiffPreview: () => Effect.die("unexpected"), - listRefs: () => Effect.die("unexpected"), - createWorktree: () => Effect.die("unexpected"), - removeWorktree: () => Effect.die("unexpected"), - createRef: () => Effect.die("unexpected"), - switchRef: () => Effect.die("unexpected"), - pullCurrentBranch: () => Effect.die("unexpected"), - renameBranch: () => Effect.die("unexpected"), - } as unknown as GitVcsDriverShape); - - const layer = Layer.mergeAll( - Layer.succeed( - GitWorkflowService, - makeBaseGitWorkflow({ - createWorktreePath: "/tmp/test", - createWorktreeRefName: "test-branch", - }), - ), - Layer.succeed(GitVcsDriver, gitWithSpy), - Layer.succeed(ReviewService, makeBaseReview()), - ); - - const service = yield* (BackgroundAgentService as any).make.pipe(Effect.provide(layer)); - - yield* runAndCollect({ - service, - input: { - threadId: "thread-1", - prNumber: 1, - commentId: "comment-1", - cwd: "/test/repo", - prHeadRef: "refs/t3/pr/1/head", - commentFile: "test.ts", - commentLine: 42, - commentBody: "Fix this", - }, - fakeChild, - exitCode: 0, - }); - - expect(capturedBaseRef).toBe("origin/HEAD"); - expect(capturedHeadRef).toBe("refs/t3/pr/1/head"); - }).pipe( - Effect.provide( - Layer.mergeAll( - Layer.succeed( - GitWorkflowService, - makeBaseGitWorkflow({ - createWorktreePath: "/tmp/test", - createWorktreeRefName: "test-branch", - }), - ), - Layer.succeed( - GitVcsDriver, - GitVcsDriver.of({ - execute: () => - Effect.succeed({ - stdout: "", - stderr: "", - exitCode: 0, - stdoutTruncated: false, - stderrTruncated: false, - } as ExecuteGitResult), - getPrDiff: (cwd: string, baseRef: string, headRef: string) => { - expect(baseRef).toBe("origin/HEAD"); - expect(headRef).toBe("refs/t3/pr/1/head"); - return Effect.succeed("test diff"); - }, - getReviewDiffPreview: () => Effect.die("unexpected"), - listRefs: () => Effect.die("unexpected"), - createWorktree: () => Effect.die("unexpected"), - removeWorktree: () => Effect.die("unexpected"), - createRef: () => Effect.die("unexpected"), - switchRef: () => Effect.die("unexpected"), - pullCurrentBranch: () => Effect.die("unexpected"), - renameBranch: () => Effect.die("unexpected"), - } as unknown as GitVcsDriverShape), - ), - Layer.succeed(ReviewService, makeBaseReview()), - ), - ), - )); - - describe("runBatchAgents", () => { - function createBatchFakeChildrenSpawnMock() { - const children: ReturnType[] = []; - vi.mocked(child_process.spawn).mockImplementation(() => { - const child = makeFakeChildProcess(); - children.push(child); - return child as unknown as ReturnType; - }); - return children; - } - - const batchInput1: Parameters[0] = { - threadId: "thread-1", - prNumber: 1, - commentId: "comment-1", - cwd: "/test/repo", - prHeadRef: "refs/t3/pr/1/head", - commentFile: "test.ts", - commentLine: 42, - commentBody: "Fix this", - }; - - const batchInput2: Parameters[0] = { - threadId: "thread-1", - prNumber: 1, - commentId: "comment-2", - cwd: "/test/repo", - prHeadRef: "refs/t3/pr/1/head", - commentFile: "src/app.ts", - commentLine: 10, - commentBody: "Extract this", - }; - - const batchInput3: Parameters[0] = { - threadId: "thread-1", - prNumber: 1, - commentId: "comment-3", - cwd: "/test/repo", - prHeadRef: "refs/t3/pr/1/head", - commentFile: "src/utils.ts", - commentLine: undefined, - commentBody: "Add type", - }; - - it("runs batch agents in parallel and returns events for all comments", () => - Effect.gen(function* () { - const fakeChildren = createBatchFakeChildrenSpawnMock(); - - const updateMutation = vi.fn(); - const { layer } = makeLayer({ - gitDiff: "test diff", - gitStatus: "", - createWorktreePath: "/tmp/test", - createWorktreeRefName: "test-branch", - updateMutation, - }); - - const service = yield* (BackgroundAgentService as any).make.pipe(Effect.provide(layer)); - - // @effect-diagnostics-next-line runEffectInsideEffect:off - const collectPromise = Effect.runPromise( - service.runBatchAgents([batchInput1, batchInput2, batchInput3]).pipe(Stream.runCollect), - ); - - // @effect-diagnostics-next-line globalTimers:off - yield* Effect.promise(() => new Promise((r) => setTimeout(r, 20))); - - for (const child of fakeChildren) { - child._emitClose(0); - } - - const events = yield* Effect.promise(() => collectPromise); - const eventsArray = Array.from(events); - - expect(eventsArray.length).toBeGreaterThan(0); - - // Verify all commentIds appear in events - const eventCommentIds = new Set(eventsArray.map((e) => e.commentId)); - expect(eventCommentIds.has("comment-1")).toBe(true); - expect(eventCommentIds.has("comment-2")).toBe(true); - expect(eventCommentIds.has("comment-3")).toBe(true); - - // Each comment should get at least a status event - for (const commentId of ["comment-1", "comment-2", "comment-3"]) { - const hasStatus = eventsArray.some( - (e) => e.commentId === commentId && e.type === "status", - ); - expect(hasStatus).toBe(true); - } - - // Each comment should get a done event - for (const commentId of ["comment-1", "comment-2", "comment-3"]) { - const hasDone = eventsArray.some((e) => e.commentId === commentId && e.type === "done"); - expect(hasDone).toBe(true); - } - - expect(updateMutation).toHaveBeenCalledTimes(6); // 2 per comment (running + completed) - }).pipe( - Effect.provide( - makeLayer({ - gitDiff: "test diff", - gitStatus: "", - createWorktreePath: "/tmp/test", - createWorktreeRefName: "test-branch", - }).layer, - ), - )); - - it("single agent failure does not block other agents", () => - Effect.gen(function* () { - const children = createBatchFakeChildrenSpawnMock(); - - const updateMutation = vi.fn(); - const { layer } = makeLayer({ - gitDiff: "test diff", - gitStatus: "", - createWorktreePath: "/tmp/test", - createWorktreeRefName: "test-branch", - updateMutation, - }); - - const service = yield* (BackgroundAgentService as any).make.pipe(Effect.provide(layer)); - - // @effect-diagnostics-next-line runEffectInsideEffect:off - const collectPromise = Effect.runPromise( - service.runBatchAgents([batchInput1, batchInput2, batchInput3]).pipe(Stream.runCollect), - ); - - // @effect-diagnostics-next-line globalTimers:off - yield* Effect.promise(() => new Promise((r) => setTimeout(r, 20))); - - // Fail the first child, succeed the rest - if (children[0]) children[0]._emitClose(1); - for (let i = 1; i < children.length; i++) { - children[i]?._emitClose(0); - } - - const events = yield* Effect.promise(() => collectPromise); - const eventsArray = Array.from(events); - - // comment-2 and comment-3 should complete - const doneIds = eventsArray.filter((e) => e.type === "done").map((e) => e.commentId); - expect(doneIds).toContain("comment-2"); - expect(doneIds).toContain("comment-3"); - - // comment-1 should have error events - const errorEvents = eventsArray.filter( - (e) => e.type === "error" && e.commentId === "comment-1", - ); - expect(errorEvents.length).toBeGreaterThanOrEqual(1); - - // All three comments should get events - const allIds = new Set(eventsArray.map((e) => e.commentId)); - expect(allIds.has("comment-1")).toBe(true); - expect(allIds.has("comment-2")).toBe(true); - expect(allIds.has("comment-3")).toBe(true); - }).pipe( - Effect.provide( - makeLayer({ - gitDiff: "test diff", - gitStatus: "", - createWorktreePath: "/tmp/test", - createWorktreeRefName: "test-branch", - }).layer, - ), - )); - - it("respects concurrency limit", () => - Effect.gen(function* () { - const children = createBatchFakeChildrenSpawnMock(); - const spawnOrder: string[] = []; - // Track spawn calls by tracking when each fake child is created - vi.mocked(child_process.spawn).mockImplementation(() => { - const child = makeFakeChildProcess(); - children.push(child); - spawnOrder.push(`spawn-${children.length}`); - return child as unknown as ReturnType; - }); - - const updateMutation = vi.fn(); - const { layer } = makeLayer({ - gitDiff: "test diff", - gitStatus: "", - createWorktreePath: "/tmp/test", - createWorktreeRefName: "test-branch", - updateMutation, - }); - - const service = yield* (BackgroundAgentService as any).make.pipe(Effect.provide(layer)); - - // Run 5 agents with max concurrency 2 - const inputs = [ - { ...batchInput1, commentId: "c-1" }, - { ...batchInput1, commentId: "c-2" }, - { ...batchInput1, commentId: "c-3" }, - { ...batchInput1, commentId: "c-4" }, - { ...batchInput1, commentId: "c-5" }, - ]; - - // @effect-diagnostics-next-line runEffectInsideEffect:off - const collectPromise = Effect.runPromise( - service.runBatchAgents(inputs, 2).pipe(Stream.runCollect), - ); - - // @effect-diagnostics-next-line globalTimers:off - yield* Effect.promise(() => new Promise((r) => setTimeout(r, 20))); - - // Close all children - for (const child of children) { - child._emitClose(0); - } - - const events = yield* Effect.promise(() => collectPromise); - const eventsArray = Array.from(events); - - // All 5 comments should have events - for (const cid of ["c-1", "c-2", "c-3", "c-4", "c-5"]) { - const hasEvent = eventsArray.some((e) => e.commentId === cid); - expect(hasEvent).toBe(true); - } - - // Verify spawn was called for all 5 - expect(child_process.spawn).toHaveBeenCalledTimes(5); - }).pipe( - Effect.provide( - makeLayer({ - gitDiff: "test diff", - gitStatus: "", - createWorktreePath: "/tmp/test", - createWorktreeRefName: "test-branch", - }).layer, - ), - )); - - it("runBatchAgents with empty inputs completes immediately", () => - Effect.gen(function* () { - const updateMutation = vi.fn(); - const { layer } = makeLayer({ - gitDiff: "test diff", - gitStatus: "", - createWorktreePath: "/tmp/test", - createWorktreeRefName: "test-branch", - updateMutation, - }); - - const service = yield* (BackgroundAgentService as any).make.pipe(Effect.provide(layer)); - - const events = yield* service.runBatchAgents([]).pipe(Stream.runCollect); - - const eventsArray = Array.from(events); - expect(eventsArray).toHaveLength(0); - expect(child_process.spawn).not.toHaveBeenCalled(); - }).pipe( - Effect.provide( - makeLayer({ - gitDiff: "test diff", - gitStatus: "", - createWorktreePath: "/tmp/test", - createWorktreeRefName: "test-branch", - }).layer, - ), - )); - - it("uses DEFAULT_MAX_CONCURRENT_AGENTS when maxConcurrent is not specified", () => - Effect.gen(function* () { - expect(DEFAULT_MAX_CONCURRENT_AGENTS).toBe(3); - })); - }); -}); diff --git a/apps/server/src/review/BackgroundAgentService.ts b/apps/server/src/review/BackgroundAgentService.ts deleted file mode 100644 index adf176d5bf7a..000000000000 --- a/apps/server/src/review/BackgroundAgentService.ts +++ /dev/null @@ -1,473 +0,0 @@ -// TODO: Replace raw child_process/fs usage with the Effect platform services once -// the agent execution is routed through ProviderService (see TODO below). -// @effect-diagnostics-next-line nodeBuiltinImport:off -import * as child_process from "node:child_process"; - -import * as Clock from "effect/Clock"; -import * as Context from "effect/Context"; -import * as Duration from "effect/Duration"; -import * as Effect from "effect/Effect"; -import * as Layer from "effect/Layer"; -import * as Queue from "effect/Queue"; -import * as Ref from "effect/Ref"; -import * as Stream from "effect/Stream"; - -import { - ChangeRequestRunBackgroundAgentError, - DEFAULT_SERVER_SETTINGS, - type BackgroundAgentResponseEvent, - type ProviderDriverKind, - type ServerSettings, - type VcsCreateWorktreeResult, -} from "@t3tools/contracts"; - -import { GitWorkflowService } from "../git/GitWorkflowService.ts"; -import { GitVcsDriver } from "../vcs/GitVcsDriver.ts"; -import { ReviewService } from "./ReviewService.ts"; - -export const DEFAULT_MAX_CONCURRENT_AGENTS = 3; - -const AGENT_PROMPT_TEMPLATE = ` -You are a code review assistant. A developer has left a review comment on a pull request. - -## PR Diff Context -{diff} - -## Comment to respond to -The following comment was left on \`{commentFile}\`{commentLine}: - -> {commentBody} - -## Instructions -1. Read and understand the comment and the PR diff context. -2. Explain your understanding of the issue raised in the comment. -3. Implement a fix for the issue described in the comment. -4. Keep changes minimal and focused — only fix what the comment asks for. -5. After making changes, explain what you did. - -Respond with a clear explanation first, then implement the fix. DO NOT ask questions — just explain and implement. -`.trim(); - -function buildPrompt(input: { - diff: string; - commentFile: string; - commentLine: number | undefined; - commentBody: string; -}): string { - return AGENT_PROMPT_TEMPLATE.replace("{diff}", input.diff) - .replace("{commentFile}", input.commentFile) - .replace( - "{commentLine}", - typeof input.commentLine === "number" ? ` (line ${input.commentLine})` : "", - ) - .replace("{commentBody}", input.commentBody); -} - -export interface RunBackgroundAgentInput { - readonly threadId: string; - readonly prNumber: number; - readonly commentId: string; - readonly cwd: string; - readonly prHeadRef: string; - readonly commentFile: string; - readonly commentLine: number | undefined; - readonly commentBody: string; -} - -export interface BackgroundAgentServiceShape { - readonly runBackgroundAgent: ( - input: RunBackgroundAgentInput, - ) => Stream.Stream; - readonly runBatchAgents: ( - inputs: readonly RunBackgroundAgentInput[], - maxConcurrent?: number, - ) => Stream.Stream; -} - -function fail( - kind: ChangeRequestRunBackgroundAgentError["kind"], - detail: string, - cause?: unknown, -): ChangeRequestRunBackgroundAgentError { - return new ChangeRequestRunBackgroundAgentError({ - kind, - detail, - cause, - }); -} - -/** - * CLI args for each supported provider in one-shot mode. - * `__CWD__` is replaced with the worktree path at spawn time. - */ -function getAgentCliArgs(kind: ProviderDriverKind): ReadonlyArray { - if (kind === "opencode") { - return [ - "--dir", - "__CWD__", - "run", - "--dangerously-skip-permissions", - "-m", - "opencode/deepseek-v4-flash-free", - ]; - } - if (kind === "claudeAgent") { - return ["-p", "--dangerously-skip-permissions"]; - } - return []; -} - -/** - * Read the binary path from settings for a given provider kind. - */ -function resolveAgentBinary(providerKind: ProviderDriverKind, settings: ServerSettings): string { - if (providerKind === "opencode") return settings.providers.opencode.binaryPath ?? "opencode"; - if (providerKind === "claudeAgent") return settings.providers.claudeAgent.binaryPath ?? "claude"; - return "opencode"; -} - -const make = Effect.fn("makeBackgroundAgentService")(function* () { - yield* Effect.logDebug("backgroundAgentService.make start"); - const git = yield* GitVcsDriver; - const gitWorkflow = yield* GitWorkflowService; - const review = yield* ReviewService; - yield* Effect.logDebug("backgroundAgentService.make dependencies ready"); - - const runBackgroundAgent: BackgroundAgentServiceShape["runBackgroundAgent"] = (input) => - Stream.callback((queue) => - Effect.gen(function* () { - const offer = (event: BackgroundAgentResponseEvent) => - Queue.offer(queue, event).pipe(Effect.asVoid); - - let worktree: VcsCreateWorktreeResult | null = null; - - const cleanup = () => - worktree - ? gitWorkflow - .removeWorktree({ - cwd: input.cwd, - path: worktree.worktree.path, - force: true, - }) - .pipe(Effect.ignore) - : Effect.void; - - const finalizeWithStatus = (agentStatus: "completed" | "failed", errorMessage?: string) => - Effect.gen(function* () { - yield* cleanup(); - yield* review - .updateCommentAgentStatus({ - threadId: input.threadId, - prNumber: input.prNumber, - commentId: input.commentId, - agentStatus, - }) - .pipe(Effect.ignore); - yield* offer({ - type: "status", - commentId: input.commentId, - agentStatus, - }); - if (errorMessage) { - yield* offer({ - type: "error", - commentId: input.commentId, - message: errorMessage, - }); - } - yield* offer({ - type: "done", - commentId: input.commentId, - }); - yield* Queue.end(queue); - }); - - const runAgent = Effect.gen(function* () { - yield* review - .updateCommentAgentStatus({ - threadId: input.threadId, - prNumber: input.prNumber, - commentId: input.commentId, - agentStatus: "running", - }) - .pipe(Effect.ignore); - - yield* offer({ - type: "status", - commentId: input.commentId, - agentStatus: "running", - }); - - const diffResult = yield* git - .getPrDiff(input.cwd, "origin/HEAD", input.prHeadRef) - .pipe( - Effect.mapError((cause) => - fail("agent-failed", `Failed to get PR diff: ${cause.message}`, cause), - ), - ); - - yield* offer({ - type: "detail", - commentId: input.commentId, - title: "PR Diff Context", - content: diffResult, - }); - - const prompt = buildPrompt({ - diff: diffResult, - commentFile: input.commentFile, - commentLine: input.commentLine, - commentBody: input.commentBody, - }); - - yield* offer({ - type: "detail", - commentId: input.commentId, - title: "Agent Prompt", - content: prompt, - }); - - const now = yield* Clock.currentTimeMillis; - const tempBranch = `t3/agent-response-${input.commentId.slice(0, 8)}-${now}`; - worktree = yield* gitWorkflow - .createWorktree({ - cwd: input.cwd, - refName: input.prHeadRef, - newRefName: tempBranch, - path: null, - }) - .pipe( - Effect.mapError((cause) => - fail("agent-failed", `Failed to create worktree: ${cause.message}`, cause), - ), - ); - - const worktreePath = worktree.worktree.path; - yield* offer({ - type: "detail", - commentId: input.commentId, - title: "Worktree Created", - content: `Created worktree at ${worktreePath} on branch ${tempBranch}`, - }); - - // Agent binary and CLI args — defaults to opencode. - // To use a different agent, the caller can extend RunBackgroundAgentInput - // with a `providerInstanceId` or `modelSelection` field. - const agentKind = "opencode" as ProviderDriverKind; - const binaryPath = resolveAgentBinary(agentKind, DEFAULT_SERVER_SETTINGS); - const argsTemplate = getAgentCliArgs(agentKind); - const args = [...argsTemplate.map((a) => (a === "__CWD__" ? worktreePath : a)), prompt]; - - yield* offer({ - type: "detail", - commentId: input.commentId, - title: "Running Agent", - content: `Executing agent (${agentKind}) in ${worktreePath}...`, - }); - - const combinedOutputRef = yield* Ref.make(""); - const AGENT_TIMEOUT_MS = 2 * 60 * 1000; - - const safeOffer = (event: BackgroundAgentResponseEvent) => - Effect.runFork(Queue.offer(queue, event)); - - const runAgentProcess = Effect.callback( - (resume) => { - let resolved = false; - let child: child_process.ChildProcess; - try { - child = child_process.spawn(binaryPath, args, { - cwd: worktreePath, - env: { ...process.env }, - stdio: ["ignore", "pipe", "pipe"], - }); - } catch (err: unknown) { - const message = err instanceof Error ? err.message : String(err); - safeOffer({ - type: "detail", - commentId: input.commentId, - title: "Agent Spawn Error", - content: `Failed to spawn agent: ${message}`, - }); - resume( - Effect.fail( - fail("agent-failed", `Failed to spawn agent process: ${message}`, err), - ), - ); - return; - } - - child.stdout?.on("data", (chunk: Buffer) => { - const text = chunk.toString("utf-8"); - Effect.runFork(Ref.update(combinedOutputRef, (prev) => prev + text)); - safeOffer({ - type: "text", - commentId: input.commentId, - content: text, - }); - }); - - child.stderr?.on("data", (chunk: Buffer) => { - const text = chunk.toString("utf-8"); - Effect.runFork(Ref.update(combinedOutputRef, (prev) => prev + text)); - safeOffer({ - type: "detail", - commentId: input.commentId, - title: "Agent stderr", - content: text, - }); - }); - - child.on("close", (code: number | null) => { - if (!resolved) { - resolved = true; - resume(Effect.succeed(code ?? 0)); - } - }); - - child.on("error", (err) => { - if (!resolved) { - resolved = true; - safeOffer({ - type: "detail", - commentId: input.commentId, - title: "Agent Error", - content: `Agent spawn error: ${err.message}`, - }); - resume(Effect.succeed(127)); - } - }); - }, - ); - - const exitCode = yield* runAgentProcess.pipe( - Effect.timeout(Duration.millis(AGENT_TIMEOUT_MS)), - Effect.mapError((cause) => { - const detail = - cause instanceof Error && cause.message - ? cause.message - : typeof cause === "object" && cause !== null && "_tag" in cause - ? ((cause as { _tag: string })._tag ?? "unknown") - : cause != null - ? String(cause) - : "Agent process timed out or failed with an unknown error"; - return fail("agent-failed", `Agent process failed or timed out: ${detail}`, cause); - }), - ); - - if (exitCode !== 0) { - const combinedOutput = yield* Ref.get(combinedOutputRef); - yield* offer({ - type: "detail", - commentId: input.commentId, - title: "Agent Exit", - content: `Agent exited with code ${exitCode}. Output: ${combinedOutput.slice(0, 1000)}`, - }); - } - - const statusResult = yield* git - .execute({ - operation: "backgroundAgent.checkStatus", - cwd: worktreePath, - args: ["status", "--porcelain"], - }) - .pipe(Effect.orElseSucceed(() => ({ stdout: "" }))); - - if (statusResult.stdout.trim()) { - yield* offer({ - type: "detail", - commentId: input.commentId, - title: "Changes Detected", - content: statusResult.stdout, - }); - - yield* git - .execute({ - operation: "backgroundAgent.commit", - cwd: worktreePath, - args: ["add", "-A"], - }) - .pipe(Effect.ignore); - - yield* git - .execute({ - operation: "backgroundAgent.commit", - cwd: worktreePath, - args: ["commit", "-m", `Agent response to comment ${input.commentId.slice(0, 8)}`], - }) - .pipe(Effect.ignore); - - const remoteBranch = `refs/heads/${tempBranch}`; - yield* git - .execute({ - operation: "backgroundAgent.push", - cwd: worktreePath, - args: ["push", "origin", `${tempBranch}:${remoteBranch}`], - }) - .pipe(Effect.ignore); - - yield* offer({ - type: "detail", - commentId: input.commentId, - title: "Pushed", - content: `Pushed changes to branch ${tempBranch}`, - }); - } else { - yield* offer({ - type: "detail", - commentId: input.commentId, - title: "No Changes", - content: "Agent did not produce any file changes.", - }); - } - - yield* finalizeWithStatus("completed"); - }); - - yield* runAgent.pipe(Effect.catch((error) => finalizeWithStatus("failed", error.detail))); - }), - ); - - const runBatchAgents: BackgroundAgentServiceShape["runBatchAgents"] = (inputs, maxConcurrent) => - Stream.callback( - (outputQueue) => - Effect.gen(function* () { - const concurrency = maxConcurrent ?? DEFAULT_MAX_CONCURRENT_AGENTS; - - if (inputs.length === 0) { - yield* Queue.end(outputQueue); - return; - } - - yield* Effect.forEach( - inputs, - (input) => - runBackgroundAgent(input).pipe( - Stream.runForEach((event) => Queue.offer(outputQueue, event)), - Effect.catch((error) => - Queue.offer(outputQueue, { - type: "error" as const, - commentId: input.commentId, - message: error.detail, - }), - ), - ), - { concurrency }, - ); - - yield* Queue.end(outputQueue); - }), - ); - - return { - runBackgroundAgent, - runBatchAgents, - } satisfies BackgroundAgentServiceShape; -}); - -export class BackgroundAgentService extends Context.Service< - BackgroundAgentService, - BackgroundAgentServiceShape ->()("t3/review/BackgroundAgentService", { make: make() }) {} - -export const layer = Layer.effect(BackgroundAgentService, BackgroundAgentService.make); diff --git a/apps/server/src/review/ReviewDraftStore.test.ts b/apps/server/src/review/ReviewDraftStore.test.ts deleted file mode 100644 index a5e162b4fdd3..000000000000 --- a/apps/server/src/review/ReviewDraftStore.test.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { describe, it, expect } from "vite-plus/test"; -import * as Effect from "effect/Effect"; -import * as Layer from "effect/Layer"; -import * as Option from "effect/Option"; -import type { ReviewComment, ReviewDraft } from "@t3tools/contracts"; - -import * as NodeServices from "@effect/platform-node/NodeServices"; -import * as ReviewDraftStore from "./ReviewDraftStore.ts"; -import { ServerConfig } from "../config.ts"; - -function makeLayer() { - return ReviewDraftStore.layer.pipe( - Layer.provide(ServerConfig.layerTest("test-cwd", { prefix: "t3-review-draft-store-" })), - Layer.provideMerge(NodeServices.layer), - ); -} - -const testComment: ReviewComment = { - id: "comment-1", - file: "src/app.ts", - line: 42, - commitSHA: "abc123", - body: "Consider renaming this variable.", - author: { login: "codex-bot" }, - createdAt: "2025-06-01T12:00:00Z", -}; - -const testDraft: ReviewDraft = { - threadId: "thread-1", - prNumber: 42, - prHeadSHA: "abc123", - comments: [testComment], - state: "draft", -}; - -describe("ReviewDraftStore", () => { - it("get returns none for unknown draft", () => - Effect.gen(function* () { - const store = yield* ReviewDraftStore.ReviewDraftStore; - const result = yield* store.get("unknown", 1); - expect(Option.isNone(result)).toBe(true); - }).pipe(Effect.provide(makeLayer()))); - - it("round-trip: upsert then get", () => - Effect.gen(function* () { - const store = yield* ReviewDraftStore.ReviewDraftStore; - yield* store.upsert(testDraft); - - const result = yield* store.get("thread-1", 42); - expect(Option.getOrNull(result)).toEqual(testDraft); - }).pipe(Effect.provide(makeLayer()))); - - it("delete removes a draft", () => - Effect.gen(function* () { - const store = yield* ReviewDraftStore.ReviewDraftStore; - yield* store.upsert(testDraft); - yield* store.delete("thread-1", 42); - - const result = yield* store.get("thread-1", 42); - expect(Option.isNone(result)).toBe(true); - }).pipe(Effect.provide(makeLayer()))); - - it("upsert overwrites existing draft", () => - Effect.gen(function* () { - const store = yield* ReviewDraftStore.ReviewDraftStore; - - yield* store.upsert(testDraft); - - const updatedDraft: ReviewDraft = { - threadId: "thread-1", - prNumber: 42, - prHeadSHA: "def456", - comments: [ - { - id: "comment-2", - file: "src/app.ts", - commitSHA: "def456", - body: "Also fix this typo.", - author: { login: "codex-bot" }, - createdAt: "2025-06-02T12:00:00Z", - }, - ], - state: "draft", - }; - yield* store.upsert(updatedDraft); - - const result = yield* store.get("thread-1", 42); - const value = Option.getOrNull(result); - expect(value?.prHeadSHA).toBe("def456"); - expect(value?.comments).toHaveLength(1); - expect(value?.comments[0]?.id).toBe("comment-2"); - }).pipe(Effect.provide(makeLayer()))); -}); diff --git a/apps/server/src/review/ReviewDraftStore.ts b/apps/server/src/review/ReviewDraftStore.ts deleted file mode 100644 index 0d75a10ca153..000000000000 --- a/apps/server/src/review/ReviewDraftStore.ts +++ /dev/null @@ -1,98 +0,0 @@ -import * as Context from "effect/Context"; -import * as Effect from "effect/Effect"; -import * as FileSystem from "effect/FileSystem"; -import * as Layer from "effect/Layer"; -import * as Option from "effect/Option"; -import * as Path from "effect/Path"; -import type { ReviewDraft } from "@t3tools/contracts"; - -import { writeFileStringAtomically } from "../atomicWrite.ts"; -import { ServerConfig } from "../config.ts"; - -export interface ReviewDraftStoreShape { - readonly get: ( - threadId: string, - prNumber: number, - ) => Effect.Effect, never>; - readonly upsert: (draft: ReviewDraft) => Effect.Effect; - readonly delete: (threadId: string, prNumber: number) => Effect.Effect; -} - -export class ReviewDraftStore extends Context.Service()( - "t3/review/ReviewDraftStore", -) {} - -export const make = Effect.fn("makeReviewDraftStore")(function* () { - const config = yield* ServerConfig; - const fs = yield* FileSystem.FileSystem; - const path = yield* Path.Path; - - const persistPath = path.join(config.stateDir, "review-drafts.json"); - const drafts = new Map(); - - yield* fs - .makeDirectory(config.stateDir, { recursive: true }) - .pipe(Effect.orElseSucceed(() => undefined)); - - const exists = yield* fs.exists(persistPath).pipe(Effect.orElseSucceed(() => false)); - if (exists) { - const raw = yield* fs.readFileString(persistPath).pipe(Effect.orElseSucceed(() => "{}")); - // @effect-diagnostics-next-line tryCatchInEffectGen:off - try { - // @effect-diagnostics-next-line preferSchemaOverJson:off - const parsed = JSON.parse(raw) as Record; - for (const [k, v] of Object.entries(parsed)) { - drafts.set(k, v); - } - } catch { - drafts.clear(); - } - } - - const persist = () => - Effect.gen(function* () { - const obj: Record = {}; - for (const [k, v] of drafts) { - obj[k] = v; - } - // @effect-diagnostics-next-line tryCatchInEffectGen:off - try { - // @effect-diagnostics-next-line preferSchemaOverJson:off - const contents = JSON.stringify(obj); - yield* writeFileStringAtomically({ filePath: persistPath, contents }); - } catch { - // Best-effort persistence - } - }).pipe(Effect.catch(() => Effect.void)); - - const key = (threadId: string, prNumber: number) => `${threadId}:${prNumber}`; - - return ReviewDraftStore.of({ - get: (threadId, prNumber) => - Effect.sync(() => Option.fromNullishOr(drafts.get(key(threadId, prNumber)))), - upsert: (draft) => - Effect.sync(() => { - drafts.set(key(draft.threadId, draft.prNumber), draft); - }).pipe( - Effect.tap(() => - persist().pipe( - Effect.provideService(FileSystem.FileSystem, fs), - Effect.provideService(Path.Path, path), - ), - ), - ), - delete: (threadId, prNumber) => - Effect.sync(() => { - drafts.delete(key(threadId, prNumber)); - }).pipe( - Effect.tap(() => - persist().pipe( - Effect.provideService(FileSystem.FileSystem, fs), - Effect.provideService(Path.Path, path), - ), - ), - ), - }); -}); - -export const layer = Layer.effect(ReviewDraftStore, make()); diff --git a/apps/server/src/review/ReviewService.ts b/apps/server/src/review/ReviewService.ts index f83c7079ee86..63f1d1332135 100644 --- a/apps/server/src/review/ReviewService.ts +++ b/apps/server/src/review/ReviewService.ts @@ -3,16 +3,11 @@ import * as DateTime from "effect/DateTime"; import * as Effect from "effect/Effect"; import * as FileSystem from "effect/FileSystem"; import * as Layer from "effect/Layer"; -import * as Option from "effect/Option"; import * as Path from "effect/Path"; import { - ChangeRequestSubmitReviewError, VcsRepositoryDetectionError, VcsUnsupportedOperationError, - type ReviewComment, - type ReviewCommentAgentStatus, - type ReviewDraft, type ReviewDiffPreviewError, type ReviewDiffPreviewInput, type ReviewDiffPreviewResult, @@ -21,40 +16,11 @@ import { import { ServerConfig } from "../config.ts"; import * as GitVcsDriver from "../vcs/GitVcsDriver.ts"; import * as VcsDriverRegistry from "../vcs/VcsDriverRegistry.ts"; -import * as ReviewDraftStore from "./ReviewDraftStore.ts"; -import * as GitHubCli from "../sourceControl/GitHubCli.ts"; export interface ReviewServiceShape { readonly getDiffPreview: ( input: ReviewDiffPreviewInput, ) => Effect.Effect; - readonly getReviewDraft: (input: { - readonly threadId: string; - readonly prNumber: number; - readonly cwd?: string | undefined; - }) => Effect.Effect; - readonly upsertReviewComment: (input: { - readonly threadId: string; - readonly prNumber: number; - readonly prHeadSHA: string; - readonly comment: ReviewComment; - }) => Effect.Effect; - readonly deleteReviewComment: (input: { - readonly threadId: string; - readonly prNumber: number; - readonly commentId: string; - }) => Effect.Effect; - readonly submitReview: (input: { - readonly threadId: string; - readonly prNumber: number; - readonly cwd?: string | undefined; - }) => Effect.Effect; - readonly updateCommentAgentStatus: (input: { - readonly threadId: string; - readonly prNumber: number; - readonly commentId: string; - readonly agentStatus: ReviewCommentAgentStatus; - }) => Effect.Effect; } export class ReviewService extends Context.Service()( @@ -62,30 +28,11 @@ export class ReviewService extends Context.Service fileSystem.realPath(path.resolve(value)).pipe(Effect.orElseSucceed(() => path.resolve(value))); @@ -144,272 +91,9 @@ export const make = Effect.fn("makeReviewService")(function* () { return yield* getDriverDiffPreview(input); }); - const getReviewDraft: ReviewServiceShape["getReviewDraft"] = Effect.fn( - "ReviewService.getReviewDraft", - )((input) => - Effect.gen(function* () { - const localDraftOption = yield* draftStore.get(input.threadId, input.prNumber); - - let githubComments: ReviewComment[] = []; - if (input.cwd && Option.isSome(githubCliOption)) { - const cli = githubCliOption.value; - const reviews = yield* cli - .getPullRequestReviews({ - cwd: input.cwd, - reference: String(input.prNumber), - }) - .pipe(Effect.orElseSucceed(() => ({ comments: [] }))); - githubComments = reviews.comments.map(mapGitHubCommentToReviewComment); - } - - const existingDraft = Option.getOrNull(localDraftOption); - - if (!existingDraft && githubComments.length === 0) return null; - - const localCommentIds = new Set(existingDraft?.comments.map((c) => c.id) ?? []); - const mergedComments = [ - ...githubComments.filter((c) => !localCommentIds.has(c.id)), - ...(existingDraft?.comments ?? []), - ]; - - return { - threadId: input.threadId, - prNumber: input.prNumber, - prHeadSHA: existingDraft?.prHeadSHA ?? "", - comments: mergedComments, - state: existingDraft?.state ?? ("draft" as const), - } satisfies ReviewDraft; - }), - ); - - const upsertReviewComment: ReviewServiceShape["upsertReviewComment"] = Effect.fn( - "ReviewService.upsertReviewComment", - )((input) => - draftStore.get(input.threadId, input.prNumber).pipe( - Effect.flatMap((option) => { - const existingDraft = Option.getOrNull(option); - const draft: ReviewDraft = existingDraft - ? { - ...existingDraft, - prHeadSHA: input.prHeadSHA, - comments: [ - ...existingDraft.comments.filter((c) => c.id !== input.comment.id), - input.comment, - ], - } - : { - threadId: input.threadId, - prNumber: input.prNumber, - prHeadSHA: input.prHeadSHA, - comments: [input.comment], - state: "draft" as const, - }; - - return draftStore.upsert(draft).pipe(Effect.as(draft)); - }), - ), - ); - - const deleteReviewComment: ReviewServiceShape["deleteReviewComment"] = Effect.fn( - "ReviewService.deleteReviewComment", - )((input) => - draftStore.get(input.threadId, input.prNumber).pipe( - Effect.flatMap((option) => { - const existingDraft = Option.getOrNull(option); - if (!existingDraft) { - return Effect.succeed(null); - } - - const updatedComments = existingDraft.comments.filter((c) => c.id !== input.commentId); - - if (updatedComments.length === 0) { - return draftStore - .delete(input.threadId, input.prNumber) - .pipe(Effect.as(null)); - } - - const draft: ReviewDraft = { - ...existingDraft, - comments: updatedComments, - }; - - return draftStore.upsert(draft).pipe(Effect.as(draft)); - }), - ), - ); - - const submitReview: ReviewServiceShape["submitReview"] = Effect.fn("ReviewService.submitReview")( - (input) => - Effect.gen(function* () { - const localDraftOption = yield* draftStore.get(input.threadId, input.prNumber); - if (Option.isNone(localDraftOption)) { - return yield* new ChangeRequestSubmitReviewError({ - kind: "no-draft", - detail: "No draft review comments to submit.", - }); - } - - const draft = localDraftOption.value; - if (draft.comments.length === 0) { - return yield* new ChangeRequestSubmitReviewError({ - kind: "no-draft", - detail: "No draft review comments to submit.", - }); - } - - if (Option.isNone(githubCliOption) || !input.cwd) { - return yield* new ChangeRequestSubmitReviewError({ - kind: "not-a-repo", - detail: "Cannot submit review: missing GitHub CLI or worktree path.", - }); - } - - const cli = githubCliOption.value; - - const localComments = draft.comments.filter((c) => c.author.login === "local"); - - if (localComments.length === 0) { - return yield* new ChangeRequestSubmitReviewError({ - kind: "no-draft", - detail: "No local draft review comments to submit.", - }); - } - - // Separate line-specific comments from file-level comments. - // Line comments go into the GitHub API `comments` array (visible in - // "Files changed" tab pinned to the line). File-level comments go in - // the review `body` (visible in the "Conversation" tab). - const lineComments = localComments.filter((c) => typeof c.line === "number"); - const fileComments = localComments.filter((c) => typeof c.line !== "number"); - - const body = fileComments.map((c) => `**${c.file}**\n\n${c.body}`).join("\n\n---\n\n"); - - const apiComments = lineComments.map((c) => ({ - path: c.file, - line: c.line, - side: "RIGHT", - body: c.body, - })); - - const payload = { - event: "COMMENT", - body, - commit_id: draft.prHeadSHA, - ...(apiComments.length > 0 ? { comments: apiComments } : {}), - }; - - // Write JSON payload to a temporary file - yield* fileSystem - .makeDirectory(path.join(config.stateDir, "tmp"), { - recursive: true, - }) - .pipe(Effect.orElseSucceed(() => undefined)); - const commentsJsonFile = path.join( - config.stateDir, - "tmp", - `review-comments-${input.threadId}-${input.prNumber}.json`, - ); - yield* fileSystem - .writeFileString(commentsJsonFile, JSON.stringify(payload)) - .pipe(Effect.orElseSucceed(() => undefined)); - - // Submit via gh api for inline comments, fall back to gh pr review - const submitEffect = - apiComments.length > 0 - ? cli.createPullRequestReviewWithComments({ - cwd: input.cwd, - reference: String(input.prNumber), - commentsJsonFile, - }) - : cli.createPullRequestReview({ - cwd: input.cwd, - reference: String(input.prNumber), - bodyFile: commentsJsonFile, - }); - - yield* submitEffect.pipe( - Effect.mapError( - (cause) => - new ChangeRequestSubmitReviewError({ - kind: "review-failed", - detail: cause.message, - cause, - }), - ), - Effect.ensuring( - fileSystem.remove(commentsJsonFile).pipe(Effect.catch(() => Effect.void)), - ), - ); - - // Fetch fresh GitHub comments to merge with published local comments - const reviews = yield* cli - .getPullRequestReviews({ - cwd: input.cwd, - reference: String(input.prNumber), - }) - .pipe(Effect.orElseSucceed(() => ({ comments: [] }))); - const githubComments = reviews.comments.map(mapGitHubCommentToReviewComment); - - // Merge: local comments are marked as published (no longer "local" author) - // so future submissions won't re-post them. GitHub comments fill in any extras. - const localIds = new Set(localComments.map((c) => c.id)); - const mergedComments = [ - ...localComments.map((c) => ({ - ...c, - author: { login: "local-published" }, - })), - ...githubComments.filter((c) => !localIds.has(c.id)), - ]; - - const publishedDraft: ReviewDraft = { - threadId: input.threadId, - prNumber: input.prNumber, - prHeadSHA: draft.prHeadSHA, - comments: mergedComments, - state: "draft", - }; - - // Replace local draft - yield* draftStore.upsert(publishedDraft).pipe(Effect.orElseSucceed(() => undefined)); - - return publishedDraft; - }), - ); - - const updateCommentAgentStatus: ReviewServiceShape["updateCommentAgentStatus"] = Effect.fn( - "ReviewService.updateCommentAgentStatus", - )((input) => - draftStore.get(input.threadId, input.prNumber).pipe( - Effect.flatMap((option) => { - const existingDraft = Option.getOrNull(option); - if (!existingDraft) { - return Effect.succeed(null); - } - - const updatedComments = existingDraft.comments.map((c) => - c.id === input.commentId ? { ...c, agentStatus: input.agentStatus } : c, - ); - - const draft: ReviewDraft = { - ...existingDraft, - comments: updatedComments, - }; - - return draftStore.upsert(draft).pipe(Effect.as(draft)); - }), - ), - ); - return ReviewService.of({ getDiffPreview, - getReviewDraft, - upsertReviewComment, - deleteReviewComment, - submitReview, - updateCommentAgentStatus, }); }); -export const layer = Layer.effect(ReviewService, make()).pipe( - Layer.provideMerge(ReviewDraftStore.layer), -); +export const layer = Layer.effect(ReviewService, make()); diff --git a/apps/server/src/review/ReviewServiceDraft.test.ts b/apps/server/src/review/ReviewServiceDraft.test.ts deleted file mode 100644 index 6ae848315649..000000000000 --- a/apps/server/src/review/ReviewServiceDraft.test.ts +++ /dev/null @@ -1,584 +0,0 @@ -import { describe, it, expect, vi } from "vite-plus/test"; -import * as Effect from "effect/Effect"; -import * as Layer from "effect/Layer"; -import * as FileSystem from "effect/FileSystem"; -import type { ReviewComment, ReviewDraft } from "@t3tools/contracts"; - -import * as NodeServices from "@effect/platform-node/NodeServices"; -import * as ReviewService from "./ReviewService.ts"; -import * as ReviewDraftStore from "./ReviewDraftStore.ts"; -import * as GitHubCli from "../sourceControl/GitHubCli.ts"; -import { ServerConfig } from "../config.ts"; - -function makeLayer() { - return ReviewService.layer.pipe( - Layer.provide(ServerConfig.layerTest("test-cwd", { prefix: "t3-review-draft-service-" })), - Layer.provideMerge(NodeServices.layer), - ); -} - -const testComment: ReviewComment = { - id: "comment-1", - file: "src/app.ts", - line: 42, - commitSHA: "abc123", - body: "Consider renaming this variable.", - author: { login: "codex-bot" }, - createdAt: "2025-06-01T12:00:00Z", -}; - -const testComment2: ReviewComment = { - id: "comment-2", - file: "src/utils.ts", - commitSHA: "abc123", - body: "Extract this into a helper function.", - agentStatus: "running", - author: { login: "codex-bot" }, - createdAt: "2025-06-01T12:05:00Z", -}; - -describe("ReviewService review drafts", () => { - it("getReviewDraft returns null for unknown draft", () => - Effect.gen(function* () { - const review = yield* ReviewService.ReviewService; - const result = yield* review.getReviewDraft({ threadId: "unknown", prNumber: 1 }); - expect(result).toBeNull(); - }).pipe(Effect.provide(makeLayer()))); - - it("round-trip: upsert → getReviewDraft → delete → getReviewDraft", () => - Effect.gen(function* () { - const review = yield* ReviewService.ReviewService; - - const upserted = yield* review.upsertReviewComment({ - threadId: "thread-1", - prNumber: 42, - prHeadSHA: "abc123", - comment: testComment, - }); - - expect(upserted.threadId).toBe("thread-1"); - expect(upserted.comments).toHaveLength(1); - expect(upserted.comments[0]?.id).toBe("comment-1"); - - const draft = yield* review.getReviewDraft({ threadId: "thread-1", prNumber: 42 }); - expect(draft).not.toBeNull(); - expect(draft?.comments).toHaveLength(1); - - const afterDelete = yield* review.deleteReviewComment({ - threadId: "thread-1", - prNumber: 42, - commentId: "comment-1", - }); - expect(afterDelete).toBeNull(); - - const emptyDraft = yield* review.getReviewDraft({ threadId: "thread-1", prNumber: 42 }); - expect(emptyDraft).toBeNull(); - }).pipe(Effect.provide(makeLayer()))); - - it("upsertReviewComment adds new comment to existing draft", () => - Effect.gen(function* () { - const review = yield* ReviewService.ReviewService; - - yield* review.upsertReviewComment({ - threadId: "thread-2", - prNumber: 99, - prHeadSHA: "sha1", - comment: testComment, - }); - - const upserted = yield* review.upsertReviewComment({ - threadId: "thread-2", - prNumber: 99, - prHeadSHA: "sha1", - comment: testComment2, - }); - - expect(upserted.comments).toHaveLength(2); - expect(upserted.comments[1]?.id).toBe("comment-2"); - }).pipe(Effect.provide(makeLayer()))); - - it("upsertReviewComment replaces existing comment with same id", () => - Effect.gen(function* () { - const review = yield* ReviewService.ReviewService; - - yield* review.upsertReviewComment({ - threadId: "thread-3", - prNumber: 7, - prHeadSHA: "sha1", - comment: testComment, - }); - - const updatedComment: ReviewComment = { - ...testComment, - body: "Updated body text.", - agentStatus: "completed", - }; - - const upserted = yield* review.upsertReviewComment({ - threadId: "thread-3", - prNumber: 7, - prHeadSHA: "sha2", - comment: updatedComment, - }); - - expect(upserted.comments).toHaveLength(1); - expect(upserted.comments[0]?.body).toBe("Updated body text."); - expect(upserted.comments[0]?.agentStatus).toBe("completed"); - expect(upserted.prHeadSHA).toBe("sha2"); - }).pipe(Effect.provide(makeLayer()))); - - it("deleteReviewComment returns null for unknown draft", () => - Effect.gen(function* () { - const review = yield* ReviewService.ReviewService; - - const result = yield* review.deleteReviewComment({ - threadId: "unknown", - prNumber: 1, - commentId: "no-such-comment", - }); - - expect(result).toBeNull(); - }).pipe(Effect.provide(makeLayer()))); -}); - -const testGhComment: GitHubCli.GitHubPullRequestReviewComment = { - id: "123", - path: "src/app.ts", - line: 42, - commitSHA: "abc123", - body: "Consider renaming this variable.", - author: { login: "codex-bot" }, - createdAt: "2025-06-01T12:00:00Z", -}; - -const testGhComment2: GitHubCli.GitHubPullRequestReviewComment = { - id: "124", - path: "src/utils.ts", - commitSHA: "abc123", - body: "Extract this into a helper function.", - author: { login: "codex-bot" }, - createdAt: "2025-06-01T12:05:00Z", -}; - -const testGhComment3: GitHubCli.GitHubPullRequestReviewComment = { - id: "125", - path: "src/index.ts", - line: 10, - commitSHA: "abc123", - body: "Use a named export here.", - author: { login: "codex-bot" }, - createdAt: "2025-06-01T12:10:00Z", -}; - -function makeSubmitReviewLayer(input: { - readonly cwd: string; - readonly baseDir: string; - readonly ghCreateReview: (opts: { - readonly bodyFile: string; - }) => Effect.Effect; - readonly ghCreateReviewWithComments?: (opts: { - readonly cwd: string; - readonly reference: string; - readonly commentsJsonFile: string; - }) => Effect.Effect; - readonly ghGetReviews: () => Effect.Effect< - GitHubCli.GitHubPullRequestReview, - GitHubCli.GitHubCliError - >; -}) { - return ReviewService.layer.pipe( - Layer.provide(ServerConfig.layerTest(input.cwd, input.baseDir)), - Layer.provide( - Layer.effect( - GitHubCli.GitHubCli, - Effect.succeed( - GitHubCli.GitHubCli.of({ - execute: () => Effect.die("unexpected GitHubCli.execute call"), - listOpenPullRequests: () => Effect.die("unexpected"), - getPullRequest: () => Effect.die("unexpected"), - getRepositoryCloneUrls: () => Effect.die("unexpected"), - createRepository: () => Effect.die("unexpected"), - createPullRequest: () => Effect.die("unexpected"), - getDefaultBranch: () => Effect.die("unexpected"), - checkoutPullRequest: () => Effect.die("unexpected"), - getPullRequestReviews: ({ cwd: _, reference: __ }) => input.ghGetReviews(), - createPullRequestReview: ({ cwd: _, reference: __, bodyFile }) => - input.ghCreateReview({ bodyFile }), - createPullRequestReviewWithComments: ({ cwd: _, reference: __, commentsJsonFile }) => - input.ghCreateReviewWithComments - ? input.ghCreateReviewWithComments({ cwd: __, reference: __, commentsJsonFile }) - : input.ghCreateReview({ bodyFile: commentsJsonFile }), - }), - ), - ), - ), - Layer.provideMerge(NodeServices.layer), - ); -} - -const testLocalComment: ReviewComment = { - id: "local-1", - file: "src/app.ts", - line: 42, - commitSHA: "abc123", - body: "Consider renaming this variable.", - author: { login: "local" }, - createdAt: "2025-06-01T12:00:00Z", -}; - -const testLocalComment2: ReviewComment = { - id: "local-2", - file: "src/utils.ts", - commitSHA: "abc123", - body: "Extract this into a helper function.", - author: { login: "local" }, - createdAt: "2025-06-01T12:05:00Z", -}; - -const testLocalComment3: ReviewComment = { - id: "local-3", - file: "src/index.ts", - line: 10, - commitSHA: "abc123", - body: "Use a named export here.", - author: { login: "local" }, - createdAt: "2025-06-01T12:10:00Z", -}; - -describe("ReviewService submitReview", () => { - it("submitReview fails with no-draft when no draft comments exist", () => - Effect.gen(function* () { - const fs = yield* FileSystem.FileSystem; - const cwd = yield* fs.makeTempDirectoryScoped({ prefix: "t3-submit-review-" }); - const baseDir = yield* fs.makeTempDirectoryScoped({ prefix: "t3-submit-review-base-" }); - - const error = yield* Effect.gen(function* () { - const review = yield* ReviewService.ReviewService; - return yield* review - .submitReview({ - threadId: "thread-no-draft", - prNumber: 1, - cwd, - }) - .pipe(Effect.flip); - }).pipe( - Effect.provide( - makeSubmitReviewLayer({ - cwd, - baseDir, - ghCreateReview: () => Effect.die("should not be called"), - ghGetReviews: () => Effect.die("should not be called"), - }), - ), - ); - - expect(error._tag).toBe("ChangeRequestSubmitReviewError"); - expect(error.kind).toBe("no-draft"); - }).pipe(Effect.provide(NodeServices.layer))); - - it("submitReview posts local comments and marks them as published", () => - Effect.gen(function* () { - const fs = yield* FileSystem.FileSystem; - const cwd = yield* fs.makeTempDirectoryScoped({ prefix: "t3-submit-review-" }); - const baseDir = yield* fs.makeTempDirectoryScoped({ prefix: "t3-submit-review-base-" }); - - const createReviewCalls: Array<{ readonly commentsJsonFile: string }> = []; - let payloadContent = ""; - - const outcome = yield* Effect.gen(function* () { - const review = yield* ReviewService.ReviewService; - - // Upsert 3 draft comments (2 with line, 1 file-level) - yield* review.upsertReviewComment({ - threadId: "thread-submit", - prNumber: 99, - prHeadSHA: "sha1", - comment: testLocalComment, - }); - yield* review.upsertReviewComment({ - threadId: "thread-submit", - prNumber: 99, - prHeadSHA: "sha1", - comment: testLocalComment2, - }); - yield* review.upsertReviewComment({ - threadId: "thread-submit", - prNumber: 99, - prHeadSHA: "sha1", - comment: testLocalComment3, - }); - - const result = yield* review.submitReview({ - threadId: "thread-submit", - prNumber: 99, - cwd, - }); - - return result; - }).pipe( - Effect.provide( - makeSubmitReviewLayer({ - cwd, - baseDir, - ghCreateReview: () => Effect.die("should not be called for line comments"), - ghCreateReviewWithComments: ({ commentsJsonFile }) => - Effect.gen(function* () { - createReviewCalls.push({ commentsJsonFile }); - payloadContent = yield* fs - .readFileString(commentsJsonFile) - .pipe(Effect.orElseSucceed(() => "file-read-error")); - }), - ghGetReviews: () => Effect.succeed({ comments: [] }), - }), - ), - ); - - // Verify gh api was called - expect(createReviewCalls).toHaveLength(1); - - // Parse JSON payload - const payload = JSON.parse(payloadContent); - expect(payload.event).toBe("COMMENT"); - expect(payload.commit_id).toBe("sha1"); - - // Body contains file-level comment (testLocalComment2 has no line) - expect(payload.body).toContain("src/utils.ts"); - expect(payload.body).toContain("Extract this into a helper function."); - - // Comments array contains line-specific comments - expect(payload.comments).toHaveLength(2); - expect(payload.comments[0].path).toBe("src/app.ts"); - expect(payload.comments[0].line).toBe(42); - expect(payload.comments[0].side).toBe("RIGHT"); - expect(payload.comments[0].body).toBe("Consider renaming this variable."); - expect(payload.comments[1].path).toBe("src/index.ts"); - expect(payload.comments[1].line).toBe(10); - expect(payload.comments[1].body).toBe("Use a named export here."); - - // Verify returned draft stays in "draft" state so future submissions are possible - expect(outcome.state).toBe("draft"); - expect(outcome.comments).toHaveLength(3); - expect(outcome.comments[0]?.id).toBe("local-1"); - // Published comments are no longer marked as "local" author - expect(outcome.comments[0]?.author.login).toBe("local-published"); - - // Verify getReviewDraft returns the draft (not published) with authored comments - const freshDraft = yield* Effect.gen(function* () { - const review = yield* ReviewService.ReviewService; - return yield* review.getReviewDraft({ - threadId: "thread-submit", - prNumber: 99, - cwd, - }); - }).pipe( - Effect.provide( - makeSubmitReviewLayer({ - cwd, - baseDir, - ghCreateReview: () => Effect.die("should not be called"), - ghGetReviews: () => Effect.succeed({ comments: [] }), - }), - ), - ); - - expect(freshDraft?.state).toBe("draft"); - expect(freshDraft?.comments).toHaveLength(3); - expect(freshDraft?.comments[0]?.id).toBe("local-1"); - }).pipe(Effect.provide(NodeServices.layer))); - - it("submitReview preserves draft on gh pr review failure", () => - Effect.gen(function* () { - const fs = yield* FileSystem.FileSystem; - const cwd = yield* fs.makeTempDirectoryScoped({ prefix: "t3-submit-review-" }); - const baseDir = yield* fs.makeTempDirectoryScoped({ prefix: "t3-submit-review-base-" }); - - const result = yield* Effect.gen(function* () { - const review = yield* ReviewService.ReviewService; - - // Upsert a draft comment - yield* review.upsertReviewComment({ - threadId: "thread-fail", - prNumber: 7, - prHeadSHA: "sha1", - comment: testLocalComment, - }); - - // Attempt to submit (will fail because gh api fails) - return yield* review - .submitReview({ - threadId: "thread-fail", - prNumber: 7, - cwd, - }) - .pipe(Effect.flip); - }).pipe( - Effect.provide( - makeSubmitReviewLayer({ - cwd, - baseDir, - ghCreateReview: () => Effect.die("should not be called"), - ghCreateReviewWithComments: () => - Effect.fail( - new GitHubCli.GitHubCliError({ - operation: "createPullRequestReviewWithComments", - detail: "gh api review failed: status 403", - }), - ), - ghGetReviews: () => Effect.die("should not be called"), - }), - ), - ); - - expect(result._tag).toBe("ChangeRequestSubmitReviewError"); - expect(result.kind).toBe("review-failed"); - expect(result.detail).toContain("gh api review failed"); - - // Verify local draft still exists - const existingDraft = yield* Effect.gen(function* () { - const review = yield* ReviewService.ReviewService; - return yield* review.getReviewDraft({ - threadId: "thread-fail", - prNumber: 7, - cwd, - }); - }).pipe( - Effect.provide( - makeSubmitReviewLayer({ - cwd, - baseDir, - ghCreateReview: () => Effect.die("should not be called"), - ghGetReviews: () => Effect.succeed({ comments: [] }), - }), - ), - ); - - expect(existingDraft).not.toBeNull(); - expect(existingDraft?.state).toBe("draft"); - expect(existingDraft?.comments).toHaveLength(1); - }).pipe(Effect.provide(NodeServices.layer))); - - it("submitReview only posts new local comments on resubmission", () => - Effect.gen(function* () { - const fs = yield* FileSystem.FileSystem; - const cwd = yield* fs.makeTempDirectoryScoped({ prefix: "t3-submit-review-" }); - const baseDir = yield* fs.makeTempDirectoryScoped({ prefix: "t3-submit-review-base-" }); - - const createReviewCalls: Array = []; - let secondPayload: Record | null = null; - - yield* Effect.gen(function* () { - const review = yield* ReviewService.ReviewService; - - // First submission: post comment-1 (has line) - yield* review.upsertReviewComment({ - threadId: "thread-incremental", - prNumber: 42, - prHeadSHA: "sha1", - comment: testLocalComment, - }); - yield* review.submitReview({ - threadId: "thread-incremental", - prNumber: 42, - cwd, - }); - - // Add a second comment (no line = file-level) - yield* review.upsertReviewComment({ - threadId: "thread-incremental", - prNumber: 42, - prHeadSHA: "sha1", - comment: testLocalComment2, - }); - - // Second submission should only include the new comment - yield* review.submitReview({ - threadId: "thread-incremental", - prNumber: 42, - cwd, - }); - }).pipe( - Effect.provide( - makeSubmitReviewLayer({ - cwd, - baseDir, - ghCreateReview: ({ bodyFile }) => - Effect.gen(function* () { - createReviewCalls.push("body:" + bodyFile); - const raw = yield* fs - .readFileString(bodyFile) - .pipe(Effect.orElseSucceed(() => "{}")); - secondPayload = JSON.parse(raw); - }), - ghCreateReviewWithComments: ({ commentsJsonFile }) => - Effect.gen(function* () { - createReviewCalls.push("inline:" + commentsJsonFile); - }), - ghGetReviews: () => Effect.succeed({ comments: [] }), - }), - ), - ); - - expect(createReviewCalls).toHaveLength(2); - // Second submission uses body path (file-level only), should not contain first comment - const sp = secondPayload as Record | null; - const bodyText = typeof sp?.body === "string" ? sp.body : ""; - expect(bodyText).not.toContain("Consider renaming this variable."); - expect(bodyText).toContain("Extract this into a helper function."); - // No comments array since the new comment has no line - expect(sp?.comments).toBeUndefined(); - }).pipe(Effect.provide(NodeServices.layer))); - - it("submitReview returns no-draft when all local comments are already published", () => - Effect.gen(function* () { - const fs = yield* FileSystem.FileSystem; - const cwd = yield* fs.makeTempDirectoryScoped({ prefix: "t3-submit-review-" }); - const baseDir = yield* fs.makeTempDirectoryScoped({ prefix: "t3-submit-review-base-" }); - - const createReviewCalls: Array<{ readonly commentsJsonFile: string }> = []; - - const error = yield* Effect.gen(function* () { - const review = yield* ReviewService.ReviewService; - - yield* review.upsertReviewComment({ - threadId: "thread-all-published", - prNumber: 1, - prHeadSHA: "sha1", - comment: testLocalComment, - }); - - // First submission publishes the comment - yield* review.submitReview({ - threadId: "thread-all-published", - prNumber: 1, - cwd, - }); - - // Second submission with no new local comments - return yield* review - .submitReview({ - threadId: "thread-all-published", - prNumber: 1, - cwd, - }) - .pipe(Effect.flip); - }).pipe( - Effect.provide( - makeSubmitReviewLayer({ - cwd, - baseDir, - ghCreateReview: () => Effect.die("should not be called"), - ghCreateReviewWithComments: ({ commentsJsonFile }) => - Effect.gen(function* () { - createReviewCalls.push({ commentsJsonFile }); - }), - ghGetReviews: () => Effect.succeed({ comments: [] }), - }), - ), - ); - - expect(createReviewCalls).toHaveLength(1); - expect(error._tag).toBe("ChangeRequestSubmitReviewError"); - expect(error.kind).toBe("no-draft"); - expect(error.detail).toBe("No local draft review comments to submit."); - }).pipe(Effect.provide(NodeServices.layer))); -}); diff --git a/apps/server/src/server.test.ts b/apps/server/src/server.test.ts index 727393762b8b..15d384782546 100644 --- a/apps/server/src/server.test.ts +++ b/apps/server/src/server.test.ts @@ -88,15 +88,14 @@ import { } from "./orchestration/Services/ProjectionSnapshotQuery.ts"; import { SqlitePersistenceMemory } from "./persistence/Layers/Sqlite.ts"; import { PersistenceSqlError } from "./persistence/Errors.ts"; -import { ProviderUnsupportedError } from "./provider/Errors.ts"; -import { - ProviderAdapterRegistry, - type ProviderAdapterRegistryShape, -} from "./provider/Services/ProviderAdapterRegistry.ts"; import { ProviderRegistry, type ProviderRegistryShape, } from "./provider/Services/ProviderRegistry.ts"; +import { + ProviderAdapterRegistry, + type ProviderAdapterRegistryShape, +} from "./provider/Services/ProviderAdapterRegistry.ts"; import { makeManualOnlyProviderMaintenanceCapabilities } from "./provider/providerMaintenance.ts"; import { ServerLifecycleEvents, type ServerLifecycleEventsShape } from "./serverLifecycleEvents.ts"; import { ServerRuntimeStartup, type ServerRuntimeStartupShape } from "./serverRuntimeStartup.ts"; @@ -131,9 +130,6 @@ import * as VcsProvisioningService from "./vcs/VcsProvisioningService.ts"; import * as GitWorkflowService from "./git/GitWorkflowService.ts"; import * as ReviewService from "./review/ReviewService.ts"; import * as SourceControlRepositoryService from "./sourceControl/SourceControlRepositoryService.ts"; -import * as SourceControlDiscovery from "./sourceControl/SourceControlDiscovery.ts"; -import * as ProviderMaintenanceRunner from "./provider/providerMaintenanceRunner.ts"; -import * as BackgroundAgentService from "./review/BackgroundAgentService.ts"; import * as ServerSecretStore from "./auth/ServerSecretStore.ts"; import * as EnvironmentAuth from "./auth/EnvironmentAuth.ts"; import { @@ -350,6 +346,7 @@ const buildAppUnderTest = (options?: { layers?: { keybindings?: Partial; providerRegistry?: Partial; + providerAdapterRegistry?: Partial; serverSettings?: Partial; externalLauncher?: Partial; vcsDriver?: Partial; @@ -533,16 +530,6 @@ const buildAppUnderTest = (options?: { ); const reviewLayer = options?.layers?.reviewService ? Layer.mock(ReviewService.ReviewService)({ - getReviewDraft: () => Effect.succeed(null), - upsertReviewComment: () => - Effect.succeed({ - threadId: "", - prNumber: 1, - prHeadSHA: "", - comments: [], - state: "draft", - }), - deleteReviewComment: () => Effect.succeed(null), ...options.layers.reviewService, }) : ReviewService.layer.pipe( @@ -554,24 +541,6 @@ const buildAppUnderTest = (options?: { ...options.layers.vcsStatusBroadcaster, }) : VcsStatusBroadcaster.layer.pipe(Layer.provide(gitWorkflowLayer)); - const providerAdapterRegistryLayer = Layer.mock(ProviderAdapterRegistry)({ - getByInstance: (instanceId) => - Effect.fail( - new ProviderUnsupportedError({ - provider: instanceId, - }), - ), - getInstanceInfo: (instanceId) => - Effect.fail( - new ProviderUnsupportedError({ - provider: instanceId, - }), - ), - listInstances: () => Effect.succeed([]), - listProviders: () => Effect.succeed([]), - streamChanges: Stream.empty, - subscribeChanges: Effect.die("ProviderAdapterRegistry.subscribeChanges not implemented."), - } satisfies ProviderAdapterRegistryShape); const servedRoutesLayer = HttpRouter.serve(makeRoutesLayer, { disableListenLog: true, @@ -601,7 +570,11 @@ const buildAppUnderTest = (options?: { ...options?.layers?.providerRegistry, }), ), - Layer.provide(providerAdapterRegistryLayer), + Layer.provide( + Layer.mock(ProviderAdapterRegistry)({ + ...options?.layers?.providerAdapterRegistry, + }), + ), Layer.provide( Layer.mock(ServerSettingsService)({ start: Effect.void, @@ -820,7 +793,7 @@ const buildAppUnderTest = (options?: { ), Layer.provide( Layer.mock(CloudCliTokenManager.CloudCliTokenManager)({ - get: Effect.die(new Error("Unexpected T3 Cloud CLI authorization request.")), + get: Effect.die(new Error("Unexpected T3 Connect CLI authorization request.")), getExisting: Effect.succeed(Option.none()), hasCredential: Effect.succeed(false), clear: Effect.void, @@ -828,23 +801,6 @@ const buildAppUnderTest = (options?: { }), ), Layer.provideMerge(makeAuthTestLayer()), - Layer.provide( - Layer.mock(SourceControlDiscovery.SourceControlDiscovery)({ - discover: Effect.succeed({ versionControlSystems: [], sourceControlProviders: [] }), - }), - ), - Layer.provide( - Layer.mock(ProviderMaintenanceRunner.ProviderMaintenanceRunner)({ - updateProvider: () => - Effect.die("ProviderMaintenanceRunner.updateProvider not implemented in test"), - }), - ), - Layer.provide( - Layer.mock(BackgroundAgentService.BackgroundAgentService)({ - runBackgroundAgent: () => Stream.empty, - runBatchAgents: () => Stream.empty, - }), - ), Layer.provideMerge(ServerSecretStore.layer), Layer.provide(workspaceAndProjectServicesLayer), Layer.provideMerge(FetchHttpClient.layer), @@ -1768,7 +1724,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { yield* buildAppUnderTest(); const ownerCookie = yield* getAuthenticatedSessionCookieHeader(); - const linkProofUrl = yield* getHttpServerUrl("/api/cloud/link-proof"); + const linkProofUrl = yield* getHttpServerUrl("/api/connect/link-proof"); const linkProofResponse = yield* fetchEffect(linkProofUrl, { method: "POST", headers: { @@ -1805,7 +1761,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { yield* buildAppUnderTest(); const ownerCookie = yield* getAuthenticatedSessionCookieHeader(); - const linkProofUrl = yield* getHttpServerUrl("/api/cloud/link-proof"); + const linkProofUrl = yield* getHttpServerUrl("/api/connect/link-proof"); const serverPort = Number(new URL(linkProofUrl).port); const linkProofResponse = yield* fetchEffect(linkProofUrl, { method: "POST", @@ -1817,10 +1773,10 @@ it.layer(NodeServices.layer)("server router seam", (it) => { challenge: "relay-link-challenge", relayIssuer: "https://relay.example.test", endpoint: { - httpBaseUrl: linkProofUrl.replace("/api/cloud/link-proof", ""), + httpBaseUrl: linkProofUrl.replace("/api/connect/link-proof", ""), wsBaseUrl: linkProofUrl .replace("http://", "ws://") - .replace("/api/cloud/link-proof", "/ws"), + .replace("/api/connect/link-proof", "/ws"), providerKind: "manual", }, origin: { @@ -1844,9 +1800,9 @@ it.layer(NodeServices.layer)("server router seam", (it) => { Effect.gen(function* () { yield* buildAppUnderTest(); - const linkProofUrl = yield* getHttpServerUrl("/api/cloud/link-proof"); + const linkProofUrl = yield* getHttpServerUrl("/api/connect/link-proof"); const serverPort = Number(new URL(linkProofUrl).port); - const linkProofResponse = yield* HttpClient.post("/api/cloud/link-proof", { + const linkProofResponse = yield* HttpClient.post("/api/connect/link-proof", { headers: { cookie: yield* getAuthenticatedSessionCookieHeader(), "content-type": "application/json", @@ -1888,9 +1844,9 @@ it.layer(NodeServices.layer)("server router seam", (it) => { Effect.gen(function* () { yield* buildAppUnderTest(); - const linkProofUrl = yield* getHttpServerUrl("/api/cloud/link-proof"); + const linkProofUrl = yield* getHttpServerUrl("/api/connect/link-proof"); const serverPort = Number(new URL(linkProofUrl).port); - const linkProofResponse = yield* HttpClient.post("/api/cloud/link-proof", { + const linkProofResponse = yield* HttpClient.post("/api/connect/link-proof", { headers: { cookie: yield* getAuthenticatedSessionCookieHeader(), "content-type": "application/json", @@ -1930,9 +1886,9 @@ it.layer(NodeServices.layer)("server router seam", (it) => { Effect.gen(function* () { yield* buildAppUnderTest(); - const linkProofUrl = yield* getHttpServerUrl("/api/cloud/link-proof"); + const linkProofUrl = yield* getHttpServerUrl("/api/connect/link-proof"); const serverPort = Number(new URL(linkProofUrl).port); - const linkProofResponse = yield* HttpClient.post("/api/cloud/link-proof", { + const linkProofResponse = yield* HttpClient.post("/api/connect/link-proof", { headers: { cookie: yield* getAuthenticatedSessionCookieHeader(), "content-type": "application/json", @@ -1973,7 +1929,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { yield* buildAppUnderTest(); const ownerCookie = yield* getAuthenticatedSessionCookieHeader(); - const linkProofUrl = yield* getHttpServerUrl("/api/cloud/link-proof"); + const linkProofUrl = yield* getHttpServerUrl("/api/connect/link-proof"); const serverPort = Number(new URL(linkProofUrl).port); const linkProofResponse = yield* fetchEffect(linkProofUrl, { method: "POST", @@ -2017,7 +1973,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { }); const credential = (yield* credentialResponse.json) as { readonly credential: string }; const pairedCookie = yield* getAuthenticatedSessionCookieHeader(credential.credential); - const linkStateUrl = yield* getHttpServerUrl("/api/cloud/link-state"); + const linkStateUrl = yield* getHttpServerUrl("/api/connect/link-state"); const response = yield* fetchEffect(linkStateUrl, { headers: { cookie: pairedCookie }, }); @@ -2083,7 +2039,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { yield* buildAppUnderTest(); const ownerCookie = yield* getAuthenticatedSessionCookieHeader(); - const preferencesUrl = yield* getHttpServerUrl("/api/cloud/preferences"); + const preferencesUrl = yield* getHttpServerUrl("/api/connect/preferences"); const ownerResponse = yield* fetchEffect(preferencesUrl, { method: "POST", headers: { @@ -2127,7 +2083,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { yield* buildAppUnderTest(); const ownerCookie = yield* getAuthenticatedSessionCookieHeader(); - const relayConfigUrl = yield* getHttpServerUrl("/api/cloud/relay-config"); + const relayConfigUrl = yield* getHttpServerUrl("/api/connect/relay-config"); const relayConfigResponse = yield* fetchEffect(relayConfigUrl, { method: "POST", headers: { @@ -2162,7 +2118,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { publicKeyEncoding: { format: "pem", type: "spki" }, }); const ownerCookie = yield* getAuthenticatedSessionCookieHeader(); - const relayConfigUrl = yield* getHttpServerUrl("/api/cloud/relay-config"); + const relayConfigUrl = yield* getHttpServerUrl("/api/connect/relay-config"); const postRelayConfig = (body: { readonly relayUrl: string; readonly relayIssuer?: string; @@ -2239,7 +2195,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { publicKeyEncoding: { format: "pem", type: "spki" }, }); const ownerCookie = yield* getAuthenticatedSessionCookieHeader(); - const relayConfigUrl = yield* getHttpServerUrl("/api/cloud/relay-config"); + const relayConfigUrl = yield* getHttpServerUrl("/api/connect/relay-config"); const postRelayConfig = (cloudUserId: string, environmentCredential: string) => fetchEffect(relayConfigUrl, { method: "POST", @@ -2282,8 +2238,8 @@ it.layer(NodeServices.layer)("server router seam", (it) => { publicKeyEncoding: { format: "pem", type: "spki" }, }); const ownerCookie = yield* getAuthenticatedSessionCookieHeader(); - const linkStateUrl = yield* getHttpServerUrl("/api/cloud/link-state"); - const relayConfigUrl = yield* getHttpServerUrl("/api/cloud/relay-config"); + const linkStateUrl = yield* getHttpServerUrl("/api/connect/link-state"); + const relayConfigUrl = yield* getHttpServerUrl("/api/connect/relay-config"); const initialResponse = yield* fetchEffect(linkStateUrl, { headers: { @@ -2339,7 +2295,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { Effect.gen(function* () { yield* buildAppUnderTest(); - const reconcileUrl = yield* getHttpServerUrl("/api/cloud/reconcile"); + const reconcileUrl = yield* getHttpServerUrl("/api/connect/reconcile"); const response = yield* fetchEffect(reconcileUrl, { method: "POST", }); @@ -2376,9 +2332,9 @@ it.layer(NodeServices.layer)("server router seam", (it) => { publicKeyEncoding: { format: "pem", type: "spki" }, }); const ownerCookie = yield* getAuthenticatedSessionCookieHeader(); - const relayConfigUrl = yield* getHttpServerUrl("/api/cloud/relay-config"); - const unlinkUrl = yield* getHttpServerUrl("/api/cloud/unlink"); - const linkStateUrl = yield* getHttpServerUrl("/api/cloud/link-state"); + const relayConfigUrl = yield* getHttpServerUrl("/api/connect/relay-config"); + const unlinkUrl = yield* getHttpServerUrl("/api/connect/unlink"); + const linkStateUrl = yield* getHttpServerUrl("/api/connect/link-state"); const relayConfigResponse = yield* fetchEffect(relayConfigUrl, { method: "POST", @@ -2453,7 +2409,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { publicKeyEncoding: { format: "pem", type: "spki" }, }); const ownerCookie = yield* getAuthenticatedSessionCookieHeader(); - const relayConfigUrl = yield* getHttpServerUrl("/api/cloud/relay-config"); + const relayConfigUrl = yield* getHttpServerUrl("/api/connect/relay-config"); const relayConfigResponse = yield* fetchEffect(relayConfigUrl, { method: "POST", headers: { @@ -2479,7 +2435,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { issuedAt: DateTime.formatIso(now), expiresAt: DateTime.formatIso(DateTime.add(now, { minutes: 5 })), }); - const mintUrl = yield* getHttpServerUrl("/api/cloud/mint-credential"); + const mintUrl = yield* getHttpServerUrl("/api/connect/mint-credential"); const postMint = () => fetchEffect(mintUrl, { method: "POST", @@ -2503,7 +2459,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { }).pipe(Effect.provide(NodeHttpServer.layerTest)), ); - it.effect("serves the documented T3 Cloud mint credential endpoint", () => + it.effect("serves the documented T3 Connect mint credential endpoint", () => Effect.gen(function* () { yield* buildAppUnderTest(); @@ -2512,7 +2468,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { publicKeyEncoding: { format: "pem", type: "spki" }, }); const ownerCookie = yield* getAuthenticatedSessionCookieHeader(); - const relayConfigUrl = yield* getHttpServerUrl("/api/cloud/relay-config"); + const relayConfigUrl = yield* getHttpServerUrl("/api/connect/relay-config"); const relayConfigResponse = yield* fetchEffect(relayConfigUrl, { method: "POST", headers: { @@ -2539,7 +2495,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { issuedAt: DateTime.formatIso(now), expiresAt: DateTime.formatIso(DateTime.add(now, { minutes: 5 })), }); - const mintUrl = yield* getHttpServerUrl("/api/t3-cloud/mint-credential"); + const mintUrl = yield* getHttpServerUrl("/api/t3-connect/mint-credential"); const response = yield* fetchEffect(mintUrl, { method: "POST", headers: { @@ -2562,7 +2518,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { }).pipe(Effect.provide(NodeHttpServer.layerTest)), ); - it.effect("serves signed T3 Cloud environment health checks", () => + it.effect("serves signed T3 Connect environment health checks", () => Effect.gen(function* () { yield* buildAppUnderTest(); @@ -2571,7 +2527,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { publicKeyEncoding: { format: "pem", type: "spki" }, }); const ownerCookie = yield* getAuthenticatedSessionCookieHeader(); - const relayConfigUrl = yield* getHttpServerUrl("/api/cloud/relay-config"); + const relayConfigUrl = yield* getHttpServerUrl("/api/connect/relay-config"); const relayConfigResponse = yield* fetchEffect(relayConfigUrl, { method: "POST", headers: { @@ -2597,7 +2553,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { issuedAt: DateTime.formatIso(now), expiresAt: DateTime.formatIso(DateTime.add(now, { minutes: 5 })), }); - const healthUrl = yield* getHttpServerUrl("/api/t3-cloud/health"); + const healthUrl = yield* getHttpServerUrl("/api/t3-connect/health"); const response = yield* fetchEffect(healthUrl, { method: "POST", headers: { @@ -2631,7 +2587,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { publicKeyEncoding: { format: "pem", type: "spki" }, }); const ownerCookie = yield* getAuthenticatedSessionCookieHeader(); - const relayConfigUrl = yield* getHttpServerUrl("/api/cloud/relay-config"); + const relayConfigUrl = yield* getHttpServerUrl("/api/connect/relay-config"); const relayConfigResponse = yield* fetchEffect(relayConfigUrl, { method: "POST", headers: { @@ -2657,7 +2613,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { issuedAt: DateTime.formatIso(now), expiresAt: DateTime.formatIso(DateTime.add(now, { minutes: 5 })), }); - const healthUrl = yield* getHttpServerUrl("/api/t3-cloud/health"); + const healthUrl = yield* getHttpServerUrl("/api/t3-connect/health"); const postHealth = () => fetchEffect(healthUrl, { method: "POST", @@ -2692,7 +2648,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { publicKeyEncoding: { format: "pem", type: "spki" }, }); const ownerCookie = yield* getAuthenticatedSessionCookieHeader(); - const relayConfigUrl = yield* getHttpServerUrl("/api/cloud/relay-config"); + const relayConfigUrl = yield* getHttpServerUrl("/api/connect/relay-config"); const relayConfigResponse = yield* fetchEffect(relayConfigUrl, { method: "POST", headers: { @@ -2711,7 +2667,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { assert.equal(relayConfigResponse.status, 200); const now = yield* DateTime.now; - const mintUrl = yield* getHttpServerUrl("/api/t3-cloud/mint-credential"); + const mintUrl = yield* getHttpServerUrl("/api/t3-connect/mint-credential"); const postMint = (request: ReturnType) => fetchEffect(mintUrl, { method: "POST", @@ -2772,7 +2728,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { publicKeyEncoding: { format: "pem", type: "spki" }, }); const ownerCookie = yield* getAuthenticatedSessionCookieHeader(); - const relayConfigUrl = yield* getHttpServerUrl("/api/cloud/relay-config"); + const relayConfigUrl = yield* getHttpServerUrl("/api/connect/relay-config"); const relayConfigResponse = yield* fetchEffect(relayConfigUrl, { method: "POST", headers: { @@ -2811,7 +2767,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { issuedAt: DateTime.formatIso(now), expiresAt: DateTime.formatIso(DateTime.add(now, { minutes: 5 })), }); - const healthUrl = yield* getHttpServerUrl("/api/t3-cloud/health"); + const healthUrl = yield* getHttpServerUrl("/api/t3-connect/health"); const healthResponse = yield* fetchEffect(healthUrl, { method: "POST", headers: { @@ -2841,7 +2797,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { publicKeyEncoding: { format: "pem", type: "spki" }, }); const ownerCookie = yield* getAuthenticatedSessionCookieHeader(); - const relayConfigUrl = yield* getHttpServerUrl("/api/cloud/relay-config"); + const relayConfigUrl = yield* getHttpServerUrl("/api/connect/relay-config"); const relayConfigResponse = yield* fetchEffect(relayConfigUrl, { method: "POST", headers: { @@ -2859,7 +2815,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { assert.equal(relayConfigResponse.status, 200); const now = yield* DateTime.now; - const mintUrl = yield* getHttpServerUrl("/api/cloud/mint-credential"); + const mintUrl = yield* getHttpServerUrl("/api/connect/mint-credential"); const postMint = (request: ReturnType) => fetchEffect(mintUrl, { method: "POST", @@ -2908,7 +2864,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { publicKeyEncoding: { format: "pem", type: "spki" }, }); const ownerCookie = yield* getAuthenticatedSessionCookieHeader(); - const relayConfigUrl = yield* getHttpServerUrl("/api/cloud/relay-config"); + const relayConfigUrl = yield* getHttpServerUrl("/api/connect/relay-config"); const relayConfigResponse = yield* fetchEffect(relayConfigUrl, { method: "POST", headers: { @@ -2926,7 +2882,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { assert.equal(relayConfigResponse.status, 200); const now = yield* DateTime.now; - const mintUrl = yield* getHttpServerUrl("/api/t3-cloud/mint-credential"); + const mintUrl = yield* getHttpServerUrl("/api/t3-connect/mint-credential"); const response = yield* fetchEffect(mintUrl, { method: "POST", headers: { @@ -2959,7 +2915,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { publicKeyEncoding: { format: "pem", type: "spki" }, }); const ownerCookie = yield* getAuthenticatedSessionCookieHeader(); - const relayConfigUrl = yield* getHttpServerUrl("/api/cloud/relay-config"); + const relayConfigUrl = yield* getHttpServerUrl("/api/connect/relay-config"); const relayConfigResponse = yield* fetchEffect(relayConfigUrl, { method: "POST", headers: { @@ -2977,7 +2933,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { assert.equal(relayConfigResponse.status, 200); const now = yield* DateTime.now; - const mintUrl = yield* getHttpServerUrl("/api/t3-cloud/mint-credential"); + const mintUrl = yield* getHttpServerUrl("/api/t3-connect/mint-credential"); const response = yield* fetchEffect(mintUrl, { method: "POST", headers: { @@ -3010,7 +2966,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { publicKeyEncoding: { format: "pem", type: "spki" }, }); const ownerCookie = yield* getAuthenticatedSessionCookieHeader(); - const relayConfigUrl = yield* getHttpServerUrl("/api/cloud/relay-config"); + const relayConfigUrl = yield* getHttpServerUrl("/api/connect/relay-config"); const relayConfigResponse = yield* fetchEffect(relayConfigUrl, { method: "POST", headers: { @@ -3028,7 +2984,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { assert.equal(relayConfigResponse.status, 200); const now = yield* DateTime.now; - const healthUrl = yield* getHttpServerUrl("/api/t3-cloud/health"); + const healthUrl = yield* getHttpServerUrl("/api/t3-connect/health"); const postHealth = (request: ReturnType) => fetchEffect(healthUrl, { method: "POST", @@ -3075,7 +3031,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { publicKeyEncoding: { format: "pem", type: "spki" }, }); const ownerCookie = yield* getAuthenticatedSessionCookieHeader(); - const relayConfigUrl = yield* getHttpServerUrl("/api/cloud/relay-config"); + const relayConfigUrl = yield* getHttpServerUrl("/api/connect/relay-config"); const relayConfigResponse = yield* fetchEffect(relayConfigUrl, { method: "POST", headers: { @@ -3093,7 +3049,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { assert.equal(relayConfigResponse.status, 200); const now = yield* DateTime.now; - const healthUrl = yield* getHttpServerUrl("/api/t3-cloud/health"); + const healthUrl = yield* getHttpServerUrl("/api/t3-connect/health"); const response = yield* fetchEffect(healthUrl, { method: "POST", headers: { @@ -3125,7 +3081,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { publicKeyEncoding: { format: "pem", type: "spki" }, }); const ownerCookie = yield* getAuthenticatedSessionCookieHeader(); - const relayConfigUrl = yield* getHttpServerUrl("/api/cloud/relay-config"); + const relayConfigUrl = yield* getHttpServerUrl("/api/connect/relay-config"); const relayConfigResponse = yield* fetchEffect(relayConfigUrl, { method: "POST", headers: { @@ -3143,7 +3099,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { assert.equal(relayConfigResponse.status, 200); const now = yield* DateTime.now; - const healthUrl = yield* getHttpServerUrl("/api/t3-cloud/health"); + const healthUrl = yield* getHttpServerUrl("/api/t3-connect/health"); const response = yield* fetchEffect(healthUrl, { method: "POST", headers: { @@ -3335,7 +3291,7 @@ it.layer(NodeServices.layer)("server router seam", (it) => { config: { devUrl: new URL(crossOriginClientOrigin) }, }); - const linkProofUrl = yield* getHttpServerUrl("/api/cloud/link-proof"); + const linkProofUrl = yield* getHttpServerUrl("/api/connect/link-proof"); const response = yield* fetchEffect(linkProofUrl, { method: "OPTIONS", headers: { diff --git a/apps/server/src/server.ts b/apps/server/src/server.ts index 422aa0236e54..436e90165574 100644 --- a/apps/server/src/server.ts +++ b/apps/server/src/server.ts @@ -44,9 +44,6 @@ import { RuntimeReceiptBusLive } from "./orchestration/Layers/RuntimeReceiptBus. import { ProviderRuntimeIngestionLive } from "./orchestration/Layers/ProviderRuntimeIngestion.ts"; import { ProviderCommandReactorLive } from "./orchestration/Layers/ProviderCommandReactor.ts"; import { CheckpointReactorLive } from "./orchestration/Layers/CheckpointReactor.ts"; -import { OrchestrationProjectionSnapshotQueryLive } from "./orchestration/Layers/ProjectionSnapshotQuery.ts"; -import { SeededWorkItemWritebackLive } from "./orchestration/Layers/SeededWorkItemWriteback.ts"; -import { SeededWorkItemWritebackReactorLive } from "./orchestration/Layers/SeededWorkItemWritebackReactor.ts"; import { ThreadDeletionReactorLive } from "./orchestration/Layers/ThreadDeletionReactor.ts"; import * as AgentAwarenessRelay from "./relay/AgentAwarenessRelay.ts"; import { hasCloudPublicConfig } from "./cloud/publicConfig.ts"; @@ -64,10 +61,7 @@ import * as VcsProcess from "./vcs/VcsProcess.ts"; import * as VcsProvisioningService from "./vcs/VcsProvisioningService.ts"; import * as VcsStatusBroadcaster from "./vcs/VcsStatusBroadcaster.ts"; import * as GitWorkflowService from "./git/GitWorkflowService.ts"; -import * as BackgroundAgentService from "./review/BackgroundAgentService.ts"; -import * as ProviderMaintenanceRunner from "./provider/providerMaintenanceRunner.ts"; import * as ReviewService from "./review/ReviewService.ts"; -import * as SourceControlDiscoveryLayer from "./sourceControl/SourceControlDiscovery.ts"; import * as SourceControlProviderRegistry from "./sourceControl/SourceControlProviderRegistry.ts"; import * as SourceControlRepositoryService from "./sourceControl/SourceControlRepositoryService.ts"; import { ProjectSetupScriptRunnerLive } from "./project/Layers/ProjectSetupScriptRunner.ts"; @@ -76,7 +70,7 @@ import { ServerEnvironmentLive } from "./environment/Layers/ServerEnvironment.ts import { authHttpApiLayer, environmentAuthenticatedAuthLayer } from "./auth/http.ts"; import * as ServerSecretStore from "./auth/ServerSecretStore.ts"; import * as EnvironmentAuth from "./auth/EnvironmentAuth.ts"; -import { cloudHttpApiLayer, reconcileDesiredCloudLink } from "./cloud/http.ts"; +import { connectHttpApiLayer, reconcileDesiredCloudLink } from "./cloud/http.ts"; import * as CloudManagedEndpointRuntime from "./cloud/ManagedEndpointRuntime.ts"; import * as CloudCliTokenManager from "./cloud/CliTokenManager.ts"; import * as CloudCliState from "./cloud/CliState.ts"; @@ -149,26 +143,16 @@ const PlatformServicesLive = Layer.unwrap( }), ); -const SeededWorkItemWritebackCompositeLive = Layer.mergeAll( - SeededWorkItemWritebackLive, - SeededWorkItemWritebackReactorLive.pipe(Layer.provide(SeededWorkItemWritebackLive)), -); - -const ReactorDependencyLayerLive = Layer.empty.pipe( +const ReactorLayerLive = Layer.empty.pipe( + Layer.provideMerge(OrchestrationReactorLive), Layer.provideMerge(ProviderRuntimeIngestionLive), Layer.provideMerge(ProviderCommandReactorLive), Layer.provideMerge(CheckpointReactorLive), - Layer.provideMerge(SeededWorkItemWritebackCompositeLive), Layer.provideMerge(ThreadDeletionReactorLive), Layer.provideMerge(AgentAwarenessRelay.layer.pipe(Layer.provide(ServerSecretStore.layer))), Layer.provideMerge(RuntimeReceiptBusLive), ); -const ReactorLayerLive = Layer.mergeAll( - ReactorDependencyLayerLive, - OrchestrationReactorLive.pipe(Layer.provide(ReactorDependencyLayerLive)), -); - const ProviderSessionDirectoryLayerLive = ProviderSessionDirectoryLive.pipe( Layer.provide(ProviderSessionRuntimeRepositoryLive), ); @@ -186,11 +170,8 @@ const ProviderLayerLive = ProviderServiceLive.pipe( const PersistenceLayerLive = Layer.empty.pipe(Layer.provideMerge(SqlitePersistenceLayerLive)); -const TerminalLayerLive = TerminalManagerLive.pipe(Layer.provide(PtyAdapterLive)); - -const ProjectionSnapshotQueryLayerLive = OrchestrationProjectionSnapshotQueryLive.pipe( - Layer.provideMerge(PersistenceLayerLive), - Layer.provideMerge(RepositoryIdentityResolverLive), +const ThreadMcpToggleRepositoryLayerLive = ThreadMcpToggleRepositoryLive.pipe( + Layer.provide(PersistenceLayerLive), ); const VcsDriverRegistryLayerLive = VcsDriverRegistry.layer.pipe( @@ -205,13 +186,8 @@ const SourceControlProviderRegistryLayerLive = SourceControlProviderRegistry.lay Layer.provideMerge(VcsDriverRegistryLayerLive), ); -const ProjectSetupScriptRunnerLayerLive = ProjectSetupScriptRunnerLive.pipe( - Layer.provideMerge(TerminalLayerLive), - Layer.provideMerge(ProjectionSnapshotQueryLayerLive), -); - const GitManagerLayerLive = GitManager.layer.pipe( - Layer.provideMerge(ProjectSetupScriptRunnerLayerLive), + Layer.provideMerge(ProjectSetupScriptRunnerLive), Layer.provideMerge(GitVcsDriver.layer), Layer.provideMerge(SourceControlProviderRegistryLayerLive), Layer.provideMerge(TextGeneration.layer), @@ -235,17 +211,6 @@ const SourceControlRepositoryServiceLayerLive = SourceControlRepositoryService.l const ReviewLayerLive = ReviewService.layer.pipe( Layer.provideMerge(GitVcsDriver.layer), Layer.provideMerge(VcsDriverRegistryLayerLive), - Layer.provideMerge(GitHubCli.layer), -); - -const BackgroundAgentServiceLayerLive = BackgroundAgentService.layer.pipe( - Layer.provideMerge(GitVcsDriver.layer), - Layer.provideMerge(GitWorkflowLayerLive), - Layer.provideMerge(ReviewLayerLive), -); - -const SourceControlDiscoveryLayerLive = SourceControlDiscoveryLayer.layer.pipe( - Layer.provideMerge(SourceControlProviderRegistryLayerLive), ); const VcsLayerLive = Layer.empty.pipe( @@ -258,20 +223,13 @@ const VcsLayerLive = Layer.empty.pipe( Layer.provideMerge(VcsStatusBroadcaster.layer.pipe(Layer.provide(GitWorkflowLayerLive))), ); -const CheckpointStoreLayerLive = CheckpointStoreLive.pipe( - Layer.provide(VcsDriverRegistryLayerLive), -); - -const CheckpointDiffQueryLayerLive = CheckpointDiffQueryLive.pipe( - Layer.provideMerge(CheckpointStoreLayerLive), - Layer.provideMerge(ProjectionSnapshotQueryLayerLive), -); - const CheckpointingLayerLive = Layer.empty.pipe( - Layer.provideMerge(CheckpointDiffQueryLayerLive), - Layer.provideMerge(CheckpointStoreLayerLive), + Layer.provideMerge(CheckpointDiffQueryLive), + Layer.provideMerge(CheckpointStoreLive.pipe(Layer.provide(VcsDriverRegistryLayerLive))), ); +const TerminalLayerLive = TerminalManagerLive.pipe(Layer.provide(PtyAdapterLive)); + const WorkspaceEntriesLayerLive = WorkspaceEntriesLive.pipe( Layer.provide(WorkspacePathsLive), Layer.provideMerge(VcsDriverRegistryLayerLive), @@ -301,62 +259,50 @@ const CloudManagedEndpointRuntimeLive = Layer.mergeAll( ), ); -const ThreadMcpToggleRepositoryLayerLive = ThreadMcpToggleRepositoryLive.pipe( - Layer.provide(PersistenceLayerLive), -); - -const ProviderDriverInfrastructureLayerLive = Layer.mergeAll( - ThreadMcpToggleRepositoryLayerLive, - ServerSettingsLive, - ProviderEventLoggersLive, - OpenCodeRuntimeLive, -); - -const ProviderInstanceRegistryHydrationLayerLive = ProviderInstanceRegistryHydrationLive.pipe( - Layer.provideMerge(ProviderDriverInfrastructureLayerLive), -); - -const ProviderRegistryLayerLive = ProviderRegistryLive.pipe( - Layer.provideMerge(ProviderInstanceRegistryHydrationLayerLive), -); - -const ProviderMaintenanceRunnerLayerLive = ProviderMaintenanceRunner.layer.pipe( - Layer.provideMerge(ProviderRegistryLayerLive), -); - -const ProviderAdapterRegistryLayerLive = ProviderAdapterRegistryLive.pipe( - Layer.provide(ProviderInstanceRegistryHydrationLayerLive), -); - const ProviderRuntimeLayerLive = ProviderSessionReaperLive.pipe( Layer.provideMerge(ProviderLayerLive), Layer.provideMerge(OrchestrationLayerLive), ); -const RuntimeCoreDependenciesLive = ReactorLayerLive.pipe( +const RuntimeCoreDependenciesBaseLive = ReactorLayerLive.pipe( // Core Services Layer.provideMerge(CheckpointingLayerLive), Layer.provideMerge(SourceControlProviderRegistryLayerLive), Layer.provideMerge(GitLayerLive), Layer.provideMerge(VcsLayerLive), - Layer.provideMerge(ProviderDriverInfrastructureLayerLive), Layer.provideMerge(ProviderRuntimeLayerLive), Layer.provideMerge(TerminalLayerLive), Layer.provideMerge(PersistenceLayerLive), - Layer.provideMerge(ProjectionSnapshotQueryLayerLive), +); + +const RuntimeCoreDependenciesLive = RuntimeCoreDependenciesBaseLive.pipe( Layer.provideMerge(KeybindingsLive), - Layer.provideMerge(ProviderRegistryLayerLive), + Layer.provideMerge(ProviderRegistryLive), + Layer.provideMerge(ProviderAdapterRegistryLive), // The instance registry is the new routing keystone — text generation, // adapter lookup, and runtime ingestion all resolve `ProviderInstanceId` // through this layer. Built-in drivers come from `BUILT_IN_DRIVERS`; // `providerInstances` hydration merges `settings.providers.` // with explicit `providerInstances` entries on boot. - Layer.provideMerge(ProviderAdapterRegistryLayerLive), + Layer.provideMerge(ProviderInstanceRegistryHydrationLive), + Layer.provideMerge(ThreadMcpToggleRepositoryLayerLive), + // Shared native/canonical NDJSON writers used by both the per-instance + // drivers (native stream, written from inside each `Adapter`) and + // `ProviderService` (canonical stream, written after event normalization). + // Provided once at the runtime level so every consumer sees the same + // logger instances. + Layer.provideMerge(ProviderEventLoggersLive), + // `OpenCodeDriver.create()` yields `OpenCodeRuntime`; previously the old + // `ProviderRegistryLive` pulled `OpenCodeRuntimeLive` in for itself, but + // the rewritten registry reads snapshots off the instance registry and + // no longer transitively provides it. Exposing it at the runtime level + // keeps a single Live for all opencode consumers. + Layer.provideMerge(OpenCodeRuntimeLive), + Layer.provideMerge(ServerSettingsLive), Layer.provideMerge(WorkspaceLayerLive), Layer.provideMerge(ProjectFaviconResolverLive), Layer.provideMerge(RepositoryIdentityResolverLive), Layer.provideMerge(ServerEnvironmentLive), - Layer.provideMerge(BackgroundAgentServiceLayerLive), Layer.provideMerge(AuthLayerLive), Layer.provideMerge(ServerSecretStore.layer), Layer.provideMerge( @@ -369,8 +315,6 @@ const RuntimeCoreDependenciesLive = ReactorLayerLive.pipe( const RuntimeDependenciesLive = RuntimeCoreDependenciesLive.pipe( // Misc. - Layer.provideMerge(SourceControlDiscoveryLayerLive), - Layer.provideMerge(ProviderMaintenanceRunnerLayerLive), Layer.provideMerge(ProcessDiagnostics.layer), Layer.provideMerge(ProcessResourceMonitor.layer), Layer.provideMerge(TraceDiagnostics.layer), @@ -380,20 +324,14 @@ const RuntimeDependenciesLive = RuntimeCoreDependenciesLive.pipe( Layer.provide(NetService.layer), ); -const ServerRuntimeStartupLayerLive = ServerRuntimeStartupLive.pipe( +const RuntimeServicesLive = ServerRuntimeStartupLive.pipe( Layer.provideMerge(RuntimeDependenciesLive), - Layer.provideMerge(ProjectionSnapshotQueryLayerLive), -); - -export const RuntimeServicesLive = Layer.mergeAll( - RuntimeDependenciesLive, - ServerRuntimeStartupLayerLive, ); export const makeRoutesLayer = Layer.mergeAll( HttpApiBuilder.layer(EnvironmentHttpApi).pipe( Layer.provide(authHttpApiLayer), - Layer.provide(cloudHttpApiLayer), + Layer.provide(connectHttpApiLayer), Layer.provide(orchestrationHttpApiLayer), Layer.provide(serverEnvironmentHttpApiLayer), Layer.provide(environmentAuthenticatedAuthLayer), @@ -501,9 +439,9 @@ export const makeServerLayer = Layer.unwrap( Effect.sleep("250 millis").pipe( Effect.andThen(reconcileDesiredCloudLink(`http://127.0.0.1:${address.port}`)), Effect.retry({ times: 4 }), - Effect.tap(() => Effect.logInfo("T3 Cloud desired link reconciled on startup")), + Effect.tap(() => Effect.logInfo("T3 Connect desired link reconciled on startup")), Effect.catch((cause) => - Effect.logWarning("Failed to reconcile T3 Cloud desired link on startup", { + Effect.logWarning("Failed to reconcile T3 Connect desired link on startup", { cause, }), ), @@ -511,6 +449,7 @@ export const makeServerLayer = Layer.unwrap( ); }), ); + const serverApplicationLayer = Layer.mergeAll( HttpRouter.serve(makeRoutesLayer, { disableLogger: !config.logWebSocketEvents, @@ -533,6 +472,4 @@ export const makeServerLayer = Layer.unwrap( ); // Important: Only `ServerConfig` should be provided by the CLI layer!!! Don't let other requirements leak into the launch layer. -export const runServer = Layer.launch(makeServerLayer).pipe( - Effect.provide(ThreadMcpToggleRepositoryLayerLive), -); +export const runServer = Layer.launch(makeServerLayer); diff --git a/apps/server/src/serverSettings.ts b/apps/server/src/serverSettings.ts index 2ccbb121be85..0e126604b4af 100644 --- a/apps/server/src/serverSettings.ts +++ b/apps/server/src/serverSettings.ts @@ -13,6 +13,7 @@ import { DEFAULT_GIT_TEXT_GENERATION_MODEL, DEFAULT_GIT_TEXT_GENERATION_MODEL_BY_PROVIDER, + DEFAULT_MODEL_BY_PROVIDER, DEFAULT_SERVER_SETTINGS, isProviderDriverKind, type ModelSelection, @@ -207,6 +208,7 @@ function fallbackTextGenerationProvider(settings: ServerSettings): ServerSetting instanceId: ProviderInstanceId.make(fallback), model: DEFAULT_GIT_TEXT_GENERATION_MODEL_BY_PROVIDER[fallback] ?? + DEFAULT_MODEL_BY_PROVIDER[fallback] ?? DEFAULT_GIT_TEXT_GENERATION_MODEL, } satisfies ModelSelection, }; diff --git a/apps/server/src/sourceControl/AzureDevOpsSourceControlProvider.ts b/apps/server/src/sourceControl/AzureDevOpsSourceControlProvider.ts index 76c7fd4773f1..8d8e081cb896 100644 --- a/apps/server/src/sourceControl/AzureDevOpsSourceControlProvider.ts +++ b/apps/server/src/sourceControl/AzureDevOpsSourceControlProvider.ts @@ -139,22 +139,6 @@ export const make = Effect.fn("makeAzureDevOpsSourceControlProvider")(function* ...(input.context !== undefined ? { remoteName: input.context.remoteName } : {}), }) .pipe(Effect.mapError((error) => providerError("checkoutChangeRequest", error))), - getPullRequestReviews: (_input) => - Effect.fail( - new SourceControlProviderError({ - provider: "azure-devops", - operation: "getPullRequestReviews", - detail: "Not implemented for this provider.", - }), - ), - createPullRequestReview: (_input) => - Effect.fail( - new SourceControlProviderError({ - provider: "azure-devops", - operation: "createPullRequestReview", - detail: "Not implemented for this provider.", - }), - ), }); }); diff --git a/apps/server/src/sourceControl/BitbucketSourceControlProvider.ts b/apps/server/src/sourceControl/BitbucketSourceControlProvider.ts index 9ad290407f23..f3fd502f7fb8 100644 --- a/apps/server/src/sourceControl/BitbucketSourceControlProvider.ts +++ b/apps/server/src/sourceControl/BitbucketSourceControlProvider.ts @@ -109,22 +109,6 @@ export const make = Effect.fn("makeBitbucketSourceControlProvider")(function* () ...(input.force !== undefined ? { force: input.force } : {}), }) .pipe(Effect.mapError((error) => providerError("checkoutChangeRequest", error))), - getPullRequestReviews: (_input) => - Effect.fail( - new SourceControlProviderError({ - provider: "bitbucket", - operation: "getPullRequestReviews", - detail: "Not implemented for this provider.", - }), - ), - createPullRequestReview: (_input) => - Effect.fail( - new SourceControlProviderError({ - provider: "bitbucket", - operation: "createPullRequestReview", - detail: "Not implemented for this provider.", - }), - ), }); }); diff --git a/apps/server/src/sourceControl/GitHubCli.test.ts b/apps/server/src/sourceControl/GitHubCli.test.ts index 0749da1a99ad..40fb0dd64191 100644 --- a/apps/server/src/sourceControl/GitHubCli.test.ts +++ b/apps/server/src/sourceControl/GitHubCli.test.ts @@ -30,176 +30,6 @@ afterEach(() => { }); describe("GitHubCli.layer", () => { - it.effect("falls back when gh does not support labels json field (pr view)", () => - Effect.gen(function* () { - mockRun.mockReturnValueOnce( - Effect.fail( - new VcsProcessExitError({ - operation: "GitHubCli.execute", - command: "gh", - cwd: "/repo", - exitCode: 1, - detail: - "unknown field: labels\nRun `gh pr view --help` for more information about this command.\n", - }), - ), - ); - mockRun.mockReturnValueOnce( - Effect.succeed( - processOutput( - // @effect-diagnostics-next-line preferSchemaOverJson:off - JSON.stringify({ - number: 42, - title: "Add PR thread creation", - url: "https://github.com/pingdotgg/codething-mvp/pull/42", - baseRefName: "main", - headRefName: "feature/pr-threads", - state: "OPEN", - mergedAt: null, - isCrossRepository: false, - headRepository: null, - headRepositoryOwner: null, - }), - ), - ), - ); - - const gh = yield* GitHubCli.GitHubCli; - const result = yield* gh.getPullRequest({ - cwd: "/repo", - reference: "#42", - }); - - assert.deepStrictEqual(result, { - number: 42, - title: "Add PR thread creation", - url: "https://github.com/pingdotgg/codething-mvp/pull/42", - baseRefName: "main", - headRefName: "feature/pr-threads", - state: "open", - isCrossRepository: false, - }); - expect(mockRun).toHaveBeenNthCalledWith(1, { - operation: "GitHubCli.execute", - command: "gh", - args: [ - "pr", - "view", - "#42", - "--json", - "number,title,url,baseRefName,headRefName,state,mergedAt,isCrossRepository,headRepository,headRepositoryOwner,labels", - ], - cwd: "/repo", - timeoutMs: 30_000, - }); - expect(mockRun).toHaveBeenNthCalledWith(2, { - operation: "GitHubCli.execute", - command: "gh", - args: [ - "pr", - "view", - "#42", - "--json", - "number,title,url,baseRefName,headRefName,state,mergedAt,isCrossRepository,headRepository,headRepositoryOwner", - ], - cwd: "/repo", - timeoutMs: 30_000, - }); - }).pipe(Effect.provide(layer)), - ); - - it.effect("falls back when gh does not support labels json field (pr list)", () => - Effect.gen(function* () { - mockRun.mockReturnValueOnce( - Effect.fail( - new VcsProcessExitError({ - operation: "GitHubCli.execute", - command: "gh", - cwd: "/repo", - exitCode: 1, - detail: - "unknown field: labels\nRun `gh pr list --help` for more information about this command.\n", - }), - ), - ); - mockRun.mockReturnValueOnce( - Effect.succeed( - processOutput( - // @effect-diagnostics-next-line preferSchemaOverJson:off - JSON.stringify([ - { - number: 43, - title: "Valid PR", - url: "https://github.com/pingdotgg/codething-mvp/pull/43", - baseRefName: "main", - headRefName: "feature/pr-list", - state: "OPEN", - mergedAt: null, - isCrossRepository: false, - headRepository: null, - headRepositoryOwner: null, - }, - ]), - ), - ), - ); - - const gh = yield* GitHubCli.GitHubCli; - const result = yield* gh.listOpenPullRequests({ - cwd: "/repo", - headSelector: "feature/pr-list", - }); - - assert.deepStrictEqual(result, [ - { - number: 43, - title: "Valid PR", - url: "https://github.com/pingdotgg/codething-mvp/pull/43", - baseRefName: "main", - headRefName: "feature/pr-list", - state: "open", - isCrossRepository: false, - }, - ]); - expect(mockRun).toHaveBeenNthCalledWith(1, { - operation: "GitHubCli.execute", - command: "gh", - args: [ - "pr", - "list", - "--head", - "feature/pr-list", - "--state", - "open", - "--limit", - "1", - "--json", - "number,title,url,baseRefName,headRefName,state,mergedAt,isCrossRepository,headRepository,headRepositoryOwner,labels", - ], - cwd: "/repo", - timeoutMs: 30_000, - }); - expect(mockRun).toHaveBeenNthCalledWith(2, { - operation: "GitHubCli.execute", - command: "gh", - args: [ - "pr", - "list", - "--head", - "feature/pr-list", - "--state", - "open", - "--limit", - "1", - "--json", - "number,title,url,baseRefName,headRefName,state,mergedAt,isCrossRepository,headRepository,headRepositoryOwner", - ], - cwd: "/repo", - timeoutMs: 30_000, - }); - }).pipe(Effect.provide(layer)), - ); - it.effect("parses pull request view output", () => Effect.gen(function* () { mockRun.mockReturnValueOnce( @@ -221,16 +51,6 @@ describe("GitHubCli.layer", () => { headRepositoryOwner: { login: "octocat", }, - labels: [ - { - name: "ready-for-agent", - color: "0e8a16", - }, - { - name: "enhancement", - color: "a2eeef", - }, - ], }), ), ), @@ -252,16 +72,6 @@ describe("GitHubCli.layer", () => { isCrossRepository: true, headRepositoryNameWithOwner: "octocat/codething-mvp", headRepositoryOwnerLogin: "octocat", - labels: [ - { - name: "ready-for-agent", - color: "#0e8a16", - }, - { - name: "enhancement", - color: "#a2eeef", - }, - ], }); expect(mockRun).toHaveBeenCalledWith({ operation: "GitHubCli.execute", @@ -300,12 +110,6 @@ describe("GitHubCli.layer", () => { headRepositoryOwner: { login: " octocat ", }, - labels: [ - { - name: " ready-for-agent ", - color: " 0e8a16 ", - }, - ], }), ), ), @@ -327,12 +131,6 @@ describe("GitHubCli.layer", () => { isCrossRepository: true, headRepositoryNameWithOwner: "octocat/codething-mvp", headRepositoryOwnerLogin: "octocat", - labels: [ - { - name: "ready-for-agent", - color: "#0e8a16", - }, - ], }); }).pipe(Effect.provide(layer)), ); @@ -363,12 +161,6 @@ describe("GitHubCli.layer", () => { headRepositoryOwner: { login: " ", }, - labels: [ - { - name: " enhancement ", - color: "a2eeef", - }, - ], }, ]), ), @@ -389,107 +181,58 @@ describe("GitHubCli.layer", () => { baseRefName: "main", headRefName: "feature/pr-list", state: "open", - labels: [ - { - name: "enhancement", - color: "#a2eeef", - }, - ], }, ]); }).pipe(Effect.provide(layer)), ); - it.effect( - "retries pull request list queries without labels when gh does not support that json field", - () => - Effect.gen(function* () { - mockRun.mockReturnValueOnce( - Effect.fail( - new VcsProcessExitError({ - operation: "GitHubCli.execute", - command: "gh pr list", - cwd: "/repo", - exitCode: 1, - detail: 'Unknown JSON field: "labels"', - }), - ), - ); - mockRun.mockReturnValueOnce( - Effect.succeed( - processOutput( - // @effect-diagnostics-next-line preferSchemaOverJson:off - JSON.stringify([ - { - number: 43, - title: "Fallback PR", - url: "https://github.com/pingdotgg/codething-mvp/pull/43", - baseRefName: "main", - headRefName: "feature/pr-list", - state: "OPEN", - }, - ]), - ), + it.effect("retries PR listings without labels when old gh rejects that JSON field", () => + Effect.gen(function* () { + mockRun.mockReturnValueOnce( + Effect.fail( + new VcsProcessExitError({ + operation: "GitHubCli.execute", + command: "gh pr list", + cwd: "/repo", + exitCode: 1, + detail: 'Unknown JSON field: "labels"', + }), + ), + ); + mockRun.mockReturnValueOnce( + Effect.succeed( + processOutput( + // @effect-diagnostics-next-line preferSchemaOverJson:off + JSON.stringify([ + { + number: 43, + title: "Fallback PR", + url: "https://github.com/pingdotgg/codething-mvp/pull/43", + baseRefName: "main", + headRefName: "feature/pr-list", + state: "OPEN", + }, + ]), ), - ); + ), + ); - const gh = yield* GitHubCli.GitHubCli; - const result = yield* gh.listOpenPullRequests({ - cwd: "/repo", - headSelector: "feature/pr-list", - }); - - assert.deepStrictEqual(result, [ - { - number: 43, - title: "Fallback PR", - url: "https://github.com/pingdotgg/codething-mvp/pull/43", - baseRefName: "main", - headRefName: "feature/pr-list", - state: "open", - }, - ]); - expect(mockRun).toHaveBeenCalledTimes(2); - expect(mockRun).toHaveBeenNthCalledWith(1, { - operation: "GitHubCli.execute", - command: "gh", - args: [ - "pr", - "list", - "--head", - "feature/pr-list", - "--state", - "open", - "--limit", - "1", - "--json", - "number,title,url,baseRefName,headRefName,state,mergedAt,isCrossRepository,headRepository,headRepositoryOwner,labels", - ], - cwd: "/repo", - timeoutMs: 30_000, - }); - expect(mockRun).toHaveBeenNthCalledWith(2, { - operation: "GitHubCli.execute", - command: "gh", - args: [ - "pr", - "list", - "--head", - "feature/pr-list", - "--state", - "open", - "--limit", - "1", - "--json", - "number,title,url,baseRefName,headRefName,state,mergedAt,isCrossRepository,headRepository,headRepositoryOwner", - ], - cwd: "/repo", - timeoutMs: 30_000, - }); - }).pipe(Effect.provide(layer)), + const gh = yield* GitHubCli.GitHubCli; + const result = yield* gh.listOpenPullRequests({ + cwd: "/repo", + headSelector: "feature/pr-list", + }); + + assert.strictEqual(result[0]?.number, 43); + expect(mockRun).toHaveBeenCalledTimes(2); + const firstArgs = mockRun.mock.calls[0]?.[0].args ?? []; + const secondArgs = mockRun.mock.calls[1]?.[0].args ?? []; + assert.match(firstArgs.at(-1) ?? "", /labels/); + assert.notMatch(secondArgs.at(-1) ?? "", /labels/); + }).pipe(Effect.provide(layer)), ); - it.effect("deduplicates labels case-insensitively when decoding pull requests", () => + it.effect("deduplicates PR labels case-insensitively", () => Effect.gen(function* () { mockRun.mockReturnValueOnce( Effect.succeed( @@ -503,14 +246,8 @@ describe("GitHubCli.layer", () => { headRefName: "feature/pr-threads", state: "OPEN", labels: [ - { - name: "bug", - color: "d73a4a", - }, - { - name: "Bug", - color: "d73a4a", - }, + { name: "bug", color: "d73a4a" }, + { name: "Bug", color: "d73a4a" }, ], }), ), @@ -518,17 +255,9 @@ describe("GitHubCli.layer", () => { ); const gh = yield* GitHubCli.GitHubCli; - const result = yield* gh.getPullRequest({ - cwd: "/repo", - reference: "#42", - }); + const result = yield* gh.getPullRequest({ cwd: "/repo", reference: "#42" }); - assert.deepStrictEqual(result.labels, [ - { - name: "bug", - color: "#d73a4a", - }, - ]); + assert.deepStrictEqual(result.labels, [{ name: "bug", color: "#d73a4a" }]); }).pipe(Effect.provide(layer)), ); diff --git a/apps/server/src/sourceControl/GitHubCli.ts b/apps/server/src/sourceControl/GitHubCli.ts index cec6de3f5a1b..896d7290a764 100644 --- a/apps/server/src/sourceControl/GitHubCli.ts +++ b/apps/server/src/sourceControl/GitHubCli.ts @@ -43,21 +43,6 @@ export interface GitHubPullRequestSummary { readonly headRepositoryOwnerLogin?: string | null; } -export interface GitHubPullRequestReviewComment { - readonly id: string; - readonly path: string; - readonly line?: number; - readonly commitSHA: string; - readonly body: string; - readonly author: { readonly login: string }; - readonly createdAt: string; - readonly replies?: ReadonlyArray; -} - -export interface GitHubPullRequestReview { - readonly comments: ReadonlyArray; -} - export interface GitHubRepositoryCloneUrls { readonly nameWithOwner: string; readonly url: string; @@ -110,26 +95,6 @@ export interface GitHubCliShape { readonly reference: string; readonly force?: boolean; }) => Effect.Effect; - - readonly getPullRequestReviews: (input: { - readonly cwd: string; - readonly reference: string; - }) => Effect.Effect; - - readonly createPullRequestReview: (input: { - readonly cwd: string; - readonly reference: string; - readonly bodyFile: string; - }) => Effect.Effect; - - /** Post a PR review with inline comments via the GitHub API. - * Uses `gh api POST /repos/{owner}/{repo}/pulls/{pr}/reviews` with - * a JSON payload containing both a body and per-file/line comments array. */ - readonly createPullRequestReviewWithComments: (input: { - readonly cwd: string; - readonly reference: string; - readonly commentsJsonFile: string; - }) => Effect.Effect; } export class GitHubCli extends Context.Service()( @@ -157,19 +122,18 @@ function gitHubPullRequestJsonFields(input: { } function isUnsupportedLabelsJsonFieldError(error: GitHubCliError): boolean { - const lower = error.detail.toLowerCase(); + const detail = error.detail.toLowerCase(); return ( - lower.includes("labels") && - (lower.includes("unknown field") || - lower.includes("unknown json field") || - lower.includes("invalid field")) + detail.includes("labels") && + detail.includes("json") && + (detail.includes("unknown field") || + detail.includes("unknown json field") || + detail.includes("invalid field")) ); } function toSummaryWithOptionalUpdatedAt( - record: GitHubPullRequestSummary & { - readonly updatedAt: Option.Option; - }, + record: GitHubPullRequestSummary & { readonly updatedAt: Option.Option }, ): GitHubPullRequestSummary { const { updatedAt, ...summary } = record; return Option.isSome(updatedAt) ? { ...summary, updatedAt } : summary; @@ -190,12 +154,12 @@ export function executeGitHubPullRequestJsonCommand(input: { "--json", gitHubPullRequestJsonFields({ includeLabels, - ...(input.includeUpdatedAt !== undefined - ? { includeUpdatedAt: input.includeUpdatedAt } - : {}), + ...(input.includeUpdatedAt === undefined + ? {} + : { includeUpdatedAt: input.includeUpdatedAt }), }), ], - ...(input.timeoutMs !== undefined ? { timeoutMs: input.timeoutMs } : {}), + ...(input.timeoutMs === undefined ? {} : { timeoutMs: input.timeoutMs }), }); return run(true).pipe( @@ -470,76 +434,6 @@ export const make = Effect.fn("makeGitHubCli")(function* () { cwd: input.cwd, args: ["pr", "checkout", input.reference, ...(input.force ? ["--force"] : [])], }).pipe(Effect.asVoid), - getPullRequestReviews: (input) => - execute({ - cwd: input.cwd, - args: ["pr", "view", input.reference, "--json", "reviews"], - }).pipe( - Effect.map((result) => result.stdout.trim()), - Effect.flatMap((raw) => - Effect.sync(() => { - // @effect-diagnostics-next-line preferSchemaOverJson:off - const parsed = JSON.parse(raw); - const reviews = Array.isArray(parsed.reviews) ? parsed.reviews : []; - const comments: Array = []; - for (const review of reviews) { - if (review.comments && Array.isArray(review.comments)) { - for (const comment of review.comments) { - comments.push({ - id: String(comment.id ?? ""), - path: comment.path ?? "", - line: typeof comment.line === "number" ? comment.line : undefined, - commitSHA: comment.commit?.oid ?? "", - body: comment.body ?? "", - author: { login: comment.author?.login ?? "" }, - createdAt: comment.createdAt ?? "", - replies: - comment.replies?.nodes?.map((reply: Record) => ({ - id: String(reply.id ?? ""), - path: reply.path ?? "", - line: typeof reply.line === "number" ? reply.line : undefined, - commitSHA: (reply.commit as Record | undefined)?.oid ?? "", - body: reply.body ?? "", - author: { - login: (reply.author as Record | undefined)?.login ?? "", - }, - createdAt: reply.createdAt ?? "", - })) ?? undefined, - }); - } - } - } - return { comments }; - }), - ), - ), - createPullRequestReview: (input) => - execute({ - cwd: input.cwd, - args: ["pr", "review", input.reference, "--comment", "--body-file", input.bodyFile], - }).pipe(Effect.asVoid), - createPullRequestReviewWithComments: (input) => - Effect.gen(function* () { - const repoResult = yield* execute({ - cwd: input.cwd, - args: ["repo", "view", "--json", "nameWithOwner"], - }); - const repoRaw = repoResult.stdout.trim(); - let nameWithOwner = ""; - try { - nameWithOwner = (JSON.parse(repoRaw) as { nameWithOwner: string }).nameWithOwner; - } catch { - return yield* new GitHubCliError({ - operation: "createPullRequestReviewWithComments", - detail: "Failed to parse repo nameWithOwner from gh repo view output.", - }); - } - const apiPath = `repos/${nameWithOwner}/pulls/${input.reference}/reviews`; - yield* execute({ - cwd: input.cwd, - args: ["api", apiPath, "--input", input.commentsJsonFile], - }); - }).pipe(Effect.asVoid), }); }); diff --git a/apps/server/src/sourceControl/GitHubSourceControlProvider.test.ts b/apps/server/src/sourceControl/GitHubSourceControlProvider.test.ts index c117d304bdac..3fb1c41e11aa 100644 --- a/apps/server/src/sourceControl/GitHubSourceControlProvider.test.ts +++ b/apps/server/src/sourceControl/GitHubSourceControlProvider.test.ts @@ -4,7 +4,6 @@ import * as Effect from "effect/Effect"; import * as Layer from "effect/Layer"; import * as Option from "effect/Option"; import { ChildProcessSpawner } from "effect/unstable/process"; -import { VcsProcessExitError } from "@t3tools/contracts"; import * as VcsProcess from "../vcs/VcsProcess.ts"; import * as GitHubCli from "./GitHubCli.ts"; @@ -42,12 +41,6 @@ it.effect("maps GitHub PR summaries into provider-neutral change requests", () = baseRefName: "main", headRefName: "feature/source-control", state: "open", - labels: [ - { - name: "ready-for-agent", - color: "#0e8a16", - }, - ], isCrossRepository: true, headRepositoryNameWithOwner: "fork/t3code", headRepositoryOwnerLogin: "fork", @@ -67,12 +60,6 @@ it.effect("maps GitHub PR summaries into provider-neutral change requests", () = baseRefName: "main", headRefName: "feature/source-control", state: "open", - labels: [ - { - name: "ready-for-agent", - color: "#0e8a16", - }, - ], updatedAt: Option.none(), isCrossRepository: true, headRepositoryNameWithOwner: "fork/t3code", @@ -97,12 +84,6 @@ it.effect("uses gh json listing for non-open change request state queries", () = baseRefName: "main", headRefName: "feature/merged", state: "merged", - labels: [ - { - name: "release", - color: "5319e7", - }, - ], updatedAt: "2026-01-02T00:00:00.000Z", }, ]), @@ -132,12 +113,6 @@ it.effect("uses gh json listing for non-open change request state queries", () = ]); assert.strictEqual(changeRequests[0]?.provider, "github"); assert.strictEqual(changeRequests[0]?.state, "merged"); - assert.deepStrictEqual(changeRequests[0]?.labels, [ - { - name: "release", - color: "#5319e7", - }, - ]); assert.deepStrictEqual( changeRequests[0]?.updatedAt, Option.some(DateTime.makeUnsafe("2026-01-02T00:00:00.000Z")), @@ -162,88 +137,6 @@ it.effect("treats empty non-open change request listing output as no results", ( }), ); -it.effect("retries non-open change request listings without labels on older gh versions", () => - Effect.gen(function* () { - const executeCalls: Array> = []; - const provider = yield* makeProvider({ - execute: (input) => { - executeCalls.push(input.args); - if (executeCalls.length === 1) { - return Effect.fail( - new GitHubCli.GitHubCliError({ - operation: "execute", - detail: 'Unknown JSON field: "labels"', - cause: new VcsProcessExitError({ - operation: "GitHubCli.execute", - command: "gh pr list", - cwd: input.cwd, - exitCode: 1, - detail: 'Unknown JSON field: "labels"', - }), - }), - ); - } - - return Effect.succeed( - processResult( - JSON.stringify([ - { - number: 7, - title: "Merged work", - url: "https://github.com/pingdotgg/t3code/pull/7", - baseRefName: "main", - headRefName: "feature/merged", - state: "merged", - updatedAt: "2026-01-02T00:00:00.000Z", - }, - ]), - ), - ); - }, - }); - - const changeRequests = yield* provider.listChangeRequests({ - cwd: "/repo", - headSelector: "feature/merged", - state: "all", - limit: 10, - }); - - assert.deepStrictEqual(executeCalls, [ - [ - "pr", - "list", - "--head", - "feature/merged", - "--state", - "all", - "--limit", - "10", - "--json", - "number,title,url,baseRefName,headRefName,state,mergedAt,updatedAt,isCrossRepository,headRepository,headRepositoryOwner,labels", - ], - [ - "pr", - "list", - "--head", - "feature/merged", - "--state", - "all", - "--limit", - "10", - "--json", - "number,title,url,baseRefName,headRefName,state,mergedAt,updatedAt,isCrossRepository,headRepository,headRepositoryOwner", - ], - ]); - assert.strictEqual(changeRequests[0]?.number, 7); - assert.deepStrictEqual( - changeRequests[0]?.updatedAt, - Option.some(DateTime.makeUnsafe("2026-01-02T00:00:00.000Z")), - ); - assert.deepStrictEqual(changeRequests[0]?.labels, undefined); - }), -); - it.effect("creates GitHub PRs through provider-neutral input names", () => Effect.gen(function* () { let createInput: Parameters[0] | null = null; diff --git a/apps/server/src/sourceControl/GitHubSourceControlProvider.ts b/apps/server/src/sourceControl/GitHubSourceControlProvider.ts index cdcc60d8c03e..d6d03ed496cb 100644 --- a/apps/server/src/sourceControl/GitHubSourceControlProvider.ts +++ b/apps/server/src/sourceControl/GitHubSourceControlProvider.ts @@ -7,7 +7,6 @@ import { SourceControlProviderError, type ChangeRequest, type ChangeRequestState, - type ReviewComment, } from "@t3tools/contracts"; import * as GitHubCli from "./GitHubCli.ts"; @@ -52,19 +51,6 @@ function toChangeRequest(summary: GitHubCli.GitHubPullRequestSummary): ChangeReq }; } -function toReviewComment(comment: GitHubCli.GitHubPullRequestReviewComment): ReviewComment { - return { - id: comment.id, - file: comment.path, - ...(comment.line !== undefined ? { line: comment.line } : {}), - commitSHA: comment.commitSHA, - body: comment.body, - replies: comment.replies?.map(toReviewComment), - author: { login: comment.author.login }, - createdAt: comment.createdAt, - }; -} - function parseGitHubAuth(input: SourceControlProviderDiscovery.SourceControlAuthProbeInput) { const output = SourceControlProviderDiscovery.combinedAuthOutput(input); const authStatus = parseGitHubAuthStatus(input.stdout); @@ -220,15 +206,6 @@ export const make = Effect.fn("makeGitHubSourceControlProvider")(function* () { github .checkoutPullRequest(input) .pipe(Effect.mapError((error) => providerError("checkoutChangeRequest", error))), - getPullRequestReviews: (input) => - github.getPullRequestReviews(input).pipe( - Effect.map((review) => review.comments.map(toReviewComment)), - Effect.mapError((error) => providerError("getPullRequestReviews", error)), - ), - createPullRequestReview: (input) => - github - .createPullRequestReview(input) - .pipe(Effect.mapError((error) => providerError("createPullRequestReview", error))), }); }); diff --git a/apps/server/src/sourceControl/GitLabSourceControlProvider.ts b/apps/server/src/sourceControl/GitLabSourceControlProvider.ts index 22120fb0120e..77f41600e0fa 100644 --- a/apps/server/src/sourceControl/GitLabSourceControlProvider.ts +++ b/apps/server/src/sourceControl/GitLabSourceControlProvider.ts @@ -164,22 +164,6 @@ export const make = Effect.fn("makeGitLabSourceControlProvider")(function* () { gitlab .checkoutMergeRequest(input) .pipe(Effect.mapError((error) => providerError("checkoutChangeRequest", error))), - getPullRequestReviews: (_input) => - Effect.fail( - new SourceControlProviderError({ - provider: "gitlab", - operation: "getPullRequestReviews", - detail: "Not implemented for this provider.", - }), - ), - createPullRequestReview: (_input) => - Effect.fail( - new SourceControlProviderError({ - provider: "gitlab", - operation: "createPullRequestReview", - detail: "Not implemented for this provider.", - }), - ), }); }); diff --git a/apps/server/src/sourceControl/SourceControlDiscovery.ts b/apps/server/src/sourceControl/SourceControlDiscovery.ts index 3bf5decf4e46..eab46d235607 100644 --- a/apps/server/src/sourceControl/SourceControlDiscovery.ts +++ b/apps/server/src/sourceControl/SourceControlDiscovery.ts @@ -69,12 +69,10 @@ export class SourceControlDiscovery extends Context.Service< export const layer = Layer.effect( SourceControlDiscovery, Effect.gen(function* () { - yield* Effect.logDebug("sourceControlDiscovery.make start"); const config = yield* ServerConfig; const process = yield* VcsProcess.VcsProcess; const sourceControlProviders = yield* SourceControlProviderRegistry.SourceControlProviderRegistry; - yield* Effect.logDebug("sourceControlDiscovery.make dependencies ready"); const probe = ( input: DiscoveryProbe & { readonly kind: Kind }, diff --git a/apps/server/src/sourceControl/SourceControlProvider.ts b/apps/server/src/sourceControl/SourceControlProvider.ts index c81c6f50a0d1..f0602f03d14d 100644 --- a/apps/server/src/sourceControl/SourceControlProvider.ts +++ b/apps/server/src/sourceControl/SourceControlProvider.ts @@ -8,7 +8,6 @@ import type { SourceControlProviderKind, SourceControlRepositoryCloneUrls, SourceControlRepositoryVisibility, - ReviewComment, } from "@t3tools/contracts"; export interface SourceControlProviderContext { @@ -95,17 +94,6 @@ export interface SourceControlProviderShape { readonly reference: string; readonly force?: boolean; }) => Effect.Effect; - readonly getPullRequestReviews: (input: { - readonly cwd: string; - readonly context?: SourceControlProviderContext; - readonly reference: string; - }) => Effect.Effect, SourceControlProviderError>; - readonly createPullRequestReview: (input: { - readonly cwd: string; - readonly context?: SourceControlProviderContext; - readonly reference: string; - readonly bodyFile: string; - }) => Effect.Effect; } export class SourceControlProvider extends Context.Service< diff --git a/apps/server/src/sourceControl/SourceControlProviderRegistry.ts b/apps/server/src/sourceControl/SourceControlProviderRegistry.ts index 185c4b4f38df..08f794d1f5c8 100644 --- a/apps/server/src/sourceControl/SourceControlProviderRegistry.ts +++ b/apps/server/src/sourceControl/SourceControlProviderRegistry.ts @@ -74,8 +74,6 @@ function unsupportedProvider( createRepository: () => unsupported("createRepository"), getDefaultBranch: () => unsupported("getDefaultBranch"), checkoutChangeRequest: () => unsupported("checkoutChangeRequest"), - getPullRequestReviews: () => unsupported("getPullRequestReviews"), - createPullRequestReview: () => unsupported("createPullRequestReview"), }); } @@ -155,16 +153,6 @@ function bindProviderContext( ...input, context: input.context ?? context, }), - getPullRequestReviews: (input) => - provider.getPullRequestReviews({ - ...input, - context: input.context ?? context, - }), - createPullRequestReview: (input) => - provider.createPullRequestReview({ - ...input, - context: input.context ?? context, - }), }); } diff --git a/apps/server/src/sourceControl/SourceControlRepositoryService.test.ts b/apps/server/src/sourceControl/SourceControlRepositoryService.test.ts index 160f227669a6..811b55c70a35 100644 --- a/apps/server/src/sourceControl/SourceControlRepositoryService.test.ts +++ b/apps/server/src/sourceControl/SourceControlRepositoryService.test.ts @@ -37,8 +37,6 @@ function makeProvider( createRepository: () => Effect.succeed(CLONE_URLS), getDefaultBranch: () => Effect.succeed(null), checkoutChangeRequest: () => unsupported("checkoutChangeRequest"), - getPullRequestReviews: () => unsupported("getPullRequestReviews"), - createPullRequestReview: () => unsupported("createPullRequestReview"), ...overrides, }; } diff --git a/apps/server/src/sourceControl/gitHubPullRequests.ts b/apps/server/src/sourceControl/gitHubPullRequests.ts index bb2bf4c8d740..7612e892a4c1 100644 --- a/apps/server/src/sourceControl/gitHubPullRequests.ts +++ b/apps/server/src/sourceControl/gitHubPullRequests.ts @@ -63,12 +63,8 @@ function trimOptionalString(value: string | null | undefined): string | null { function normalizeGitHubLabelColor(value: string | null | undefined): string | null { const trimmed = value?.trim() ?? ""; - if (/^[0-9a-f]{6}$/iu.test(trimmed)) { - return `#${trimmed.toLowerCase()}`; - } - if (/^#[0-9a-f]{6}$/iu.test(trimmed)) { - return trimmed.toLowerCase(); - } + if (/^[0-9a-f]{6}$/iu.test(trimmed)) return `#${trimmed.toLowerCase()}`; + if (/^#[0-9a-f]{6}$/iu.test(trimmed)) return trimmed.toLowerCase(); return null; } @@ -107,8 +103,9 @@ function normalizeGitHubPullRequestRecord( }; }) .filter( - (label, index, labels) => - labels.findIndex((item) => item.name.toLowerCase() === label.name.toLowerCase()) === index, + (label, index, allLabels) => + allLabels.findIndex((item) => item.name.toLowerCase() === label.name.toLowerCase()) === + index, ); return { diff --git a/apps/server/src/textGeneration/GrokTextGeneration.test.ts b/apps/server/src/textGeneration/GrokTextGeneration.test.ts new file mode 100644 index 000000000000..58ce165752c8 --- /dev/null +++ b/apps/server/src/textGeneration/GrokTextGeneration.test.ts @@ -0,0 +1,234 @@ +// @effect-diagnostics nodeBuiltinImport:off +import * as path from "node:path"; +import * as os from "node:os"; +import { fileURLToPath } from "node:url"; +import { chmodSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"; + +import * as NodeServices from "@effect/platform-node/NodeServices"; +import { it } from "@effect/vitest"; +import * as Effect from "effect/Effect"; +import * as Layer from "effect/Layer"; +import * as Schema from "effect/Schema"; +import { createModelSelection } from "@t3tools/shared/model"; +import { expect } from "vite-plus/test"; +import { GrokSettings, ProviderInstanceId } from "@t3tools/contracts"; + +import { ServerConfig } from "../config.ts"; +import { type TextGenerationShape } from "./TextGeneration.ts"; +import { makeGrokTextGeneration } from "./GrokTextGeneration.ts"; +const decodeGrokSettings = Schema.decodeSync(GrokSettings); + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const mockAgentPath = path.join(__dirname, "../../scripts/acp-mock-agent.ts"); + +function shellSingleQuote(value: string): string { + return `'${value.replaceAll("'", `'"'"'`)}'`; +} + +const GrokTextGenerationTestLayer = ServerConfig.layerTest(process.cwd(), { + prefix: "t3code-grok-text-generation-test-", +}).pipe(Layer.provideMerge(NodeServices.layer)); + +function makeAcpGrokWrapper(dir: string, env: Record): string { + const binDir = path.join(dir, "bin"); + const grokPath = path.join(binDir, "grok"); + mkdirSync(binDir, { recursive: true }); + writeFileSync( + grokPath, + [ + "#!/bin/sh", + ...Object.entries(env).map(([key, value]) => `export ${key}=${shellSingleQuote(value)}`), + 'if [ "$1" != "agent" ] || [ "$2" != "stdio" ]; then', + ' printf "%s\\n" "unexpected args: $*" >&2', + " exit 11", + "fi", + `exec ${JSON.stringify(process.execPath)} ${JSON.stringify(mockAgentPath)}`, + "", + ].join("\n"), + "utf8", + ); + chmodSync(grokPath, 0o755); + return grokPath; +} + +function withFakeAcpGrok( + env: Record, + effectFn: (textGeneration: TextGenerationShape) => Effect.Effect, +) { + return Effect.gen(function* () { + const tempDir = mkdtempSync(path.join(os.tmpdir(), "t3code-grok-text-acp-")); + yield* Effect.addFinalizer(() => + Effect.sync(() => { + rmSync(tempDir, { recursive: true, force: true }); + }), + ); + const binaryPath = makeAcpGrokWrapper(tempDir, env); + const config = decodeGrokSettings({ binaryPath }); + const textGeneration = yield* makeGrokTextGeneration(config); + return yield* effectFn(textGeneration); + }).pipe(Effect.scoped); +} + +function readJsonRpcRequests( + filePath: string, +): ReadonlyArray<{ readonly method?: string; readonly params?: Record }> { + return readFileSync(filePath, "utf8") + .trim() + .split("\n") + .filter((line) => line.length > 0) + .map((line) => JSON.parse(line) as { method?: string; params?: Record }); +} + +it.layer(GrokTextGenerationTestLayer)("GrokTextGeneration", (it) => { + it.effect("uses ACP with disabled tool capabilities and forwards the requested model id", () => { + const requestLogDir = mkdtempSync(path.join(os.tmpdir(), "t3code-grok-text-log-")); + const requestLogPath = path.join(requestLogDir, "requests.ndjson"); + + return withFakeAcpGrok( + { + T3_ACP_REQUEST_LOG_PATH: requestLogPath, + T3_ACP_PROMPT_RESPONSE_TEXT: JSON.stringify({ + subject: "Add Grok provider", + body: "Wire up the ACP runtime and headless text generation path.", + }), + }, + (textGeneration) => + Effect.gen(function* () { + const generated = yield* textGeneration.generateCommitMessage({ + cwd: process.cwd(), + branch: "feature/grok", + stagedSummary: "M apps/server/src/provider/Drivers/GrokDriver.ts", + stagedPatch: "diff --git a/.../GrokDriver.ts b/.../GrokDriver.ts", + modelSelection: createModelSelection(ProviderInstanceId.make("grok"), "grok-mock-alt"), + }); + + expect(generated.subject).toBe("Add Grok provider"); + expect(generated.body).toBe("Wire up the ACP runtime and headless text generation path."); + + const requests = readJsonRpcRequests(requestLogPath); + expect( + requests.find((request) => request.method === "initialize")?.params?.clientCapabilities, + ).toMatchObject({ + fs: { readTextFile: false, writeTextFile: false }, + terminal: false, + }); + expect( + requests.some( + (request) => + request.method === "session/set_model" && + request.params?.modelId === "grok-mock-alt", + ), + ).toBe(true); + }), + ); + }); + + it.effect("extracts the JSON object when Grok wraps it in conversational text", () => + withFakeAcpGrok( + { + T3_ACP_PROMPT_RESPONSE_TEXT: + "Sure! Here's a thread title:\n\n" + + JSON.stringify({ title: "Investigate failing CI" }) + + "\n\nLet me know if you need anything else.", + }, + (textGeneration) => + Effect.gen(function* () { + const generated = yield* textGeneration.generateThreadTitle({ + cwd: process.cwd(), + message: "the lint job is red", + modelSelection: createModelSelection(ProviderInstanceId.make("grok"), "grok-mock-alt"), + }); + expect(generated.title).toBe("Investigate failing CI"); + }), + ), + ); + + it.effect("surfaces ACP request failures as text generation errors", () => + withFakeAcpGrok( + { + T3_ACP_PROMPT_RESPONSE_TEXT: JSON.stringify({ branch: "unreachable" }), + }, + (textGeneration) => + Effect.gen(function* () { + const error = yield* Effect.flip( + textGeneration.generateBranchName({ + cwd: process.cwd(), + message: "wire up grok", + modelSelection: createModelSelection( + ProviderInstanceId.make("grok"), + "missing-grok-model", + ), + }), + ); + expect(error._tag).toBe("TextGenerationError"); + expect(error.detail).toContain("Grok ACP base model"); + }), + ), + ); + + it.effect("fails with TextGenerationError when output is empty", () => + withFakeAcpGrok( + { + T3_ACP_PROMPT_RESPONSE_TEXT: " \n ", + }, + (textGeneration) => + Effect.gen(function* () { + const error = yield* Effect.flip( + textGeneration.generateThreadTitle({ + cwd: process.cwd(), + message: "anything", + modelSelection: createModelSelection(ProviderInstanceId.make("grok"), "grok-build"), + }), + ); + expect(error._tag).toBe("TextGenerationError"); + expect(error.detail).toMatch(/empty/i); + }), + ), + ); + + it.effect("decodes a structured PR title + body", () => + withFakeAcpGrok( + { + T3_ACP_PROMPT_RESPONSE_TEXT: JSON.stringify({ + title: "feat(grok): wire up session/set_model", + body: "## Summary\n- Replace `-m` spawn flag with the typed ACP `session/set_model`.\n- Translate `MODEL_SWITCH_INCOMPATIBLE_AGENT` into a validation error.", + }), + }, + (textGeneration) => + Effect.gen(function* () { + const generated = yield* textGeneration.generatePrContent({ + cwd: process.cwd(), + baseBranch: "main", + headBranch: "feat/grok-provider", + commitSummary: "feat: add grok provider", + diffSummary: "M apps/server/src/provider/Drivers/GrokDriver.ts", + diffPatch: "diff --git a/.../GrokDriver.ts b/.../GrokDriver.ts", + modelSelection: createModelSelection(ProviderInstanceId.make("grok"), "grok-build"), + }); + + expect(generated.title).toBe("feat(grok): wire up session/set_model"); + expect(generated.body).toContain("Translate `MODEL_SWITCH_INCOMPATIBLE_AGENT`"); + }), + ), + ); + + it.effect("fails with TextGenerationError when output is unparseable JSON", () => + withFakeAcpGrok( + { + T3_ACP_PROMPT_RESPONSE_TEXT: "totally not json output from a confused model", + }, + (textGeneration) => + Effect.gen(function* () { + const error = yield* Effect.flip( + textGeneration.generateThreadTitle({ + cwd: process.cwd(), + message: "anything", + modelSelection: createModelSelection(ProviderInstanceId.make("grok"), "grok-build"), + }), + ); + expect(error._tag).toBe("TextGenerationError"); + expect(error.detail).toMatch(/invalid structured output/i); + }), + ), + ); +}); diff --git a/apps/server/src/textGeneration/GrokTextGeneration.ts b/apps/server/src/textGeneration/GrokTextGeneration.ts new file mode 100644 index 000000000000..6d7ff8e872d1 --- /dev/null +++ b/apps/server/src/textGeneration/GrokTextGeneration.ts @@ -0,0 +1,272 @@ +import * as Effect from "effect/Effect"; +import * as Option from "effect/Option"; +import * as Ref from "effect/Ref"; +import * as Schema from "effect/Schema"; +import { ChildProcessSpawner } from "effect/unstable/process"; +import type * as EffectAcpErrors from "effect-acp/errors"; + +import { type GrokSettings, type ModelSelection } from "@t3tools/contracts"; +import { sanitizeBranchFragment, sanitizeFeatureBranchName } from "@t3tools/shared/git"; +import { extractJsonObject } from "@t3tools/shared/schemaJson"; + +import { TextGenerationError } from "@t3tools/contracts"; +import { type ThreadTitleGenerationResult, type TextGenerationShape } from "./TextGeneration.ts"; +import { + buildBranchNamePrompt, + buildCommitMessagePrompt, + buildPrContentPrompt, + buildThreadTitlePrompt, +} from "./TextGenerationPrompts.ts"; +import { + sanitizeCommitSubject, + sanitizePrTitle, + sanitizeThreadTitle, +} from "./TextGenerationUtils.ts"; +import { + applyGrokAcpModelSelection, + currentGrokModelIdFromSessionSetup, + makeGrokAcpRuntime, + resolveGrokAcpBaseModelId, +} from "../provider/acp/GrokAcpSupport.ts"; + +const GROK_TIMEOUT_MS = 180_000; + +function mapGrokAcpError( + operation: + | "generateCommitMessage" + | "generatePrContent" + | "generateBranchName" + | "generateThreadTitle", + detail: string, + cause: unknown, +): TextGenerationError { + return new TextGenerationError({ + operation, + detail, + ...(cause !== undefined ? { cause } : {}), + }); +} + +function isTextGenerationError(error: unknown): error is TextGenerationError { + return ( + typeof error === "object" && + error !== null && + "_tag" in error && + error._tag === "TextGenerationError" + ); +} + +export const makeGrokTextGeneration = Effect.fn("makeGrokTextGeneration")(function* ( + grokSettings: GrokSettings, + environment: NodeJS.ProcessEnv = process.env, +) { + const commandSpawner = yield* ChildProcessSpawner.ChildProcessSpawner; + + const runGrokJson = ({ + operation, + cwd, + prompt, + outputSchemaJson, + modelSelection, + }: { + operation: + | "generateCommitMessage" + | "generatePrContent" + | "generateBranchName" + | "generateThreadTitle"; + cwd: string; + prompt: string; + outputSchemaJson: S; + modelSelection: ModelSelection; + }): Effect.Effect => + Effect.gen(function* () { + const resolvedModel = resolveGrokAcpBaseModelId(modelSelection.model); + const outputRef = yield* Ref.make(""); + const runtime = yield* makeGrokAcpRuntime({ + grokSettings, + environment, + childProcessSpawner: commandSpawner, + cwd, + clientInfo: { name: "t3-code-git-text", version: "0.0.0" }, + }); + + yield* runtime.handleSessionUpdate((notification) => { + const update = notification.update; + if (update.sessionUpdate !== "agent_message_chunk") { + return Effect.void; + } + const content = update.content; + if (content.type !== "text") { + return Effect.void; + } + return Ref.update(outputRef, (current) => current + content.text); + }); + + const promptResult = yield* Effect.gen(function* () { + const started = yield* runtime.start(); + yield* applyGrokAcpModelSelection({ + runtime, + currentModelId: currentGrokModelIdFromSessionSetup(started.sessionSetupResult), + requestedModelId: resolvedModel, + mapError: (cause) => + mapGrokAcpError( + operation, + "Failed to set Grok ACP base model for text generation.", + cause, + ), + }); + + return yield* runtime.prompt({ + prompt: [{ type: "text", text: prompt }], + }); + }).pipe( + Effect.timeoutOption(GROK_TIMEOUT_MS), + Effect.flatMap( + Option.match({ + onNone: () => + Effect.fail( + new TextGenerationError({ operation, detail: "Grok ACP request timed out." }), + ), + onSome: (value) => Effect.succeed(value), + }), + ), + Effect.mapError((cause: EffectAcpErrors.AcpError | TextGenerationError) => + isTextGenerationError(cause) + ? cause + : mapGrokAcpError(operation, "Grok ACP request failed.", cause), + ), + ); + + const trimmed = (yield* Ref.get(outputRef)).trim(); + if (!trimmed) { + return yield* new TextGenerationError({ + operation, + detail: + promptResult.stopReason === "cancelled" + ? "Grok ACP request was cancelled." + : "Grok Agent returned empty output.", + }); + } + + const decodeOutput = Schema.decodeEffect(Schema.fromJsonString(outputSchemaJson)); + return yield* decodeOutput(extractJsonObject(trimmed)).pipe( + Effect.catchTag("SchemaError", (cause) => + Effect.fail( + new TextGenerationError({ + operation, + detail: "Grok Agent returned invalid structured output.", + cause, + }), + ), + ), + ); + }).pipe( + Effect.mapError((cause) => + isTextGenerationError(cause) + ? cause + : mapGrokAcpError(operation, "Grok ACP text generation failed.", cause), + ), + Effect.scoped, + ); + + const generateCommitMessage: TextGenerationShape["generateCommitMessage"] = Effect.fn( + "GrokTextGeneration.generateCommitMessage", + )(function* (input) { + const { prompt, outputSchema } = buildCommitMessagePrompt({ + branch: input.branch, + stagedSummary: input.stagedSummary, + stagedPatch: input.stagedPatch, + includeBranch: input.includeBranch === true, + }); + + const generated = yield* runGrokJson({ + operation: "generateCommitMessage", + cwd: input.cwd, + prompt, + outputSchemaJson: outputSchema, + modelSelection: input.modelSelection, + }); + + return { + subject: sanitizeCommitSubject(generated.subject), + body: generated.body.trim(), + ...("branch" in generated && typeof generated.branch === "string" + ? { branch: sanitizeFeatureBranchName(generated.branch) } + : {}), + }; + }); + + const generatePrContent: TextGenerationShape["generatePrContent"] = Effect.fn( + "GrokTextGeneration.generatePrContent", + )(function* (input) { + const { prompt, outputSchema } = buildPrContentPrompt({ + baseBranch: input.baseBranch, + headBranch: input.headBranch, + commitSummary: input.commitSummary, + diffSummary: input.diffSummary, + diffPatch: input.diffPatch, + }); + + const generated = yield* runGrokJson({ + operation: "generatePrContent", + cwd: input.cwd, + prompt, + outputSchemaJson: outputSchema, + modelSelection: input.modelSelection, + }); + + return { + title: sanitizePrTitle(generated.title), + body: generated.body.trim(), + }; + }); + + const generateBranchName: TextGenerationShape["generateBranchName"] = Effect.fn( + "GrokTextGeneration.generateBranchName", + )(function* (input) { + const { prompt, outputSchema } = buildBranchNamePrompt({ + message: input.message, + attachments: input.attachments, + }); + + const generated = yield* runGrokJson({ + operation: "generateBranchName", + cwd: input.cwd, + prompt, + outputSchemaJson: outputSchema, + modelSelection: input.modelSelection, + }); + + return { + branch: sanitizeBranchFragment(generated.branch), + }; + }); + + const generateThreadTitle: TextGenerationShape["generateThreadTitle"] = Effect.fn( + "GrokTextGeneration.generateThreadTitle", + )(function* (input) { + const { prompt, outputSchema } = buildThreadTitlePrompt({ + message: input.message, + attachments: input.attachments, + }); + + const generated = yield* runGrokJson({ + operation: "generateThreadTitle", + cwd: input.cwd, + prompt, + outputSchemaJson: outputSchema, + modelSelection: input.modelSelection, + }); + + return { + title: sanitizeThreadTitle(generated.title), + } satisfies ThreadTitleGenerationResult; + }); + + return { + generateCommitMessage, + generatePrContent, + generateBranchName, + generateThreadTitle, + } satisfies TextGenerationShape; +}); diff --git a/apps/server/src/textGeneration/TextGeneration.ts b/apps/server/src/textGeneration/TextGeneration.ts index 2b149dabbb85..d5d28e638ed1 100644 --- a/apps/server/src/textGeneration/TextGeneration.ts +++ b/apps/server/src/textGeneration/TextGeneration.ts @@ -10,7 +10,7 @@ import { } from "../provider/Services/ProviderInstanceRegistry.ts"; import type { ProviderInstance } from "../provider/ProviderDriver.ts"; -export type TextGenerationProvider = "codex" | "claudeAgent" | "cursor" | "opencode"; +export type TextGenerationProvider = "codex" | "claudeAgent" | "cursor" | "grok" | "opencode"; export interface CommitMessageGenerationInput { cwd: string; diff --git a/apps/server/src/vcs/GitVcsDriver.test.ts b/apps/server/src/vcs/GitVcsDriver.test.ts index 809a869aa97f..70bb8655ea18 100644 --- a/apps/server/src/vcs/GitVcsDriver.test.ts +++ b/apps/server/src/vcs/GitVcsDriver.test.ts @@ -108,44 +108,3 @@ it.effect("GitVcsDriver forwards execute env to the VCS process", () => { ), ); }); - -it.effect("getPrDiff computes valid unified diff for a real git repo", () => - Effect.gen(function* () { - const fileSystem = yield* FileSystem.FileSystem; - const path = yield* Path.Path; - const tempDir = yield* fileSystem.makeTempDirectory({ - prefix: "t3-getPrDiff-test-", - }); - - yield* Effect.gen(function* () { - yield* runGit(tempDir, ["init"]); - yield* runGit(tempDir, ["config", "user.email", "test@test.com"]); - yield* runGit(tempDir, ["config", "user.name", "Test"]); - - yield* fileSystem.writeFileString(path.join(tempDir, "hello.txt"), "Hello, world!\n"); - yield* runGit(tempDir, ["add", "hello.txt"]); - yield* runGit(tempDir, ["commit", "-m", "initial commit"]); - yield* runGit(tempDir, ["branch", "-M", "main"]); - - yield* runGit(tempDir, ["checkout", "-b", "feature-branch"]); - - yield* fileSystem.writeFileString(path.join(tempDir, "hello.txt"), "Hello, review world!\n"); - yield* runGit(tempDir, ["add", "hello.txt"]); - yield* runGit(tempDir, ["commit", "-m", "feature changes"]); - - const driver = yield* GitVcsDriver.GitVcsDriver; - const diff = yield* driver.getPrDiff(tempDir, "main", "feature-branch"); - - assert.ok( - diff.includes("@@"), - `expected diff to contain hunk header (@@), got: ${diff.slice(0, 100)}`, - ); - assert.ok(diff.includes("---"), "expected diff to contain file marker (---)"); - assert.ok(diff.includes("+++"), "expected diff to contain file marker (+++)"); - - yield* fileSystem.remove(tempDir, { recursive: true }).pipe(Effect.ignore); - }).pipe( - Effect.onError(() => fileSystem.remove(tempDir, { recursive: true }).pipe(Effect.ignore)), - ); - }).pipe(Effect.provide(GitContractLayer)), -); diff --git a/apps/server/src/vcs/GitVcsDriver.ts b/apps/server/src/vcs/GitVcsDriver.ts index 1c36633bfd40..465cd21f320d 100644 --- a/apps/server/src/vcs/GitVcsDriver.ts +++ b/apps/server/src/vcs/GitVcsDriver.ts @@ -219,11 +219,6 @@ export interface GitVcsDriverShape { ) => Effect.Effect; readonly initRepo: (input: VcsInitInput) => Effect.Effect; readonly listLocalBranchNames: (cwd: string) => Effect.Effect; - readonly getPrDiff: ( - cwd: string, - baseRef: string, - headRef: string, - ) => Effect.Effect; } export class GitVcsDriver extends Context.Service()( diff --git a/apps/server/src/vcs/GitVcsDriverCore.ts b/apps/server/src/vcs/GitVcsDriverCore.ts index 147a96d46256..240c20336c60 100644 --- a/apps/server/src/vcs/GitVcsDriverCore.ts +++ b/apps/server/src/vcs/GitVcsDriverCore.ts @@ -2278,21 +2278,6 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function* fallbackErrorMessage: "git init failed", }).pipe(Effect.asVoid); - const getPrDiff: GitVcsDriver.GitVcsDriverShape["getPrDiff"] = (cwd, baseRef, headRef) => - runGitStdout( - "GitVcsDriver.getPrDiff", - cwd, - [ - "diff", - "--patch", - "--no-color", - "--no-ext-diff", - "--no-textconv", - `${baseRef}...${headRef}`, - ], - false, - ); - const listLocalBranchNames: GitVcsDriver.GitVcsDriverShape["listLocalBranchNames"] = (cwd) => runGitStdout("GitVcsDriver.listLocalBranchNames", cwd, [ "branch", @@ -2338,6 +2323,5 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function* switchRef, initRepo, listLocalBranchNames, - getPrDiff, }); }); diff --git a/apps/server/src/ws.ts b/apps/server/src/ws.ts index 011200d8b169..ed53b471de8a 100644 --- a/apps/server/src/ws.ts +++ b/apps/server/src/ws.ts @@ -3,10 +3,8 @@ import * as Crypto from "effect/Crypto"; import * as DateTime from "effect/DateTime"; import * as Duration from "effect/Duration"; import * as Effect from "effect/Effect"; -import * as FileSystem from "effect/FileSystem"; import * as Layer from "effect/Layer"; import * as Option from "effect/Option"; -import * as Path from "effect/Path"; import * as Queue from "effect/Queue"; import * as Ref from "effect/Ref"; import * as Schema from "effect/Schema"; @@ -42,19 +40,15 @@ import { type RelayClientInstallProgressEvent, OrchestrationReplayEventsError, FilesystemBrowseError, - ChangeRequestGetPrDiffError, - ChangeRequestSubmitReviewError, - ChangeRequestRunBackgroundAgentError, - type BackgroundAgentResponseEvent, - ProviderInstanceId, EnvironmentAuthorizationError, + ProviderInstanceId, ThreadId, type TerminalAttachStreamEvent, type TerminalError, type TerminalEvent, + type TerminalMetadataStreamEvent, TodosLoadError, TodosMutateError, - type TerminalMetadataStreamEvent, WS_METHODS, WsRpcGroup, } from "@t3tools/contracts"; @@ -82,11 +76,12 @@ import { import { isClaudeAdapter } from "./provider/Services/ClaudeAdapter.ts"; import { ProviderAdapterRegistry } from "./provider/Services/ProviderAdapterRegistry.ts"; import { ProviderRegistry } from "./provider/Services/ProviderRegistry.ts"; +import * as ProviderMaintenanceRunner from "./provider/providerMaintenanceRunner.ts"; import { ServerLifecycleEvents } from "./serverLifecycleEvents.ts"; import { ServerRuntimeStartup } from "./serverRuntimeStartup.ts"; import { redactServerSettingsForClient, ServerSettingsService } from "./serverSettings.ts"; import { applyMutations, archiveDoneItems } from "@t3tools/shared/todoStore"; -import { appendToArchive, readTodos, type TodosData, writeTodos } from "./todoPersistence.ts"; +import { appendToArchive, readTodos, writeTodos } from "./todoPersistence.ts"; import { TerminalManager } from "./terminal/Services/Manager.ts"; import { WorkspaceEntries } from "./workspace/Services/WorkspaceEntries.ts"; import { WorkspaceFileSystem } from "./workspace/Services/WorkspaceFileSystem.ts"; @@ -94,9 +89,6 @@ import { WorkspacePathOutsideRootError } from "./workspace/Services/WorkspacePat import { VcsStatusBroadcaster } from "./vcs/VcsStatusBroadcaster.ts"; import { VcsProvisioningService } from "./vcs/VcsProvisioningService.ts"; import { GitWorkflowService } from "./git/GitWorkflowService.ts"; -import * as ProviderMaintenanceRunner from "./provider/providerMaintenanceRunner.ts"; -import * as SourceControlDiscovery from "./sourceControl/SourceControlDiscovery.ts"; -import * as BackgroundAgentService from "./review/BackgroundAgentService.ts"; import { ReviewService } from "./review/ReviewService.ts"; import { ProjectSetupScriptRunner } from "./project/Services/ProjectSetupScriptRunner.ts"; import { RepositoryIdentityResolver } from "./project/Services/RepositoryIdentityResolver.ts"; @@ -106,8 +98,17 @@ import type { AuthenticatedSession } from "./auth/EnvironmentAuth.ts"; import * as ProcessDiagnostics from "./diagnostics/ProcessDiagnostics.ts"; import * as ProcessResourceMonitor from "./diagnostics/ProcessResourceMonitor.ts"; import * as TraceDiagnostics from "./diagnostics/TraceDiagnostics.ts"; +import * as SourceControlDiscoveryLayer from "./sourceControl/SourceControlDiscovery.ts"; import { SourceControlRepositoryService } from "./sourceControl/SourceControlRepositoryService.ts"; +import * as AzureDevOpsCli from "./sourceControl/AzureDevOpsCli.ts"; +import * as BitbucketApi from "./sourceControl/BitbucketApi.ts"; +import * as GitHubCli from "./sourceControl/GitHubCli.ts"; +import * as GitLabCli from "./sourceControl/GitLabCli.ts"; +import * as SourceControlProviderRegistry from "./sourceControl/SourceControlProviderRegistry.ts"; import * as GitVcsDriver from "./vcs/GitVcsDriver.ts"; +import * as VcsDriverRegistry from "./vcs/VcsDriverRegistry.ts"; +import * as VcsProjectConfig from "./vcs/VcsProjectConfig.ts"; +import * as VcsProcess from "./vcs/VcsProcess.ts"; import * as PairingGrantStore from "./auth/PairingGrantStore.ts"; import * as SessionStore from "./auth/SessionStore.ts"; import { failEnvironmentAuthInvalid, failEnvironmentInternal } from "./auth/http.ts"; @@ -174,6 +175,8 @@ const RPC_REQUIRED_SCOPE = new Map([ [WS_METHODS.projectsWriteFile, AuthOrchestrationOperateScope], [WS_METHODS.shellOpenInEditor, AuthOrchestrationOperateScope], [WS_METHODS.filesystemBrowse, AuthOrchestrationReadScope], + [WS_METHODS.mcpListServers, AuthOrchestrationReadScope], + [WS_METHODS.mcpToggleServer, AuthOrchestrationOperateScope], [WS_METHODS.subscribeVcsStatus, AuthOrchestrationReadScope], [WS_METHODS.vcsRefreshStatus, AuthOrchestrationReadScope], [WS_METHODS.vcsPull, AuthOrchestrationOperateScope], @@ -187,12 +190,8 @@ const RPC_REQUIRED_SCOPE = new Map([ [WS_METHODS.vcsSwitchRef, AuthOrchestrationOperateScope], [WS_METHODS.vcsInit, AuthOrchestrationOperateScope], [WS_METHODS.reviewGetDiffPreview, AuthReviewWriteScope], - [WS_METHODS.changeRequestGetReviewDraft, AuthReviewWriteScope], - [WS_METHODS.changeRequestUpsertReviewComment, AuthReviewWriteScope], - [WS_METHODS.changeRequestDeleteReviewComment, AuthReviewWriteScope], - [WS_METHODS.changeRequestGetPrDiff, AuthReviewWriteScope], - [WS_METHODS.changeRequestSubmitReview, AuthReviewWriteScope], - [WS_METHODS.changeRequestRunBackgroundAgent, AuthReviewWriteScope], + [WS_METHODS.todosLoad, AuthOrchestrationReadScope], + [WS_METHODS.todosMutate, AuthOrchestrationOperateScope], [WS_METHODS.terminalOpen, AuthTerminalOperateScope], [WS_METHODS.terminalAttach, AuthTerminalOperateScope], [WS_METHODS.terminalWrite, AuthTerminalOperateScope], @@ -205,30 +204,12 @@ const RPC_REQUIRED_SCOPE = new Map([ [WS_METHODS.subscribeServerConfig, AuthOrchestrationReadScope], [WS_METHODS.subscribeServerLifecycle, AuthOrchestrationReadScope], [WS_METHODS.subscribeAuthAccess, AuthAccessReadScope], - [WS_METHODS.projectsList, AuthOrchestrationReadScope], - [WS_METHODS.projectsAdd, AuthOrchestrationOperateScope], - [WS_METHODS.projectsRemove, AuthOrchestrationOperateScope], - [WS_METHODS.mcpListServers, AuthOrchestrationReadScope], - [WS_METHODS.mcpToggleServer, AuthOrchestrationOperateScope], - [WS_METHODS.changeRequestRunBatchAgents, AuthReviewWriteScope], - [WS_METHODS.todosLoad, AuthOrchestrationReadScope], - [WS_METHODS.todosMutate, AuthOrchestrationOperateScope], ]); -/** - * Returns the tags of WS RPC methods served by {@link WsRpcGroup} that have no - * entry in {@link RPC_REQUIRED_SCOPE}. Must always be empty: an undeclared - * method throws at request time, which surfaces as a connection-level protocol - * defect and tears down the entire WebSocket (taking every in-flight - * subscription with it). Validated at boot in {@link websocketRpcRouteLayer} - * and by a regression test. - */ export const missingRpcScopeDeclarations = (): ReadonlyArray => { const missing: string[] = []; for (const tag of WsRpcGroup.requests.keys()) { - if (!RPC_REQUIRED_SCOPE.has(tag)) { - missing.push(tag); - } + if (!RPC_REQUIRED_SCOPE.has(tag)) missing.push(tag); } return missing; }; @@ -273,1749 +254,1412 @@ function toAuthAccessStreamEvent( } } -const makeWsRpcHandlers = (currentSession: AuthenticatedSession) => - Effect.gen(function* () { - const currentSessionId = currentSession.sessionId; - yield* Effect.logDebug("ws.rpc handlers init start", { - sessionId: currentSessionId, - }); - const loadService = (label: string, effect: Effect.Effect) => - Effect.logDebug("ws.rpc service start", { - sessionId: currentSessionId, - service: label, - }).pipe( - Effect.andThen(effect), - Effect.tap(() => - Effect.logDebug("ws.rpc service ready", { - sessionId: currentSessionId, - service: label, - }), +const makeWsRpcLayer = (currentSession: AuthenticatedSession) => + WsRpcGroup.toLayer( + Effect.gen(function* () { + const currentSessionId = currentSession.sessionId; + const crypto = yield* Crypto.Crypto; + const projectionSnapshotQuery = yield* ProjectionSnapshotQuery; + const orchestrationEngine = yield* OrchestrationEngineService; + const checkpointDiffQuery = yield* CheckpointDiffQuery; + const keybindings = yield* Keybindings; + const externalLauncher = yield* ExternalLauncher.ExternalLauncher; + const gitWorkflow = yield* GitWorkflowService; + const review = yield* ReviewService; + const vcsProvisioning = yield* VcsProvisioningService; + const vcsStatusBroadcaster = yield* VcsStatusBroadcaster; + const terminalManager = yield* TerminalManager; + const providerAdapterRegistry = yield* ProviderAdapterRegistry; + const providerRegistry = yield* ProviderRegistry; + const providerMaintenanceRunner = yield* ProviderMaintenanceRunner.ProviderMaintenanceRunner; + const config = yield* ServerConfig; + const lifecycleEvents = yield* ServerLifecycleEvents; + const serverSettings = yield* ServerSettingsService; + const startup = yield* ServerRuntimeStartup; + const workspaceEntries = yield* WorkspaceEntries; + const workspaceFileSystem = yield* WorkspaceFileSystem; + const projectSetupScriptRunner = yield* ProjectSetupScriptRunner; + const repositoryIdentityResolver = yield* RepositoryIdentityResolver; + const serverEnvironment = yield* ServerEnvironment; + const serverAuth = yield* EnvironmentAuth.EnvironmentAuth; + const sourceControlDiscovery = yield* SourceControlDiscoveryLayer.SourceControlDiscovery; + const automaticGitFetchInterval = serverSettings.getSettings.pipe( + Effect.map((settings) => settings.automaticGitFetchInterval), + Effect.catch((cause) => + Effect.logWarning("Failed to read automatic Git fetch interval setting", { + detail: cause.message, + }).pipe(Effect.as(DEFAULT_AUTOMATIC_GIT_FETCH_INTERVAL)), ), ); - const crypto = yield* loadService("Crypto.Crypto", Crypto.Crypto); - const projectionSnapshotQuery = yield* loadService( - "ProjectionSnapshotQuery", - ProjectionSnapshotQuery, - ); - const orchestrationEngine = yield* loadService( - "OrchestrationEngineService", - OrchestrationEngineService, - ); - const checkpointDiffQuery = yield* loadService("CheckpointDiffQuery", CheckpointDiffQuery); - const keybindings = yield* loadService("Keybindings", Keybindings); - const externalLauncher = yield* loadService( - "ExternalLauncher", - ExternalLauncher.ExternalLauncher, - ); - const gitWorkflow = yield* loadService("GitWorkflowService", GitWorkflowService); - const git = yield* loadService("GitVcsDriver", GitVcsDriver.GitVcsDriver); - const review = yield* loadService("ReviewService", ReviewService); - const backgroundAgent = yield* loadService( - "BackgroundAgentService", - BackgroundAgentService.BackgroundAgentService, - ); - yield* Effect.logDebug("ws.rpc layer review services ready", { - sessionId: currentSessionId, - }); - const vcsProvisioning = yield* VcsProvisioningService; - const vcsStatusBroadcaster = yield* VcsStatusBroadcaster; - const terminalManager = yield* TerminalManager; - const providerAdapterRegistry = yield* ProviderAdapterRegistry; - const providerRegistry = yield* ProviderRegistry; - const providerMaintenanceRunner = yield* ProviderMaintenanceRunner.ProviderMaintenanceRunner; - yield* Effect.logDebug("ws.rpc layer provider services ready", { - sessionId: currentSessionId, - }); - const config = yield* ServerConfig; - const lifecycleEvents = yield* ServerLifecycleEvents; - const serverSettings = yield* ServerSettingsService; - const startup = yield* ServerRuntimeStartup; - const workspaceEntries = yield* WorkspaceEntries; - const workspaceFileSystem = yield* WorkspaceFileSystem; - const projectSetupScriptRunner = yield* ProjectSetupScriptRunner; - const repositoryIdentityResolver = yield* RepositoryIdentityResolver; - const serverEnvironment = yield* ServerEnvironment; - const serverAuth = yield* EnvironmentAuth.EnvironmentAuth; - const sourceControlDiscovery = yield* SourceControlDiscovery.SourceControlDiscovery; - yield* Effect.logDebug("ws.rpc layer workspace services ready", { - sessionId: currentSessionId, - }); - const automaticGitFetchInterval = serverSettings.getSettings.pipe( - Effect.map((settings) => settings.automaticGitFetchInterval), - Effect.catch((cause) => - Effect.logWarning("Failed to read automatic Git fetch interval setting", { - detail: cause.message, - }).pipe(Effect.as(DEFAULT_AUTOMATIC_GIT_FETCH_INTERVAL)), - ), - ); - const sourceControlRepositories = yield* SourceControlRepositoryService; - const bootstrapCredentials = yield* PairingGrantStore.PairingGrantStore; - const sessions = yield* SessionStore.SessionStore; - const processDiagnostics = yield* ProcessDiagnostics.ProcessDiagnostics; - const processResourceMonitor = yield* ProcessResourceMonitor.ProcessResourceMonitor; - const relayClient = yield* RelayClient.RelayClient; - yield* Effect.logDebug("ws.rpc layer auxiliary services ready", { - sessionId: currentSessionId, - }); - const authorizationError = (requiredScope: AuthEnvironmentScope) => - new EnvironmentAuthorizationError({ - message: `The authenticated token is missing required scope: ${requiredScope}.`, - requiredScope, - }); - const authorizeEffect = ( - requiredScope: AuthEnvironmentScope, - effect: Effect.Effect, - ): Effect.Effect => - currentSession.scopes.includes(requiredScope) - ? effect - : Effect.fail(authorizationError(requiredScope)); - const authorizeStream = ( - requiredScope: AuthEnvironmentScope, - stream: Stream.Stream, - ): Stream.Stream => - currentSession.scopes.includes(requiredScope) - ? stream - : Stream.fail(authorizationError(requiredScope)); - const requiredScopeForMethod = (method: string): AuthEnvironmentScope => { - const requiredScope = RPC_REQUIRED_SCOPE.get(method); - if (requiredScope === undefined) { - throw new Error(`RPC method ${method} has no declared authorization scope.`); - } - return requiredScope; - }; - const observeRpcEffect = ( - method: string, - effect: Effect.Effect, - traceAttributes?: Readonly>, - ) => - instrumentRpcEffect( - method, - authorizeEffect(requiredScopeForMethod(method), effect), - traceAttributes, - ); - const observeRpcStream = ( - method: string, - stream: Stream.Stream, - traceAttributes?: Readonly>, - ) => - instrumentRpcStream( - method, - authorizeStream(requiredScopeForMethod(method), stream), - traceAttributes, - ); - const observeRpcStreamEffect = ( - method: string, - effect: Effect.Effect< - Stream.Stream, - EffectError, - EffectContext - >, - traceAttributes?: Readonly>, - ) => - instrumentRpcStreamEffect( - method, - authorizeEffect(requiredScopeForMethod(method), effect), - traceAttributes, - ); - const toDispatchCommandError = (cause: unknown, fallbackMessage: string) => - isOrchestrationDispatchCommandError(cause) - ? cause - : new OrchestrationDispatchCommandError({ - message: cause instanceof Error ? cause.message : fallbackMessage, - cause, - }); - const randomUUID = crypto.randomUUIDv4.pipe( - Effect.mapError((cause) => - toDispatchCommandError(cause, "Failed to generate orchestration command identifier."), - ), - ); - const serverEventId = randomUUID.pipe(Effect.map(EventId.make)); - const serverCommandId = (tag: string) => - randomUUID.pipe(Effect.map((uuid) => CommandId.make(`server:${tag}:${uuid}`))); - - const loadAuthAccessSnapshot = () => - Effect.all({ - pairingLinks: serverAuth.listPairingLinks(), - clientSessions: serverAuth.listClientSessions(currentSessionId), - }).pipe( - Effect.mapError( - (error) => - new AuthAccessStreamError({ - message: error.message, - }), + const sourceControlRepositories = yield* SourceControlRepositoryService; + const bootstrapCredentials = yield* PairingGrantStore.PairingGrantStore; + const sessions = yield* SessionStore.SessionStore; + const processDiagnostics = yield* ProcessDiagnostics.ProcessDiagnostics; + const processResourceMonitor = yield* ProcessResourceMonitor.ProcessResourceMonitor; + const relayClient = yield* RelayClient.RelayClient; + const authorizationError = (requiredScope: AuthEnvironmentScope) => + new EnvironmentAuthorizationError({ + message: `The authenticated token is missing required scope: ${requiredScope}.`, + requiredScope, + }); + const authorizeEffect = ( + requiredScope: AuthEnvironmentScope, + effect: Effect.Effect, + ): Effect.Effect => + currentSession.scopes.includes(requiredScope) + ? effect + : Effect.fail(authorizationError(requiredScope)); + const authorizeStream = ( + requiredScope: AuthEnvironmentScope, + stream: Stream.Stream, + ): Stream.Stream => + currentSession.scopes.includes(requiredScope) + ? stream + : Stream.fail(authorizationError(requiredScope)); + const requiredScopeForMethod = (method: string): AuthEnvironmentScope => { + const requiredScope = RPC_REQUIRED_SCOPE.get(method); + if (requiredScope === undefined) { + throw new Error(`RPC method ${method} has no declared authorization scope.`); + } + return requiredScope; + }; + const observeRpcEffect = ( + method: string, + effect: Effect.Effect, + traceAttributes?: Readonly>, + ) => + instrumentRpcEffect( + method, + authorizeEffect(requiredScopeForMethod(method), effect), + traceAttributes, + ); + const observeRpcStream = ( + method: string, + stream: Stream.Stream, + traceAttributes?: Readonly>, + ) => + instrumentRpcStream( + method, + authorizeStream(requiredScopeForMethod(method), stream), + traceAttributes, + ); + const observeRpcStreamEffect = ( + method: string, + effect: Effect.Effect< + Stream.Stream, + EffectError, + EffectContext + >, + traceAttributes?: Readonly>, + ) => + instrumentRpcStreamEffect( + method, + authorizeEffect(requiredScopeForMethod(method), effect), + traceAttributes, + ); + const toDispatchCommandError = (cause: unknown, fallbackMessage: string) => + isOrchestrationDispatchCommandError(cause) + ? cause + : new OrchestrationDispatchCommandError({ + message: cause instanceof Error ? cause.message : fallbackMessage, + cause, + }); + const randomUUID = crypto.randomUUIDv4.pipe( + Effect.mapError((cause) => + toDispatchCommandError(cause, "Failed to generate orchestration command identifier."), ), ); + const serverEventId = randomUUID.pipe(Effect.map(EventId.make)); + const serverCommandId = (tag: string) => + randomUUID.pipe(Effect.map((uuid) => CommandId.make(`server:${tag}:${uuid}`))); - const appendSetupScriptActivity = (input: { - readonly threadId: ThreadId; - readonly kind: "setup-script.requested" | "setup-script.started" | "setup-script.failed"; - readonly summary: string; - readonly createdAt: string; - readonly payload: Record; - readonly tone: "info" | "error"; - }) => - Effect.all({ - commandId: serverCommandId("setup-script-activity"), - activityId: serverEventId, - }).pipe( - Effect.flatMap(({ commandId, activityId }) => - orchestrationEngine.dispatch({ - type: "thread.activity.append", - commandId, - threadId: input.threadId, - activity: { - id: activityId, - tone: input.tone, - kind: input.kind, - summary: input.summary, - payload: input.payload, - turnId: null, + const loadAuthAccessSnapshot = () => + Effect.all({ + pairingLinks: serverAuth.listPairingLinks(), + clientSessions: serverAuth.listClientSessions(currentSessionId), + }).pipe( + Effect.mapError( + (error) => + new AuthAccessStreamError({ + message: error.message, + }), + ), + ); + + const appendSetupScriptActivity = (input: { + readonly threadId: ThreadId; + readonly kind: "setup-script.requested" | "setup-script.started" | "setup-script.failed"; + readonly summary: string; + readonly createdAt: string; + readonly payload: Record; + readonly tone: "info" | "error"; + }) => + Effect.all({ + commandId: serverCommandId("setup-script-activity"), + activityId: serverEventId, + }).pipe( + Effect.flatMap(({ commandId, activityId }) => + orchestrationEngine.dispatch({ + type: "thread.activity.append", + commandId, + threadId: input.threadId, + activity: { + id: activityId, + tone: input.tone, + kind: input.kind, + summary: input.summary, + payload: input.payload, + turnId: null, + createdAt: input.createdAt, + }, createdAt: input.createdAt, - }, - createdAt: input.createdAt, - }), - ), - ); + }), + ), + ); + + const toBootstrapDispatchCommandCauseError = (cause: Cause.Cause) => { + const error = Cause.squash(cause); + return isOrchestrationDispatchCommandError(error) + ? error + : new OrchestrationDispatchCommandError({ + message: + error instanceof Error ? error.message : "Failed to bootstrap thread turn start.", + cause, + }); + }; - const toBootstrapDispatchCommandCauseError = (cause: Cause.Cause) => { - const error = Cause.squash(cause); - return isOrchestrationDispatchCommandError(error) - ? error - : new OrchestrationDispatchCommandError({ - message: - error instanceof Error ? error.message : "Failed to bootstrap thread turn start.", + const toMcpToggleError = (cause: unknown, fallbackDetail: string): McpToggleError => { + if (isMcpToggleError(cause)) { + return cause; + } + if (isProviderUnsupportedError(cause)) { + return new McpToggleError({ + kind: "provider-not-claude", + detail: cause.message, cause, }); - }; - - const toMcpToggleError = (cause: unknown, fallbackDetail: string): McpToggleError => { - if (isMcpToggleError(cause)) { - return cause; - } - if (isProviderUnsupportedError(cause)) { - return new McpToggleError({ - kind: "provider-not-claude", - detail: cause.message, - cause, - }); - } - if (isProviderAdapterSessionNotFoundError(cause)) { - return new McpToggleError({ - kind: "session-not-found", - detail: cause.message, - cause, - }); - } - if (isProviderAdapterProcessError(cause)) { + } + if (isProviderAdapterSessionNotFoundError(cause)) { + return new McpToggleError({ + kind: "session-not-found", + detail: cause.message, + cause, + }); + } + if (isProviderAdapterProcessError(cause)) { + return new McpToggleError({ + kind: "sdk-failure", + detail: cause.detail, + cause, + }); + } return new McpToggleError({ kind: "sdk-failure", - detail: cause.detail, + detail: cause instanceof Error ? cause.message : fallbackDetail, cause, }); - } - return new McpToggleError({ - kind: "sdk-failure", - detail: cause instanceof Error ? cause.message : fallbackDetail, - cause, - }); - }; + }; - const loadClaudeAdapter = () => - providerAdapterRegistry.getByInstance(ProviderInstanceId.make("claudeAgent")).pipe( - Effect.flatMap((adapter) => - isClaudeAdapter(adapter) - ? Effect.succeed(adapter) - : Effect.fail( - new McpToggleError({ - kind: "provider-not-claude", - detail: "MCP toggles are only available for the Claude provider.", - }), - ), - ), - Effect.mapError((cause) => - toMcpToggleError(cause, "Failed to load the Claude provider adapter."), - ), - ); + const loadClaudeAdapter = () => + providerAdapterRegistry.getByInstance(ProviderInstanceId.make("claudeAgent")).pipe( + Effect.flatMap((adapter) => + isClaudeAdapter(adapter) + ? Effect.succeed(adapter) + : Effect.fail( + new McpToggleError({ + kind: "provider-not-claude", + detail: "MCP toggles are only available for the Claude provider.", + }), + ), + ), + Effect.mapError((cause) => + toMcpToggleError(cause, "Failed to load the Claude provider adapter."), + ), + ); - const enrichProjectEvent = ( - event: OrchestrationEvent, - ): Effect.Effect => { - switch (event.type) { - case "project.created": - return repositoryIdentityResolver.resolve(event.payload.workspaceRoot).pipe( - Effect.map((repositoryIdentity) => ({ - ...event, - payload: { - ...event.payload, - repositoryIdentity, - }, - })), - ); - case "project.meta-updated": - return Effect.gen(function* () { - const workspaceRoot = - event.payload.workspaceRoot ?? - Option.match( - yield* projectionSnapshotQuery.getProjectShellById(event.payload.projectId), - { - onNone: () => null, - onSome: (project) => project.workspaceRoot, + const enrichProjectEvent = ( + event: OrchestrationEvent, + ): Effect.Effect => { + switch (event.type) { + case "project.created": + return repositoryIdentityResolver.resolve(event.payload.workspaceRoot).pipe( + Effect.map((repositoryIdentity) => ({ + ...event, + payload: { + ...event.payload, + repositoryIdentity, }, - ) ?? - null; - if (workspaceRoot === null) { - return event; - } + })), + ); + case "project.meta-updated": + return Effect.gen(function* () { + const workspaceRoot = + event.payload.workspaceRoot ?? + Option.match( + yield* projectionSnapshotQuery.getProjectShellById(event.payload.projectId), + { + onNone: () => null, + onSome: (project) => project.workspaceRoot, + }, + ) ?? + null; + if (workspaceRoot === null) { + return event; + } - const repositoryIdentity = yield* repositoryIdentityResolver.resolve(workspaceRoot); - return { - ...event, - payload: { - ...event.payload, - repositoryIdentity, - }, - } satisfies OrchestrationEvent; - }).pipe(Effect.orElseSucceed(() => event)); - default: - return Effect.succeed(event); - } - }; + const repositoryIdentity = yield* repositoryIdentityResolver.resolve(workspaceRoot); + return { + ...event, + payload: { + ...event.payload, + repositoryIdentity, + }, + } satisfies OrchestrationEvent; + }).pipe(Effect.orElseSucceed(() => event)); + default: + return Effect.succeed(event); + } + }; - const enrichOrchestrationEvents = (events: ReadonlyArray) => - Effect.forEach(events, enrichProjectEvent, { concurrency: 4 }); + const enrichOrchestrationEvents = (events: ReadonlyArray) => + Effect.forEach(events, enrichProjectEvent, { concurrency: 4 }); - const toShellStreamEvent = ( - event: OrchestrationEvent, - ): Effect.Effect, never, never> => { - switch (event.type) { - case "project.created": - case "project.meta-updated": - return projectionSnapshotQuery.getProjectShellById(event.payload.projectId).pipe( - Effect.map((project) => - Option.map(project, (nextProject) => ({ - kind: "project-upserted" as const, - sequence: event.sequence, - project: nextProject, - })), - ), - Effect.orElseSucceed(() => Option.none()), - ); - case "project.deleted": - return Effect.succeed( - Option.some({ - kind: "project-removed" as const, - sequence: event.sequence, - projectId: event.payload.projectId, - }), - ); - case "thread.deleted": - case "thread.archived": - return Effect.succeed( - Option.some({ - kind: "thread-removed" as const, - sequence: event.sequence, - threadId: event.payload.threadId, - }), - ); - case "thread.unarchived": - return projectionSnapshotQuery.getThreadShellById(event.payload.threadId).pipe( - Effect.map((thread) => - Option.map(thread, (nextThread) => ({ - kind: "thread-upserted" as const, + const toShellStreamEvent = ( + event: OrchestrationEvent, + ): Effect.Effect, never, never> => { + switch (event.type) { + case "project.created": + case "project.meta-updated": + return projectionSnapshotQuery.getProjectShellById(event.payload.projectId).pipe( + Effect.map((project) => + Option.map(project, (nextProject) => ({ + kind: "project-upserted" as const, + sequence: event.sequence, + project: nextProject, + })), + ), + Effect.orElseSucceed(() => Option.none()), + ); + case "project.deleted": + return Effect.succeed( + Option.some({ + kind: "project-removed" as const, sequence: event.sequence, - thread: nextThread, - })), - ), - Effect.orElseSucceed(() => Option.none()), - ); - default: - if (event.aggregateKind !== "thread") { - return Effect.succeed(Option.none()); - } - return projectionSnapshotQuery.getThreadShellById(ThreadId.make(event.aggregateId)).pipe( - Effect.map((thread) => - Option.map(thread, (nextThread) => ({ - kind: "thread-upserted" as const, + projectId: event.payload.projectId, + }), + ); + case "thread.deleted": + case "thread.archived": + return Effect.succeed( + Option.some({ + kind: "thread-removed" as const, sequence: event.sequence, - thread: nextThread, - })), - ), - Effect.orElseSucceed(() => Option.none()), - ); - } - }; + threadId: event.payload.threadId, + }), + ); + case "thread.unarchived": + return projectionSnapshotQuery.getThreadShellById(event.payload.threadId).pipe( + Effect.map((thread) => + Option.map(thread, (nextThread) => ({ + kind: "thread-upserted" as const, + sequence: event.sequence, + thread: nextThread, + })), + ), + Effect.orElseSucceed(() => Option.none()), + ); + default: + if (event.aggregateKind !== "thread") { + return Effect.succeed(Option.none()); + } + return projectionSnapshotQuery + .getThreadShellById(ThreadId.make(event.aggregateId)) + .pipe( + Effect.map((thread) => + Option.map(thread, (nextThread) => ({ + kind: "thread-upserted" as const, + sequence: event.sequence, + thread: nextThread, + })), + ), + Effect.orElseSucceed(() => Option.none()), + ); + } + }; - const dispatchBootstrapTurnStart = ( - command: Extract, - ): Effect.Effect<{ readonly sequence: number }, OrchestrationDispatchCommandError> => - Effect.gen(function* () { - const bootstrap = command.bootstrap; - const { bootstrap: _bootstrap, ...finalTurnStartCommand } = command; - let createdThread = false; - let targetProjectId = bootstrap?.createThread?.projectId; - let targetProjectCwd = bootstrap?.prepareWorktree?.projectCwd; - let targetWorktreePath = bootstrap?.createThread?.worktreePath ?? null; + const dispatchBootstrapTurnStart = ( + command: Extract, + ): Effect.Effect<{ readonly sequence: number }, OrchestrationDispatchCommandError> => + Effect.gen(function* () { + const bootstrap = command.bootstrap; + const { bootstrap: _bootstrap, ...finalTurnStartCommand } = command; + let createdThread = false; + let targetProjectId = bootstrap?.createThread?.projectId; + let targetProjectCwd = bootstrap?.prepareWorktree?.projectCwd; + let targetWorktreePath = bootstrap?.createThread?.worktreePath ?? null; - const cleanupCreatedThread = () => - createdThread - ? serverCommandId("bootstrap-thread-delete").pipe( - Effect.flatMap((commandId) => - orchestrationEngine.dispatch({ - type: "thread.delete", - commandId, - threadId: command.threadId, - }), - ), - Effect.ignoreCause({ log: true }), - ) - : Effect.void; + const cleanupCreatedThread = () => + createdThread + ? serverCommandId("bootstrap-thread-delete").pipe( + Effect.flatMap((commandId) => + orchestrationEngine.dispatch({ + type: "thread.delete", + commandId, + threadId: command.threadId, + }), + ), + Effect.ignoreCause({ log: true }), + ) + : Effect.void; - const recordSetupScriptLaunchFailure = (input: { - readonly error: unknown; - readonly requestedAt: string; - readonly worktreePath: string; - }) => { - const detail = - input.error instanceof Error ? input.error.message : "Unknown setup failure."; - return appendSetupScriptActivity({ - threadId: command.threadId, - kind: "setup-script.failed", - summary: "Setup script failed to start", - createdAt: input.requestedAt, - payload: { - detail, - worktreePath: input.worktreePath, - }, - tone: "error", - }).pipe( - Effect.ignoreCause({ log: false }), - Effect.flatMap(() => - Effect.logWarning("bootstrap turn start failed to launch setup script", { - threadId: command.threadId, - worktreePath: input.worktreePath, + const recordSetupScriptLaunchFailure = (input: { + readonly error: unknown; + readonly requestedAt: string; + readonly worktreePath: string; + }) => { + const detail = + input.error instanceof Error ? input.error.message : "Unknown setup failure."; + return appendSetupScriptActivity({ + threadId: command.threadId, + kind: "setup-script.failed", + summary: "Setup script failed to start", + createdAt: input.requestedAt, + payload: { detail, - }), - ), - ); - }; - - const recordSetupScriptStarted = (input: { - readonly requestedAt: string; - readonly worktreePath: string; - readonly scriptId: string; - readonly scriptName: string; - readonly terminalId: string; - }) => - Effect.gen(function* () { - const startedAt = yield* nowIso; - const payload = { - scriptId: input.scriptId, - scriptName: input.scriptName, - terminalId: input.terminalId, - worktreePath: input.worktreePath, - }; - yield* Effect.all([ - appendSetupScriptActivity({ - threadId: command.threadId, - kind: "setup-script.requested", - summary: "Starting setup script", - createdAt: input.requestedAt, - payload, - tone: "info", - }), - appendSetupScriptActivity({ - threadId: command.threadId, - kind: "setup-script.started", - summary: "Setup script started", - createdAt: startedAt, - payload, - tone: "info", - }), - ]).pipe( - Effect.asVoid, - Effect.catch((error) => - Effect.logWarning( - "bootstrap turn start launched setup script but failed to record setup activity", - { - threadId: command.threadId, - worktreePath: input.worktreePath, - scriptId: input.scriptId, - terminalId: input.terminalId, - detail: error.message, - }, - ), + worktreePath: input.worktreePath, + }, + tone: "error", + }).pipe( + Effect.ignoreCause({ log: false }), + Effect.flatMap(() => + Effect.logWarning("bootstrap turn start failed to launch setup script", { + threadId: command.threadId, + worktreePath: input.worktreePath, + detail, + }), ), ); - }); + }; - const runSetupProgram = () => - Effect.gen(function* () { - if (!bootstrap?.runSetupScript || !targetWorktreePath) { - return; - } - const worktreePath = targetWorktreePath; - const requestedAt = yield* nowIso; - yield* projectSetupScriptRunner - .runForThread({ - threadId: command.threadId, - ...(targetProjectId ? { projectId: targetProjectId } : {}), - ...(targetProjectCwd ? { projectCwd: targetProjectCwd } : {}), - worktreePath, - }) - .pipe( - Effect.matchEffect({ - onFailure: (error) => - recordSetupScriptLaunchFailure({ - error, - requestedAt, - worktreePath, - }), - onSuccess: (setupResult) => { - if (setupResult.status !== "started") { - return Effect.void; - } - return recordSetupScriptStarted({ - requestedAt, - worktreePath, - scriptId: setupResult.scriptId, - scriptName: setupResult.scriptName, - terminalId: setupResult.terminalId, - }); - }, + const recordSetupScriptStarted = (input: { + readonly requestedAt: string; + readonly worktreePath: string; + readonly scriptId: string; + readonly scriptName: string; + readonly terminalId: string; + }) => + Effect.gen(function* () { + const startedAt = yield* nowIso; + const payload = { + scriptId: input.scriptId, + scriptName: input.scriptName, + terminalId: input.terminalId, + worktreePath: input.worktreePath, + }; + yield* Effect.all([ + appendSetupScriptActivity({ + threadId: command.threadId, + kind: "setup-script.requested", + summary: "Starting setup script", + createdAt: input.requestedAt, + payload, + tone: "info", }), + appendSetupScriptActivity({ + threadId: command.threadId, + kind: "setup-script.started", + summary: "Setup script started", + createdAt: startedAt, + payload, + tone: "info", + }), + ]).pipe( + Effect.asVoid, + Effect.catch((error) => + Effect.logWarning( + "bootstrap turn start launched setup script but failed to record setup activity", + { + threadId: command.threadId, + worktreePath: input.worktreePath, + scriptId: input.scriptId, + terminalId: input.terminalId, + detail: error.message, + }, + ), + ), ); - }); - - const bootstrapProgram = Effect.gen(function* () { - if (bootstrap?.createThread) { - yield* orchestrationEngine.dispatch({ - type: "thread.create", - commandId: yield* serverCommandId("bootstrap-thread-create"), - threadId: command.threadId, - projectId: bootstrap.createThread.projectId, - title: bootstrap.createThread.title, - modelSelection: bootstrap.createThread.modelSelection, - runtimeMode: bootstrap.createThread.runtimeMode, - interactionMode: bootstrap.createThread.interactionMode, - branch: bootstrap.createThread.branch, - worktreePath: bootstrap.createThread.worktreePath, - createdAt: bootstrap.createThread.createdAt, }); - createdThread = true; - } - if (bootstrap?.prepareWorktree) { - const worktree = yield* gitWorkflow.createWorktree({ - cwd: bootstrap.prepareWorktree.projectCwd, - refName: bootstrap.prepareWorktree.baseBranch, - newRefName: bootstrap.prepareWorktree.branch, - path: null, - }); - targetWorktreePath = worktree.worktree.path; - yield* orchestrationEngine.dispatch({ - type: "thread.meta.update", - commandId: yield* serverCommandId("bootstrap-thread-meta-update"), - threadId: command.threadId, - branch: worktree.worktree.refName, - worktreePath: targetWorktreePath, + const runSetupProgram = () => + Effect.gen(function* () { + if (!bootstrap?.runSetupScript || !targetWorktreePath) { + return; + } + const worktreePath = targetWorktreePath; + const requestedAt = yield* nowIso; + yield* projectSetupScriptRunner + .runForThread({ + threadId: command.threadId, + ...(targetProjectId ? { projectId: targetProjectId } : {}), + ...(targetProjectCwd ? { projectCwd: targetProjectCwd } : {}), + worktreePath, + }) + .pipe( + Effect.matchEffect({ + onFailure: (error) => + recordSetupScriptLaunchFailure({ + error, + requestedAt, + worktreePath, + }), + onSuccess: (setupResult) => { + if (setupResult.status !== "started") { + return Effect.void; + } + return recordSetupScriptStarted({ + requestedAt, + worktreePath, + scriptId: setupResult.scriptId, + scriptName: setupResult.scriptName, + terminalId: setupResult.terminalId, + }); + }, + }), + ); }); - yield* refreshGitStatus(targetWorktreePath); - } - - yield* runSetupProgram(); - return yield* orchestrationEngine.dispatch(finalTurnStartCommand); - }); + const bootstrapProgram = Effect.gen(function* () { + if (bootstrap?.createThread) { + yield* orchestrationEngine.dispatch({ + type: "thread.create", + commandId: yield* serverCommandId("bootstrap-thread-create"), + threadId: command.threadId, + projectId: bootstrap.createThread.projectId, + title: bootstrap.createThread.title, + modelSelection: bootstrap.createThread.modelSelection, + runtimeMode: bootstrap.createThread.runtimeMode, + interactionMode: bootstrap.createThread.interactionMode, + branch: bootstrap.createThread.branch, + worktreePath: bootstrap.createThread.worktreePath, + createdAt: bootstrap.createThread.createdAt, + }); + createdThread = true; + } - return yield* bootstrapProgram.pipe( - Effect.catchCause((cause) => { - const dispatchError = toBootstrapDispatchCommandCauseError(cause); - if (Cause.hasInterruptsOnly(cause)) { - return Effect.fail(dispatchError); + if (bootstrap?.prepareWorktree) { + const worktree = yield* gitWorkflow.createWorktree({ + cwd: bootstrap.prepareWorktree.projectCwd, + refName: bootstrap.prepareWorktree.baseBranch, + newRefName: bootstrap.prepareWorktree.branch, + path: null, + }); + targetWorktreePath = worktree.worktree.path; + yield* orchestrationEngine.dispatch({ + type: "thread.meta.update", + commandId: yield* serverCommandId("bootstrap-thread-meta-update"), + threadId: command.threadId, + branch: worktree.worktree.refName, + worktreePath: targetWorktreePath, + }); + yield* refreshGitStatus(targetWorktreePath); } - return cleanupCreatedThread().pipe(Effect.flatMap(() => Effect.fail(dispatchError))); - }), - ); - }); - const dispatchNormalizedCommand = ( - normalizedCommand: OrchestrationCommand, - ): Effect.Effect<{ readonly sequence: number }, OrchestrationDispatchCommandError> => { - const dispatchEffect = - normalizedCommand.type === "thread.turn.start" && normalizedCommand.bootstrap - ? dispatchBootstrapTurnStart(normalizedCommand) - : orchestrationEngine - .dispatch(normalizedCommand) - .pipe( - Effect.mapError((cause) => - toDispatchCommandError(cause, "Failed to dispatch orchestration command"), - ), - ); + yield* runSetupProgram(); - return startup - .enqueueCommand(dispatchEffect) - .pipe( - Effect.mapError((cause) => - toDispatchCommandError(cause, "Failed to dispatch orchestration command"), - ), - ); - }; + return yield* orchestrationEngine.dispatch(finalTurnStartCommand); + }); - const loadServerConfig = Effect.gen(function* () { - const keybindingsConfig = yield* keybindings.loadConfigState; - const providers = yield* providerRegistry.getProviders; - const settings = redactServerSettingsForClient(yield* serverSettings.getSettings); - const environment = yield* serverEnvironment.getDescriptor; - const auth = yield* serverAuth.getDescriptor(); + return yield* bootstrapProgram.pipe( + Effect.catchCause((cause) => { + const dispatchError = toBootstrapDispatchCommandCauseError(cause); + if (Cause.hasInterruptsOnly(cause)) { + return Effect.fail(dispatchError); + } + return cleanupCreatedThread().pipe(Effect.flatMap(() => Effect.fail(dispatchError))); + }), + ); + }); - return { - environment, - auth, - cwd: config.cwd, - keybindingsConfigPath: config.keybindingsConfigPath, - keybindings: keybindingsConfig.keybindings, - issues: keybindingsConfig.issues, - providers, - availableEditors: ExternalLauncher.resolveAvailableEditors(), - observability: { - logsDirectoryPath: config.logsDir, - localTracingEnabled: true, - ...(config.otlpTracesUrl !== undefined ? { otlpTracesUrl: config.otlpTracesUrl } : {}), - otlpTracesEnabled: config.otlpTracesUrl !== undefined, - ...(config.otlpMetricsUrl !== undefined ? { otlpMetricsUrl: config.otlpMetricsUrl } : {}), - otlpMetricsEnabled: config.otlpMetricsUrl !== undefined, - }, - settings, + const dispatchNormalizedCommand = ( + normalizedCommand: OrchestrationCommand, + ): Effect.Effect<{ readonly sequence: number }, OrchestrationDispatchCommandError> => { + const dispatchEffect = + normalizedCommand.type === "thread.turn.start" && normalizedCommand.bootstrap + ? dispatchBootstrapTurnStart(normalizedCommand) + : orchestrationEngine + .dispatch(normalizedCommand) + .pipe( + Effect.mapError((cause) => + toDispatchCommandError(cause, "Failed to dispatch orchestration command"), + ), + ); + + return startup + .enqueueCommand(dispatchEffect) + .pipe( + Effect.mapError((cause) => + toDispatchCommandError(cause, "Failed to dispatch orchestration command"), + ), + ); }; - }); - const refreshGitStatus = (cwd: string) => - vcsStatusBroadcaster - .refreshStatus(cwd) - .pipe(Effect.ignoreCause({ log: true }), Effect.forkDetach, Effect.asVoid); + const loadServerConfig = Effect.gen(function* () { + const keybindingsConfig = yield* keybindings.loadConfigState; + const providers = yield* providerRegistry.getProviders; + const settings = redactServerSettingsForClient(yield* serverSettings.getSettings); + const environment = yield* serverEnvironment.getDescriptor; + const auth = yield* serverAuth.getDescriptor(); - return WsRpcGroup.of({ - [ORCHESTRATION_WS_METHODS.dispatchCommand]: (command) => - observeRpcEffect( - ORCHESTRATION_WS_METHODS.dispatchCommand, - Effect.gen(function* () { - const normalizedCommand = yield* normalizeDispatchCommand(command); - const shouldStopSessionAfterArchive = - normalizedCommand.type === "thread.archive" - ? yield* projectionSnapshotQuery - .getThreadShellById(normalizedCommand.threadId) - .pipe( - Effect.map( - Option.match({ - onNone: () => false, - onSome: (thread) => - thread.session !== null && thread.session.status !== "stopped", - }), + return { + environment, + auth, + cwd: config.cwd, + keybindingsConfigPath: config.keybindingsConfigPath, + keybindings: keybindingsConfig.keybindings, + issues: keybindingsConfig.issues, + providers, + availableEditors: ExternalLauncher.resolveAvailableEditors(), + observability: { + logsDirectoryPath: config.logsDir, + localTracingEnabled: true, + ...(config.otlpTracesUrl !== undefined ? { otlpTracesUrl: config.otlpTracesUrl } : {}), + otlpTracesEnabled: config.otlpTracesUrl !== undefined, + ...(config.otlpMetricsUrl !== undefined + ? { otlpMetricsUrl: config.otlpMetricsUrl } + : {}), + otlpMetricsEnabled: config.otlpMetricsUrl !== undefined, + }, + settings, + }; + }); + + const refreshGitStatus = (cwd: string) => + vcsStatusBroadcaster + .refreshStatus(cwd) + .pipe(Effect.ignoreCause({ log: true }), Effect.forkDetach, Effect.asVoid); + + return WsRpcGroup.of({ + [ORCHESTRATION_WS_METHODS.dispatchCommand]: (command) => + observeRpcEffect( + ORCHESTRATION_WS_METHODS.dispatchCommand, + Effect.gen(function* () { + const normalizedCommand = yield* normalizeDispatchCommand(command); + const shouldStopSessionAfterArchive = + normalizedCommand.type === "thread.archive" + ? yield* projectionSnapshotQuery + .getThreadShellById(normalizedCommand.threadId) + .pipe( + Effect.map( + Option.match({ + onNone: () => false, + onSome: (thread) => + thread.session !== null && thread.session.status !== "stopped", + }), + ), + Effect.orElseSucceed(() => false), + ) + : false; + const result = yield* dispatchNormalizedCommand(normalizedCommand); + if (normalizedCommand.type === "thread.archive") { + if (shouldStopSessionAfterArchive) { + yield* Effect.gen(function* () { + const stopCommand = yield* normalizeDispatchCommand({ + type: "thread.session.stop", + commandId: CommandId.make( + `session-stop-for-archive:${normalizedCommand.commandId}`, ), - Effect.orElseSucceed(() => false), - ) - : false; - const result = yield* dispatchNormalizedCommand(normalizedCommand); - if (normalizedCommand.type === "thread.archive") { - if (shouldStopSessionAfterArchive) { - yield* Effect.gen(function* () { - const stopCommand = yield* normalizeDispatchCommand({ - type: "thread.session.stop", - commandId: CommandId.make( - `session-stop-for-archive:${normalizedCommand.commandId}`, + threadId: normalizedCommand.threadId, + createdAt: yield* nowIso, + }); + + yield* dispatchNormalizedCommand(stopCommand); + }).pipe( + Effect.catchCause((cause) => + Effect.logWarning("failed to stop provider session during archive", { + threadId: normalizedCommand.threadId, + cause, + }), ), - threadId: normalizedCommand.threadId, - createdAt: yield* nowIso, - }); + ); + } - yield* dispatchNormalizedCommand(stopCommand); - }).pipe( - Effect.catchCause((cause) => - Effect.logWarning("failed to stop provider session during archive", { + yield* terminalManager.close({ threadId: normalizedCommand.threadId }).pipe( + Effect.catch((error) => + Effect.logWarning("failed to close thread terminals after archive", { threadId: normalizedCommand.threadId, - cause, + error: error.message, }), ), ); } - - yield* terminalManager.close({ threadId: normalizedCommand.threadId }).pipe( - Effect.catch((error) => - Effect.logWarning("failed to close thread terminals after archive", { - threadId: normalizedCommand.threadId, - error: error.message, - }), - ), - ); - } - return result; - }).pipe( - Effect.mapError((cause) => - isOrchestrationDispatchCommandError(cause) - ? cause - : new OrchestrationDispatchCommandError({ - message: "Failed to dispatch orchestration command", - cause, - }), + return result; + }).pipe( + Effect.mapError((cause) => + isOrchestrationDispatchCommandError(cause) + ? cause + : new OrchestrationDispatchCommandError({ + message: "Failed to dispatch orchestration command", + cause, + }), + ), ), + { "rpc.aggregate": "orchestration" }, ), - { "rpc.aggregate": "orchestration" }, - ), - [ORCHESTRATION_WS_METHODS.getTurnDiff]: (input) => - observeRpcEffect( - ORCHESTRATION_WS_METHODS.getTurnDiff, - checkpointDiffQuery.getTurnDiff(input).pipe( - Effect.mapError( - (cause) => - new OrchestrationGetTurnDiffError({ - message: "Failed to load turn diff", - cause, - }), + [ORCHESTRATION_WS_METHODS.getTurnDiff]: (input) => + observeRpcEffect( + ORCHESTRATION_WS_METHODS.getTurnDiff, + checkpointDiffQuery.getTurnDiff(input).pipe( + Effect.mapError( + (cause) => + new OrchestrationGetTurnDiffError({ + message: "Failed to load turn diff", + cause, + }), + ), ), + { "rpc.aggregate": "orchestration" }, ), - { "rpc.aggregate": "orchestration" }, - ), - [ORCHESTRATION_WS_METHODS.getFullThreadDiff]: (input) => - observeRpcEffect( - ORCHESTRATION_WS_METHODS.getFullThreadDiff, - checkpointDiffQuery.getFullThreadDiff(input).pipe( - Effect.mapError( - (cause) => - new OrchestrationGetFullThreadDiffError({ - message: "Failed to load full thread diff", - cause, - }), + [ORCHESTRATION_WS_METHODS.getFullThreadDiff]: (input) => + observeRpcEffect( + ORCHESTRATION_WS_METHODS.getFullThreadDiff, + checkpointDiffQuery.getFullThreadDiff(input).pipe( + Effect.mapError( + (cause) => + new OrchestrationGetFullThreadDiffError({ + message: "Failed to load full thread diff", + cause, + }), + ), ), + { "rpc.aggregate": "orchestration" }, ), - { "rpc.aggregate": "orchestration" }, - ), - [ORCHESTRATION_WS_METHODS.replayEvents]: (input) => - observeRpcEffect( - ORCHESTRATION_WS_METHODS.replayEvents, - Stream.runCollect( - orchestrationEngine.readEvents( - clamp(input.fromSequenceExclusive, { - maximum: Number.MAX_SAFE_INTEGER, - minimum: 0, - }), - ), - ).pipe( - Effect.map((events) => Array.from(events)), - Effect.flatMap(enrichOrchestrationEvents), - Effect.mapError( - (cause) => - new OrchestrationReplayEventsError({ - message: "Failed to replay orchestration events", - cause, + [ORCHESTRATION_WS_METHODS.replayEvents]: (input) => + observeRpcEffect( + ORCHESTRATION_WS_METHODS.replayEvents, + Stream.runCollect( + orchestrationEngine.readEvents( + clamp(input.fromSequenceExclusive, { + maximum: Number.MAX_SAFE_INTEGER, + minimum: 0, }), - ), - ), - { "rpc.aggregate": "orchestration" }, - ), - [ORCHESTRATION_WS_METHODS.subscribeShell]: (_input) => - observeRpcStreamEffect( - ORCHESTRATION_WS_METHODS.subscribeShell, - Effect.gen(function* () { - const snapshot = yield* projectionSnapshotQuery.getShellSnapshot().pipe( - Effect.tapError((cause) => - Effect.logError("orchestration shell snapshot load failed", { cause }), ), + ).pipe( + Effect.map((events) => Array.from(events)), + Effect.flatMap(enrichOrchestrationEvents), Effect.mapError( (cause) => - new OrchestrationGetSnapshotError({ - message: "Failed to load orchestration shell snapshot", + new OrchestrationReplayEventsError({ + message: "Failed to replay orchestration events", cause, }), ), - ); - - const liveStream = orchestrationEngine.streamDomainEvents.pipe( - Stream.mapEffect(toShellStreamEvent), - Stream.flatMap((event) => - Option.isSome(event) ? Stream.succeed(event.value) : Stream.empty, - ), - ); - - return Stream.concat( - Stream.make({ - kind: "snapshot" as const, - snapshot, - }), - liveStream, - ); - }), - { "rpc.aggregate": "orchestration" }, - ), - [ORCHESTRATION_WS_METHODS.getArchivedShellSnapshot]: (_input) => - observeRpcEffect( - ORCHESTRATION_WS_METHODS.getArchivedShellSnapshot, - projectionSnapshotQuery.getArchivedShellSnapshot().pipe( - Effect.tapError((cause) => - Effect.logError("orchestration archived shell snapshot load failed", { cause }), - ), - Effect.mapError( - (cause) => - new OrchestrationGetSnapshotError({ - message: "Failed to load archived orchestration shell snapshot", - cause, - }), ), + { "rpc.aggregate": "orchestration" }, ), - { "rpc.aggregate": "orchestration" }, - ), - [ORCHESTRATION_WS_METHODS.subscribeThread]: (input) => - observeRpcStreamEffect( - ORCHESTRATION_WS_METHODS.subscribeThread, - Effect.gen(function* () { - const [threadDetail, snapshotSequence] = yield* Effect.all([ - projectionSnapshotQuery.getThreadDetailById(input.threadId).pipe( - Effect.mapError( - (cause) => - new OrchestrationGetSnapshotError({ - message: `Failed to load thread ${input.threadId}`, - cause, - }), + [ORCHESTRATION_WS_METHODS.subscribeShell]: (_input) => + observeRpcStreamEffect( + ORCHESTRATION_WS_METHODS.subscribeShell, + Effect.gen(function* () { + const snapshot = yield* projectionSnapshotQuery.getShellSnapshot().pipe( + Effect.tapError((cause) => + Effect.logError("orchestration shell snapshot load failed", { cause }), ), - ), - projectionSnapshotQuery.getSnapshotSequence().pipe( - Effect.map(({ snapshotSequence }) => snapshotSequence), Effect.mapError( (cause) => new OrchestrationGetSnapshotError({ - message: "Failed to load orchestration snapshot sequence", + message: "Failed to load orchestration shell snapshot", cause, }), ), - ), - ]); + ); - if (Option.isNone(threadDetail)) { - return yield* new OrchestrationGetSnapshotError({ - message: `Thread ${input.threadId} was not found`, - cause: input.threadId, - }); - } + const liveStream = orchestrationEngine.streamDomainEvents.pipe( + Stream.mapEffect(toShellStreamEvent), + Stream.flatMap((event) => + Option.isSome(event) ? Stream.succeed(event.value) : Stream.empty, + ), + ); - const liveStream = orchestrationEngine.streamDomainEvents.pipe( - Stream.filter( - (event) => - event.aggregateKind === "thread" && - event.aggregateId === input.threadId && - isThreadDetailEvent(event), + return Stream.concat( + Stream.make({ + kind: "snapshot" as const, + snapshot, + }), + liveStream, + ); + }), + { "rpc.aggregate": "orchestration" }, + ), + [ORCHESTRATION_WS_METHODS.getArchivedShellSnapshot]: (_input) => + observeRpcEffect( + ORCHESTRATION_WS_METHODS.getArchivedShellSnapshot, + projectionSnapshotQuery.getArchivedShellSnapshot().pipe( + Effect.tapError((cause) => + Effect.logError("orchestration archived shell snapshot load failed", { cause }), ), - Stream.map((event) => ({ - kind: "event" as const, - event, - })), - ); + Effect.mapError( + (cause) => + new OrchestrationGetSnapshotError({ + message: "Failed to load archived orchestration shell snapshot", + cause, + }), + ), + ), + { "rpc.aggregate": "orchestration" }, + ), + [ORCHESTRATION_WS_METHODS.subscribeThread]: (input) => + observeRpcStreamEffect( + ORCHESTRATION_WS_METHODS.subscribeThread, + Effect.gen(function* () { + const [threadDetail, snapshotSequence] = yield* Effect.all([ + projectionSnapshotQuery.getThreadDetailById(input.threadId).pipe( + Effect.mapError( + (cause) => + new OrchestrationGetSnapshotError({ + message: `Failed to load thread ${input.threadId}`, + cause, + }), + ), + ), + projectionSnapshotQuery.getSnapshotSequence().pipe( + Effect.map(({ snapshotSequence }) => snapshotSequence), + Effect.mapError( + (cause) => + new OrchestrationGetSnapshotError({ + message: "Failed to load orchestration snapshot sequence", + cause, + }), + ), + ), + ]); - return Stream.concat( - Stream.make({ - kind: "snapshot" as const, - snapshot: { - snapshotSequence, - thread: threadDetail.value, - }, - }), - liveStream, - ); - }), - { "rpc.aggregate": "orchestration" }, - ), - [WS_METHODS.serverGetConfig]: (_input) => - observeRpcEffect(WS_METHODS.serverGetConfig, loadServerConfig, { - "rpc.aggregate": "server", - }), - [WS_METHODS.serverRefreshProviders]: (input) => - observeRpcEffect( - WS_METHODS.serverRefreshProviders, - (input.instanceId !== undefined - ? providerRegistry.refreshInstance(input.instanceId) - : providerRegistry.refresh() - ).pipe(Effect.map((providers) => ({ providers }))), - { "rpc.aggregate": "server" }, - ), - [WS_METHODS.serverUpdateProvider]: (input) => - observeRpcEffect( - WS_METHODS.serverUpdateProvider, - providerMaintenanceRunner.updateProvider(input), - { + if (Option.isNone(threadDetail)) { + return yield* new OrchestrationGetSnapshotError({ + message: `Thread ${input.threadId} was not found`, + cause: input.threadId, + }); + } + + const liveStream = orchestrationEngine.streamDomainEvents.pipe( + Stream.filter( + (event) => + event.aggregateKind === "thread" && + event.aggregateId === input.threadId && + isThreadDetailEvent(event), + ), + Stream.map((event) => ({ + kind: "event" as const, + event, + })), + ); + + return Stream.concat( + Stream.make({ + kind: "snapshot" as const, + snapshot: { + snapshotSequence, + thread: threadDetail.value, + }, + }), + liveStream, + ); + }), + { "rpc.aggregate": "orchestration" }, + ), + [WS_METHODS.serverGetConfig]: (_input) => + observeRpcEffect(WS_METHODS.serverGetConfig, loadServerConfig, { "rpc.aggregate": "server", - }, - ), - [WS_METHODS.serverUpsertKeybinding]: (rule) => - observeRpcEffect( - WS_METHODS.serverUpsertKeybinding, - Effect.gen(function* () { - const keybindingsConfig = yield* keybindings.upsertKeybindingRule(rule); - return { keybindings: keybindingsConfig, issues: [] }; - }), - { "rpc.aggregate": "server" }, - ), - [WS_METHODS.serverRemoveKeybinding]: (rule) => - observeRpcEffect( - WS_METHODS.serverRemoveKeybinding, - Effect.gen(function* () { - const keybindingsConfig = yield* keybindings.removeKeybindingRule(rule); - return { keybindings: keybindingsConfig, issues: [] }; }), - { "rpc.aggregate": "server" }, - ), - [WS_METHODS.serverGetSettings]: (_input) => - observeRpcEffect( - WS_METHODS.serverGetSettings, - serverSettings.getSettings.pipe(Effect.map(redactServerSettingsForClient)), - { - "rpc.aggregate": "server", - }, - ), - [WS_METHODS.serverUpdateSettings]: ({ patch }) => - observeRpcEffect( - WS_METHODS.serverUpdateSettings, - serverSettings.updateSettings(patch).pipe(Effect.map(redactServerSettingsForClient)), - { + [WS_METHODS.serverRefreshProviders]: (input) => + observeRpcEffect( + WS_METHODS.serverRefreshProviders, + (input.instanceId !== undefined + ? providerRegistry.refreshInstance(input.instanceId) + : providerRegistry.refresh() + ).pipe(Effect.map((providers) => ({ providers }))), + { "rpc.aggregate": "server" }, + ), + [WS_METHODS.serverUpdateProvider]: (input) => + observeRpcEffect( + WS_METHODS.serverUpdateProvider, + providerMaintenanceRunner.updateProvider(input), + { + "rpc.aggregate": "server", + }, + ), + [WS_METHODS.serverUpsertKeybinding]: (rule) => + observeRpcEffect( + WS_METHODS.serverUpsertKeybinding, + Effect.gen(function* () { + const keybindingsConfig = yield* keybindings.upsertKeybindingRule(rule); + return { keybindings: keybindingsConfig, issues: [] }; + }), + { "rpc.aggregate": "server" }, + ), + [WS_METHODS.serverRemoveKeybinding]: (rule) => + observeRpcEffect( + WS_METHODS.serverRemoveKeybinding, + Effect.gen(function* () { + const keybindingsConfig = yield* keybindings.removeKeybindingRule(rule); + return { keybindings: keybindingsConfig, issues: [] }; + }), + { "rpc.aggregate": "server" }, + ), + [WS_METHODS.serverGetSettings]: (_input) => + observeRpcEffect( + WS_METHODS.serverGetSettings, + serverSettings.getSettings.pipe(Effect.map(redactServerSettingsForClient)), + { + "rpc.aggregate": "server", + }, + ), + [WS_METHODS.serverUpdateSettings]: ({ patch }) => + observeRpcEffect( + WS_METHODS.serverUpdateSettings, + serverSettings.updateSettings(patch).pipe(Effect.map(redactServerSettingsForClient)), + { + "rpc.aggregate": "server", + }, + ), + [WS_METHODS.serverDiscoverSourceControl]: (_input) => + observeRpcEffect( + WS_METHODS.serverDiscoverSourceControl, + sourceControlDiscovery.discover, + { + "rpc.aggregate": "server", + }, + ), + [WS_METHODS.serverGetTraceDiagnostics]: (_input) => + observeRpcEffect( + WS_METHODS.serverGetTraceDiagnostics, + TraceDiagnostics.readTraceDiagnostics({ + traceFilePath: config.serverTracePath, + maxFiles: config.traceMaxFiles, + }), + { + "rpc.aggregate": "server", + }, + ), + [WS_METHODS.serverGetProcessDiagnostics]: (_input) => + observeRpcEffect(WS_METHODS.serverGetProcessDiagnostics, processDiagnostics.read, { "rpc.aggregate": "server", - }, - ), - [WS_METHODS.serverDiscoverSourceControl]: (_input) => - observeRpcEffect(WS_METHODS.serverDiscoverSourceControl, sourceControlDiscovery.discover, { - "rpc.aggregate": "server", - }), - [WS_METHODS.serverGetTraceDiagnostics]: (_input) => - observeRpcEffect( - WS_METHODS.serverGetTraceDiagnostics, - TraceDiagnostics.readTraceDiagnostics({ - traceFilePath: config.serverTracePath, - maxFiles: config.traceMaxFiles, }), - { - "rpc.aggregate": "server", - }, - ), - [WS_METHODS.serverGetProcessDiagnostics]: (_input) => - observeRpcEffect(WS_METHODS.serverGetProcessDiagnostics, processDiagnostics.read, { - "rpc.aggregate": "server", - }), - [WS_METHODS.serverGetProcessResourceHistory]: (input) => - observeRpcEffect( - WS_METHODS.serverGetProcessResourceHistory, - processResourceMonitor.readHistory(input), - { + [WS_METHODS.serverGetProcessResourceHistory]: (input) => + observeRpcEffect( + WS_METHODS.serverGetProcessResourceHistory, + processResourceMonitor.readHistory(input), + { + "rpc.aggregate": "server", + }, + ), + [WS_METHODS.serverSignalProcess]: (input) => + observeRpcEffect(WS_METHODS.serverSignalProcess, processDiagnostics.signal(input), { "rpc.aggregate": "server", - }, - ), - [WS_METHODS.serverSignalProcess]: (input) => - observeRpcEffect(WS_METHODS.serverSignalProcess, processDiagnostics.signal(input), { - "rpc.aggregate": "server", - }), - [WS_METHODS.todosLoad]: (_payload) => - observeRpcEffect( - WS_METHODS.todosLoad, - Effect.gen(function* () { - yield* FileSystem.FileSystem; - return yield* readTodos(config.todosDir); - }).pipe( - Effect.catch((cause: unknown) => - Schema.is(TodosLoadError)(cause) - ? cause - : new TodosLoadError({ + }), + [WS_METHODS.cloudGetRelayClientStatus]: (_input) => + observeRpcEffect(WS_METHODS.cloudGetRelayClientStatus, relayClient.resolve, { + "rpc.aggregate": "cloud", + }), + [WS_METHODS.cloudInstallRelayClient]: (_input) => + observeRpcStream( + WS_METHODS.cloudInstallRelayClient, + Stream.callback( + (queue) => + relayClient + .installWithProgress((event) => Queue.offer(queue, event).pipe(Effect.asVoid)) + .pipe( + Effect.flatMap((status) => + Queue.offer(queue, { + type: "complete", + status, + }), + ), + Effect.catchTag("RelayClientInstallError", (error) => + Queue.fail( + queue, + new RelayClientInstallFailedError({ + reason: error.reason, + message: error.message, + }), + ), + ), + Effect.andThen(Queue.end(queue)), + Effect.forkScoped, + ), + ), + { "rpc.aggregate": "cloud" }, + ), + [WS_METHODS.todosLoad]: (_payload) => + observeRpcEffect( + WS_METHODS.todosLoad, + readTodos(config.todosDir).pipe( + Effect.mapError( + (cause) => + new TodosLoadError({ kind: "io-failure", detail: `Failed to load todos: ${cause}`, cause, }), + ), ), + { + "rpc.aggregate": "server", + }, ), - { - "rpc.aggregate": "server", - }, - ), - [WS_METHODS.todosMutate]: (input) => - observeRpcEffect( - WS_METHODS.todosMutate, - Effect.gen(function* () { - yield* FileSystem.FileSystem; - yield* Path.Path; - const current = yield* readTodos(config.todosDir); - const next = applyMutations( - { - categories: [...current.categories], - items: [...current.items], - jiraBaseUrl: current.jiraBaseUrl, - }, - input.mutations, - ); - const { state: deduped, archived } = archiveDoneItems(next); - if (archived.length > 0) { - yield* appendToArchive(config.todosDir, archived); - } - yield* writeTodos(config.todosDir, deduped as unknown as TodosData); - return deduped; - }).pipe( - Effect.catch((cause: unknown) => - Schema.is(TodosMutateError)(cause) - ? cause - : new TodosMutateError({ + [WS_METHODS.todosMutate]: (input) => + observeRpcEffect( + WS_METHODS.todosMutate, + Effect.gen(function* () { + const current = yield* readTodos(config.todosDir); + const next = applyMutations( + { + categories: current.categories, + items: current.items, + jiraBaseUrl: current.jiraBaseUrl, + }, + input.mutations, + ); + const { state: deduped, archived } = archiveDoneItems(next); + if (archived.length > 0) { + yield* appendToArchive(config.todosDir, archived); + } + yield* writeTodos(config.todosDir, { + categories: deduped.categories, + items: deduped.items, + ...(deduped.jiraBaseUrl === undefined ? {} : { jiraBaseUrl: deduped.jiraBaseUrl }), + }); + return { + categories: deduped.categories, + items: deduped.items, + ...(deduped.jiraBaseUrl === undefined ? {} : { jiraBaseUrl: deduped.jiraBaseUrl }), + }; + }).pipe( + Effect.mapError( + (cause) => + new TodosMutateError({ kind: "io-failure", detail: `Failed to mutate todos: ${cause}`, cause, }), + ), ), + { + "rpc.aggregate": "server", + }, ), - { - "rpc.aggregate": "server", - }, - ), - [WS_METHODS.cloudGetRelayClientStatus]: (_input) => - observeRpcEffect(WS_METHODS.cloudGetRelayClientStatus, relayClient.resolve, { - "rpc.aggregate": "cloud", - }), - [WS_METHODS.cloudInstallRelayClient]: (_input) => - observeRpcStream( - WS_METHODS.cloudInstallRelayClient, - Stream.callback((queue) => - relayClient - .installWithProgress((event) => Queue.offer(queue, event).pipe(Effect.asVoid)) - .pipe( - Effect.flatMap((status) => - Queue.offer(queue, { - type: "complete", - status, + [WS_METHODS.sourceControlLookupRepository]: (input) => + observeRpcEffect( + WS_METHODS.sourceControlLookupRepository, + sourceControlRepositories.lookupRepository(input), + { + "rpc.aggregate": "source-control", + }, + ), + [WS_METHODS.sourceControlCloneRepository]: (input) => + observeRpcEffect( + WS_METHODS.sourceControlCloneRepository, + sourceControlRepositories.cloneRepository(input), + { + "rpc.aggregate": "source-control", + }, + ), + [WS_METHODS.sourceControlPublishRepository]: (input) => + observeRpcEffect( + WS_METHODS.sourceControlPublishRepository, + sourceControlRepositories + .publishRepository(input) + .pipe(Effect.tap(() => refreshGitStatus(input.cwd))), + { + "rpc.aggregate": "source-control", + }, + ), + [WS_METHODS.projectsSearchEntries]: (input) => + observeRpcEffect( + WS_METHODS.projectsSearchEntries, + workspaceEntries.search(input).pipe( + Effect.mapError( + (cause) => + new ProjectSearchEntriesError({ + message: `Failed to search workspace entries: ${cause.detail}`, + cause, }), - ), - Effect.catchTag("RelayClientInstallError", (error) => - Queue.fail( - queue, - new RelayClientInstallFailedError({ - reason: error.reason, - message: error.message, - }), - ), - ), - Effect.andThen(Queue.end(queue)), - Effect.forkScoped, ), - ), - { "rpc.aggregate": "cloud" }, - ), - [WS_METHODS.sourceControlLookupRepository]: (input) => - observeRpcEffect( - WS_METHODS.sourceControlLookupRepository, - sourceControlRepositories.lookupRepository(input), - { - "rpc.aggregate": "source-control", - }, - ), - [WS_METHODS.sourceControlCloneRepository]: (input) => - observeRpcEffect( - WS_METHODS.sourceControlCloneRepository, - sourceControlRepositories.cloneRepository(input), - { - "rpc.aggregate": "source-control", - }, - ), - [WS_METHODS.sourceControlPublishRepository]: (input) => - observeRpcEffect( - WS_METHODS.sourceControlPublishRepository, - sourceControlRepositories - .publishRepository(input) - .pipe(Effect.tap(() => refreshGitStatus(input.cwd))), - { - "rpc.aggregate": "source-control", - }, - ), - [WS_METHODS.projectsSearchEntries]: (input) => - observeRpcEffect( - WS_METHODS.projectsSearchEntries, - workspaceEntries.search(input).pipe( - Effect.mapError( - (cause) => - new ProjectSearchEntriesError({ - message: `Failed to search workspace entries: ${cause.detail}`, - cause, - }), ), + { "rpc.aggregate": "workspace" }, ), - { "rpc.aggregate": "workspace" }, - ), - [WS_METHODS.projectsWriteFile]: (input) => - observeRpcEffect( - WS_METHODS.projectsWriteFile, - workspaceFileSystem.writeFile(input).pipe( - Effect.mapError((cause) => { - const message = isWorkspacePathOutsideRootError(cause) - ? "Workspace file path must stay within the project root." - : "Failed to write workspace file"; - return new ProjectWriteFileError({ - message, - cause, - }); - }), - ), - { "rpc.aggregate": "workspace" }, - ), - [WS_METHODS.shellOpenInEditor]: (input) => - observeRpcEffect(WS_METHODS.shellOpenInEditor, externalLauncher.launchEditor(input), { - "rpc.aggregate": "workspace", - }), - [WS_METHODS.filesystemBrowse]: (input) => - observeRpcEffect( - WS_METHODS.filesystemBrowse, - workspaceEntries.browse(input).pipe( - Effect.mapError( - (cause) => - new FilesystemBrowseError({ - message: cause.detail, + [WS_METHODS.projectsWriteFile]: (input) => + observeRpcEffect( + WS_METHODS.projectsWriteFile, + workspaceFileSystem.writeFile(input).pipe( + Effect.mapError((cause) => { + const message = isWorkspacePathOutsideRootError(cause) + ? "Workspace file path must stay within the project root." + : "Failed to write workspace file"; + return new ProjectWriteFileError({ + message, cause, - }), + }); + }), ), + { "rpc.aggregate": "workspace" }, ), - { "rpc.aggregate": "workspace" }, - ), - [WS_METHODS.mcpListServers]: (input) => - observeRpcEffect( - WS_METHODS.mcpListServers, - loadClaudeAdapter().pipe( - Effect.flatMap((adapter) => adapter.listMcpServersOnThread(input.threadId)), - Effect.map((servers) => ({ servers })), - Effect.mapError((cause) => - toMcpToggleError(cause, "Failed to list MCP servers for this thread."), + [WS_METHODS.shellOpenInEditor]: (input) => + observeRpcEffect(WS_METHODS.shellOpenInEditor, externalLauncher.launchEditor(input), { + "rpc.aggregate": "workspace", + }), + [WS_METHODS.filesystemBrowse]: (input) => + observeRpcEffect( + WS_METHODS.filesystemBrowse, + workspaceEntries.browse(input).pipe( + Effect.mapError( + (cause) => + new FilesystemBrowseError({ + message: cause.detail, + cause, + }), + ), ), + { "rpc.aggregate": "workspace" }, ), - { "rpc.aggregate": "mcp" }, - ), - [WS_METHODS.mcpToggleServer]: (input) => - observeRpcEffect( - WS_METHODS.mcpToggleServer, - loadClaudeAdapter().pipe( - Effect.flatMap((adapter) => - adapter.toggleMcpServerOnThread(input.threadId, input.mcpServerName, input.enabled), + [WS_METHODS.mcpListServers]: (input) => + observeRpcEffect( + WS_METHODS.mcpListServers, + loadClaudeAdapter().pipe( + Effect.flatMap((adapter) => adapter.listMcpServersOnThread(input.threadId)), + Effect.map((servers) => ({ servers })), + Effect.mapError((cause) => + toMcpToggleError(cause, "Failed to list MCP servers for this thread."), + ), ), - Effect.as({}), - Effect.mapError((cause) => - toMcpToggleError(cause, `Failed to toggle MCP server '${input.mcpServerName}'.`), + { "rpc.aggregate": "mcp" }, + ), + [WS_METHODS.mcpToggleServer]: (input) => + observeRpcEffect( + WS_METHODS.mcpToggleServer, + loadClaudeAdapter().pipe( + Effect.flatMap((adapter) => + adapter.toggleMcpServerOnThread(input.threadId, input.mcpServerName, input.enabled), + ), + Effect.as({}), + Effect.mapError((cause) => + toMcpToggleError(cause, `Failed to toggle MCP server '${input.mcpServerName}'.`), + ), ), + { "rpc.aggregate": "mcp" }, ), - { "rpc.aggregate": "mcp" }, - ), - [WS_METHODS.subscribeVcsStatus]: (input) => - observeRpcStream( - WS_METHODS.subscribeVcsStatus, - vcsStatusBroadcaster.streamStatus(input, { - automaticRemoteRefreshInterval: automaticGitFetchInterval, - }), - { - "rpc.aggregate": "vcs", - }, - ), - [WS_METHODS.vcsRefreshStatus]: (input) => - observeRpcEffect( - WS_METHODS.vcsRefreshStatus, - vcsStatusBroadcaster.refreshStatus(input.cwd), - { - "rpc.aggregate": "vcs", - }, - ), - [WS_METHODS.vcsPull]: (input) => - observeRpcEffect( - WS_METHODS.vcsPull, - gitWorkflow.pullCurrentBranch(input.cwd).pipe( - Effect.matchCauseEffect({ - onFailure: (cause) => Effect.failCause(cause), - onSuccess: (result) => - refreshGitStatus(input.cwd).pipe(Effect.ignore({ log: true }), Effect.as(result)), + [WS_METHODS.subscribeVcsStatus]: (input) => + observeRpcStream( + WS_METHODS.subscribeVcsStatus, + vcsStatusBroadcaster.streamStatus(input, { + automaticRemoteRefreshInterval: automaticGitFetchInterval, }), + { + "rpc.aggregate": "vcs", + }, ), - { "rpc.aggregate": "git" }, - ), - [WS_METHODS.gitRunStackedAction]: (input) => - observeRpcStream( - WS_METHODS.gitRunStackedAction, - Stream.callback((queue) => - gitWorkflow - .runStackedAction(input, { - actionId: input.actionId, - progressReporter: { - publish: (event) => Queue.offer(queue, event).pipe(Effect.asVoid), - }, - }) - .pipe( - Effect.matchCauseEffect({ - onFailure: (cause) => Queue.failCause(queue, cause), - onSuccess: () => - refreshGitStatus(input.cwd).pipe( - Effect.andThen(Queue.end(queue).pipe(Effect.asVoid)), - ), - }), - ), + [WS_METHODS.vcsRefreshStatus]: (input) => + observeRpcEffect( + WS_METHODS.vcsRefreshStatus, + vcsStatusBroadcaster.refreshStatus(input.cwd), + { + "rpc.aggregate": "vcs", + }, ), - { "rpc.aggregate": "vcs" }, - ), - [WS_METHODS.gitResolvePullRequest]: (input) => - observeRpcEffect(WS_METHODS.gitResolvePullRequest, gitWorkflow.resolvePullRequest(input), { - "rpc.aggregate": "git", - }), - [WS_METHODS.gitPreparePullRequestThread]: (input) => - observeRpcEffect( - WS_METHODS.gitPreparePullRequestThread, - gitWorkflow - .preparePullRequestThread(input) - .pipe(Effect.tap(() => refreshGitStatus(input.cwd))), - { "rpc.aggregate": "git" }, - ), - [WS_METHODS.vcsListRefs]: (input) => - observeRpcEffect(WS_METHODS.vcsListRefs, gitWorkflow.listRefs(input), { - "rpc.aggregate": "vcs", - }), - [WS_METHODS.vcsCreateWorktree]: (input) => - observeRpcEffect( - WS_METHODS.vcsCreateWorktree, - gitWorkflow.createWorktree(input).pipe(Effect.tap(() => refreshGitStatus(input.cwd))), - { "rpc.aggregate": "vcs" }, - ), - [WS_METHODS.vcsRemoveWorktree]: (input) => - observeRpcEffect( - WS_METHODS.vcsRemoveWorktree, - gitWorkflow.removeWorktree(input).pipe(Effect.tap(() => refreshGitStatus(input.cwd))), - { "rpc.aggregate": "vcs" }, - ), - [WS_METHODS.vcsCreateRef]: (input) => - observeRpcEffect( - WS_METHODS.vcsCreateRef, - gitWorkflow.createRef(input).pipe(Effect.tap(() => refreshGitStatus(input.cwd))), - { "rpc.aggregate": "vcs" }, - ), - [WS_METHODS.vcsSwitchRef]: (input) => - observeRpcEffect( - WS_METHODS.vcsSwitchRef, - gitWorkflow.switchRef(input).pipe(Effect.tap(() => refreshGitStatus(input.cwd))), - { "rpc.aggregate": "vcs" }, - ), - [WS_METHODS.vcsInit]: (input) => - observeRpcEffect( - WS_METHODS.vcsInit, - vcsProvisioning.initRepository(input).pipe(Effect.tap(() => refreshGitStatus(input.cwd))), - { "rpc.aggregate": "vcs" }, - ), - [WS_METHODS.reviewGetDiffPreview]: (input) => - observeRpcEffect(WS_METHODS.reviewGetDiffPreview, review.getDiffPreview(input), { - "rpc.aggregate": "review", - }), - [WS_METHODS.changeRequestGetReviewDraft]: (input) => - observeRpcEffect( - WS_METHODS.changeRequestGetReviewDraft, - Effect.gen(function* () { - const thread = yield* projectionSnapshotQuery - .getThreadShellById(input.threadId) - .pipe(Effect.orDie); - const cwd = Option.match(thread, { - onNone: () => undefined, - onSome: (t) => t.worktreePath ?? undefined, - }); - return yield* review.getReviewDraft({ ...input, cwd }); - }), - { "rpc.aggregate": "review" }, - ), - [WS_METHODS.changeRequestUpsertReviewComment]: (input) => - observeRpcEffect( - WS_METHODS.changeRequestUpsertReviewComment, - review.upsertReviewComment(input), - { "rpc.aggregate": "review" }, - ), - [WS_METHODS.changeRequestDeleteReviewComment]: (input) => - observeRpcEffect( - WS_METHODS.changeRequestDeleteReviewComment, - review.deleteReviewComment(input), - { "rpc.aggregate": "review" }, - ), - [WS_METHODS.changeRequestGetPrDiff]: (input) => - observeRpcEffect( - WS_METHODS.changeRequestGetPrDiff, - Effect.gen(function* () { - const thread = yield* projectionSnapshotQuery - .getThreadShellById(input.threadId) - .pipe(Effect.orDie); - if (Option.isNone(thread)) { - return yield* new ChangeRequestGetPrDiffError({ - kind: "not-a-repo", - detail: `Thread ${input.threadId} not found.`, - }); - } - let cwd: string | null = thread.value.worktreePath; - if (!cwd) { - const project = yield* projectionSnapshotQuery - .getProjectShellById(thread.value.projectId) - .pipe(Effect.orDie); - if (Option.isSome(project)) { - cwd = project.value.workspaceRoot; - } - } - if (!cwd) { - return yield* new ChangeRequestGetPrDiffError({ - kind: "not-a-repo", - detail: `Thread ${input.threadId} has no worktree path.`, - }); - } - const headRef = `refs/t3/pr/${input.prNumber}/head`; - yield* git - .execute({ - operation: "changeRequest.getPrDiff.fetch", - cwd, - args: ["fetch", "origin", `+refs/pull/${input.prNumber}/head:${headRef}`], - }) - .pipe( - Effect.mapError( - (cause) => - new ChangeRequestGetPrDiffError({ - kind: "pr-not-found", - detail: `Failed to fetch PR #${input.prNumber}: ${cause.message}`, - cause, - }), - ), - ); - const [resolveResult, diff] = yield* Effect.all([ - git - .execute({ - operation: "changeRequest.getPrDiff.resolveSha", - cwd, - args: ["rev-parse", headRef], + [WS_METHODS.vcsPull]: (input) => + observeRpcEffect( + WS_METHODS.vcsPull, + gitWorkflow.pullCurrentBranch(input.cwd).pipe( + Effect.matchCauseEffect({ + onFailure: (cause) => Effect.failCause(cause), + onSuccess: (result) => + refreshGitStatus(input.cwd).pipe(Effect.ignore({ log: true }), Effect.as(result)), + }), + ), + { "rpc.aggregate": "git" }, + ), + [WS_METHODS.gitRunStackedAction]: (input) => + observeRpcStream( + WS_METHODS.gitRunStackedAction, + Stream.callback((queue) => + gitWorkflow + .runStackedAction(input, { + actionId: input.actionId, + progressReporter: { + publish: (event) => Queue.offer(queue, event).pipe(Effect.asVoid), + }, }) .pipe( - Effect.mapError( - (cause) => - new ChangeRequestGetPrDiffError({ - kind: "pr-not-found", - detail: `Failed to resolve PR head SHA: ${cause.message}`, - cause, - }), - ), - ), - git.getPrDiff(cwd, "origin/HEAD", headRef).pipe( - Effect.mapError( - (cause) => - new ChangeRequestGetPrDiffError({ - kind: "diff-failed", - detail: `Failed to compute PR diff: ${cause.message}`, - cause, - }), + Effect.matchCauseEffect({ + onFailure: (cause) => Queue.failCause(queue, cause), + onSuccess: () => + refreshGitStatus(input.cwd).pipe( + Effect.andThen(Queue.end(queue).pipe(Effect.asVoid)), + ), + }), ), + ), + { "rpc.aggregate": "vcs" }, + ), + [WS_METHODS.gitResolvePullRequest]: (input) => + observeRpcEffect( + WS_METHODS.gitResolvePullRequest, + gitWorkflow.resolvePullRequest(input), + { + "rpc.aggregate": "git", + }, + ), + [WS_METHODS.gitPreparePullRequestThread]: (input) => + observeRpcEffect( + WS_METHODS.gitPreparePullRequestThread, + gitWorkflow + .preparePullRequestThread(input) + .pipe(Effect.tap(() => refreshGitStatus(input.cwd))), + { "rpc.aggregate": "git" }, + ), + [WS_METHODS.vcsListRefs]: (input) => + observeRpcEffect(WS_METHODS.vcsListRefs, gitWorkflow.listRefs(input), { + "rpc.aggregate": "vcs", + }), + [WS_METHODS.vcsCreateWorktree]: (input) => + observeRpcEffect( + WS_METHODS.vcsCreateWorktree, + gitWorkflow.createWorktree(input).pipe(Effect.tap(() => refreshGitStatus(input.cwd))), + { "rpc.aggregate": "vcs" }, + ), + [WS_METHODS.vcsRemoveWorktree]: (input) => + observeRpcEffect( + WS_METHODS.vcsRemoveWorktree, + gitWorkflow.removeWorktree(input).pipe(Effect.tap(() => refreshGitStatus(input.cwd))), + { "rpc.aggregate": "vcs" }, + ), + [WS_METHODS.vcsCreateRef]: (input) => + observeRpcEffect( + WS_METHODS.vcsCreateRef, + gitWorkflow.createRef(input).pipe(Effect.tap(() => refreshGitStatus(input.cwd))), + { "rpc.aggregate": "vcs" }, + ), + [WS_METHODS.vcsSwitchRef]: (input) => + observeRpcEffect( + WS_METHODS.vcsSwitchRef, + gitWorkflow.switchRef(input).pipe(Effect.tap(() => refreshGitStatus(input.cwd))), + { "rpc.aggregate": "vcs" }, + ), + [WS_METHODS.vcsInit]: (input) => + observeRpcEffect( + WS_METHODS.vcsInit, + vcsProvisioning + .initRepository(input) + .pipe(Effect.tap(() => refreshGitStatus(input.cwd))), + { "rpc.aggregate": "vcs" }, + ), + [WS_METHODS.reviewGetDiffPreview]: (input) => + observeRpcEffect(WS_METHODS.reviewGetDiffPreview, review.getDiffPreview(input), { + "rpc.aggregate": "review", + }), + [WS_METHODS.terminalOpen]: (input) => + observeRpcEffect(WS_METHODS.terminalOpen, terminalManager.open(input), { + "rpc.aggregate": "terminal", + }), + [WS_METHODS.terminalAttach]: (input) => + observeRpcStream( + WS_METHODS.terminalAttach, + Stream.callback((queue) => + Effect.acquireRelease( + terminalManager.attachStream(input, (event) => Queue.offer(queue, event)), + (unsubscribe) => Effect.sync(unsubscribe), ), - ]); - return { diff, prHeadSHA: resolveResult.stdout.trim() }; + ), + { "rpc.aggregate": "terminal" }, + ), + [WS_METHODS.terminalWrite]: (input) => + observeRpcEffect(WS_METHODS.terminalWrite, terminalManager.write(input), { + "rpc.aggregate": "terminal", }), - { "rpc.aggregate": "change-request" }, - ), - [WS_METHODS.changeRequestSubmitReview]: (input) => - observeRpcEffect( - WS_METHODS.changeRequestSubmitReview, - Effect.gen(function* () { - const thread = yield* projectionSnapshotQuery - .getThreadShellById(input.threadId) - .pipe(Effect.orDie); - if (Option.isNone(thread)) { - return yield* new ChangeRequestSubmitReviewError({ - kind: "not-a-repo", - detail: `Thread ${input.threadId} not found.`, - }); - } - let cwd: string | null = thread.value.worktreePath; - if (!cwd) { - const project = yield* projectionSnapshotQuery - .getProjectShellById(thread.value.projectId) - .pipe(Effect.orDie); - if (Option.isSome(project)) { - cwd = project.value.workspaceRoot; - } - } - if (!cwd) { - return yield* new ChangeRequestSubmitReviewError({ - kind: "not-a-repo", - detail: `Thread ${input.threadId} has no worktree path.`, - }); - } - return yield* review.submitReview({ ...input, cwd }); + [WS_METHODS.terminalResize]: (input) => + observeRpcEffect(WS_METHODS.terminalResize, terminalManager.resize(input), { + "rpc.aggregate": "terminal", }), - { "rpc.aggregate": "change-request" }, - ), - [WS_METHODS.changeRequestRunBackgroundAgent]: (input) => - observeRpcStreamEffect( - WS_METHODS.changeRequestRunBackgroundAgent, - Effect.gen(function* () { - const thread = yield* projectionSnapshotQuery - .getThreadShellById(input.threadId) - .pipe(Effect.orDie); - if (Option.isNone(thread)) { - return yield* Effect.fail( - new ChangeRequestRunBackgroundAgentError({ - kind: "thread-not-found", - detail: `Thread ${input.threadId} not found.`, - }), + [WS_METHODS.terminalClear]: (input) => + observeRpcEffect(WS_METHODS.terminalClear, terminalManager.clear(input), { + "rpc.aggregate": "terminal", + }), + [WS_METHODS.terminalRestart]: (input) => + observeRpcEffect(WS_METHODS.terminalRestart, terminalManager.restart(input), { + "rpc.aggregate": "terminal", + }), + [WS_METHODS.terminalClose]: (input) => + observeRpcEffect(WS_METHODS.terminalClose, terminalManager.close(input), { + "rpc.aggregate": "terminal", + }), + [WS_METHODS.subscribeTerminalEvents]: (_input) => + observeRpcStream( + WS_METHODS.subscribeTerminalEvents, + Stream.callback((queue) => + Effect.acquireRelease( + terminalManager.subscribe((event) => Queue.offer(queue, event)), + (unsubscribe) => Effect.sync(unsubscribe), + ), + ), + { "rpc.aggregate": "terminal" }, + ), + [WS_METHODS.subscribeTerminalMetadata]: (_input) => + observeRpcStream( + WS_METHODS.subscribeTerminalMetadata, + Stream.callback((queue) => + Effect.acquireRelease( + terminalManager.subscribeMetadata((event) => Queue.offer(queue, event)), + (unsubscribe) => Effect.sync(unsubscribe), + ), + ), + { "rpc.aggregate": "terminal" }, + ), + [WS_METHODS.subscribeServerConfig]: (_input) => + observeRpcStreamEffect( + WS_METHODS.subscribeServerConfig, + Effect.gen(function* () { + const keybindingsUpdates = keybindings.streamChanges.pipe( + Stream.map((event) => ({ + version: 1 as const, + type: "keybindingsUpdated" as const, + payload: { + keybindings: event.keybindings, + issues: event.issues, + }, + })), ); - } - let cwd: string | null = thread.value.worktreePath; - if (!cwd) { - const project = yield* projectionSnapshotQuery - .getProjectShellById(thread.value.projectId) - .pipe(Effect.orDie); - if (Option.isSome(project)) { - cwd = project.value.workspaceRoot; - } - } - if (!cwd) { - return yield* Effect.fail( - new ChangeRequestRunBackgroundAgentError({ - kind: "no-worktree", - detail: `Thread ${input.threadId} has no worktree path.`, - }), + const providerStatuses = providerRegistry.streamChanges.pipe( + Stream.map((providers) => ({ + version: 1 as const, + type: "providerStatuses" as const, + payload: { providers }, + })), + Stream.debounce(Duration.millis(PROVIDER_STATUS_DEBOUNCE_MS)), ); - } - - // Fetch the PR head ref so getPrDiff can use it - yield* git - .execute({ - operation: "changeRequest.runBackgroundAgent.fetchHead", - cwd, - args: [ - "fetch", - "origin", - `+refs/pull/${input.prNumber}/head:refs/t3/pr/${input.prNumber}/head`, - ], - }) - .pipe( - Effect.mapError( - (cause) => - new ChangeRequestRunBackgroundAgentError({ - kind: "agent-failed", - detail: `Failed to fetch PR head: ${cause.message}`, - cause, - }), - ), + const settingsUpdates = serverSettings.streamChanges.pipe( + Stream.map((settings) => redactServerSettingsForClient(settings)), + Stream.map((settings) => ({ + version: 1 as const, + type: "settingsUpdated" as const, + payload: { settings }, + })), ); - // Get the comment body - const draft = yield* review.getReviewDraft({ - threadId: input.threadId, - prNumber: input.prNumber, - cwd, - }); + yield* providerRegistry + .refresh() + .pipe(Effect.ignoreCause({ log: true }), Effect.forkScoped); - const comment = draft?.comments.find((c) => c.id === input.commentId); - if (!comment) { - return yield* Effect.fail( - new ChangeRequestRunBackgroundAgentError({ - kind: "agent-failed", - detail: `Comment ${input.commentId} not found.`, - }), + const liveUpdates = Stream.merge( + keybindingsUpdates, + Stream.merge(providerStatuses, settingsUpdates), ); - } - const prHeadRef = `refs/t3/pr/${input.prNumber}/head`; - - return backgroundAgent.runBackgroundAgent({ - threadId: input.threadId, - prNumber: input.prNumber, - commentId: input.commentId, - cwd, - prHeadRef, - commentFile: comment.file, - commentLine: comment.line, - commentBody: comment.body, - }); - }), - { "rpc.aggregate": "change-request" }, - ), - [WS_METHODS.changeRequestRunBatchAgents]: (input) => - observeRpcStreamEffect( - WS_METHODS.changeRequestRunBatchAgents, - Effect.gen(function* () { - const thread = yield* projectionSnapshotQuery - .getThreadShellById(input.threadId) - .pipe(Effect.orDie); - if (Option.isNone(thread)) { - return yield* Effect.fail( - new ChangeRequestRunBackgroundAgentError({ - kind: "thread-not-found", - detail: `Thread ${input.threadId} not found.`, + return Stream.concat( + Stream.make({ + version: 1 as const, + type: "snapshot" as const, + config: yield* loadServerConfig, }), + liveUpdates, ); - } - let cwd: string | null = thread.value.worktreePath; - if (!cwd) { - const project = yield* projectionSnapshotQuery - .getProjectShellById(thread.value.projectId) - .pipe(Effect.orDie); - if (Option.isSome(project)) { - cwd = project.value.workspaceRoot; - } - } - if (!cwd) { - return yield* Effect.fail( - new ChangeRequestRunBackgroundAgentError({ - kind: "no-worktree", - detail: `Thread ${input.threadId} has no worktree path.`, - }), + }), + { "rpc.aggregate": "server" }, + ), + [WS_METHODS.subscribeServerLifecycle]: (_input) => + observeRpcStreamEffect( + WS_METHODS.subscribeServerLifecycle, + Effect.gen(function* () { + const snapshot = yield* lifecycleEvents.snapshot; + const snapshotEvents = Array.from(snapshot.events).toSorted( + (left, right) => left.sequence - right.sequence, ); - } - - if (input.commentIds.length === 0) { - return Stream.empty; - } - - yield* git - .execute({ - operation: "changeRequest.runBatchAgents.fetchHead", - cwd, - args: [ - "fetch", - "origin", - `+refs/pull/${input.prNumber}/head:refs/t3/pr/${input.prNumber}/head`, - ], - }) - .pipe( - Effect.mapError( - (cause) => - new ChangeRequestRunBackgroundAgentError({ - kind: "agent-failed", - detail: `Failed to fetch PR head: ${cause.message}`, - cause, - }), - ), + const liveEvents = lifecycleEvents.stream.pipe( + Stream.filter((event) => event.sequence > snapshot.sequence), ); - - const draft = yield* review.getReviewDraft({ - threadId: input.threadId, - prNumber: input.prNumber, - cwd, - }); - - const prHeadRef = `refs/t3/pr/${input.prNumber}/head`; - - const agentInputs = input.commentIds - .map((commentId) => { - const comment = draft?.comments.find((c) => c.id === commentId); - if (!comment) return null; - return { - threadId: input.threadId, - prNumber: input.prNumber, - commentId, - cwd, - prHeadRef, - commentFile: comment.file, - commentLine: comment.line, - commentBody: comment.body, - }; - }) - .filter((x): x is NonNullable => x !== null); - - if (agentInputs.length === 0) { - return Stream.empty; - } - - return backgroundAgent.runBatchAgents(agentInputs); - }), - { "rpc.aggregate": "change-request" }, - ), - [WS_METHODS.terminalOpen]: (input) => - observeRpcEffect(WS_METHODS.terminalOpen, terminalManager.open(input), { - "rpc.aggregate": "terminal", - }), - [WS_METHODS.terminalAttach]: (input) => - observeRpcStream( - WS_METHODS.terminalAttach, - Stream.callback((queue) => - Effect.acquireRelease( - terminalManager.attachStream(input, (event) => Queue.offer(queue, event)), - (unsubscribe) => Effect.sync(unsubscribe), - ), - ), - { "rpc.aggregate": "terminal" }, - ), - [WS_METHODS.terminalWrite]: (input) => - observeRpcEffect(WS_METHODS.terminalWrite, terminalManager.write(input), { - "rpc.aggregate": "terminal", - }), - [WS_METHODS.terminalResize]: (input) => - observeRpcEffect(WS_METHODS.terminalResize, terminalManager.resize(input), { - "rpc.aggregate": "terminal", - }), - [WS_METHODS.terminalClear]: (input) => - observeRpcEffect(WS_METHODS.terminalClear, terminalManager.clear(input), { - "rpc.aggregate": "terminal", - }), - [WS_METHODS.terminalRestart]: (input) => - observeRpcEffect(WS_METHODS.terminalRestart, terminalManager.restart(input), { - "rpc.aggregate": "terminal", - }), - [WS_METHODS.terminalClose]: (input) => - observeRpcEffect(WS_METHODS.terminalClose, terminalManager.close(input), { - "rpc.aggregate": "terminal", - }), - [WS_METHODS.subscribeTerminalEvents]: (_input) => - observeRpcStream( - WS_METHODS.subscribeTerminalEvents, - Stream.callback((queue) => - Effect.acquireRelease( - terminalManager.subscribe((event) => Queue.offer(queue, event)), - (unsubscribe) => Effect.sync(unsubscribe), - ), - ), - { "rpc.aggregate": "terminal" }, - ), - [WS_METHODS.subscribeTerminalMetadata]: (_input) => - observeRpcStream( - WS_METHODS.subscribeTerminalMetadata, - Stream.callback((queue) => - Effect.acquireRelease( - terminalManager.subscribeMetadata((event) => Queue.offer(queue, event)), - (unsubscribe) => Effect.sync(unsubscribe), - ), + return Stream.concat(Stream.fromIterable(snapshotEvents), liveEvents); + }), + { "rpc.aggregate": "server" }, ), - { "rpc.aggregate": "terminal" }, - ), - [WS_METHODS.subscribeServerConfig]: (_input) => - observeRpcStreamEffect( - WS_METHODS.subscribeServerConfig, - Effect.gen(function* () { - const keybindingsUpdates = keybindings.streamChanges.pipe( - Stream.map((event) => ({ - version: 1 as const, - type: "keybindingsUpdated" as const, - payload: { - keybindings: event.keybindings, - issues: event.issues, - }, - })), - ); - const providerStatuses = providerRegistry.streamChanges.pipe( - Stream.map((providers) => ({ - version: 1 as const, - type: "providerStatuses" as const, - payload: { providers }, - })), - Stream.debounce(Duration.millis(PROVIDER_STATUS_DEBOUNCE_MS)), - ); - const settingsUpdates = serverSettings.streamChanges.pipe( - Stream.map((settings) => redactServerSettingsForClient(settings)), - Stream.map((settings) => ({ - version: 1 as const, - type: "settingsUpdated" as const, - payload: { settings }, - })), - ); - - yield* providerRegistry - .refresh() - .pipe(Effect.ignoreCause({ log: true }), Effect.forkScoped); - - const liveUpdates = Stream.merge( - keybindingsUpdates, - Stream.merge(providerStatuses, settingsUpdates), - ); + [WS_METHODS.subscribeAuthAccess]: (_input) => + observeRpcStreamEffect( + WS_METHODS.subscribeAuthAccess, + Effect.gen(function* () { + const initialSnapshot = yield* loadAuthAccessSnapshot(); + const revisionRef = yield* Ref.make(1); + const accessChanges: Stream.Stream< + PairingGrantStore.BootstrapCredentialChange | SessionStore.SessionCredentialChange + > = Stream.merge(bootstrapCredentials.streamChanges, sessions.streamChanges); - return Stream.concat( - Stream.make({ - version: 1 as const, - type: "snapshot" as const, - config: yield* loadServerConfig, - }), - liveUpdates, - ); - }), - { "rpc.aggregate": "server" }, - ), - [WS_METHODS.subscribeServerLifecycle]: (_input) => - observeRpcStreamEffect( - WS_METHODS.subscribeServerLifecycle, - Effect.gen(function* () { - const snapshot = yield* lifecycleEvents.snapshot; - const snapshotEvents = Array.from(snapshot.events).toSorted( - (left, right) => left.sequence - right.sequence, - ); - const liveEvents = lifecycleEvents.stream.pipe( - Stream.filter((event) => event.sequence > snapshot.sequence), - ); - return Stream.concat(Stream.fromIterable(snapshotEvents), liveEvents); - }), - { "rpc.aggregate": "server" }, - ), - [WS_METHODS.subscribeAuthAccess]: (_input) => - observeRpcStreamEffect( - WS_METHODS.subscribeAuthAccess, - Effect.gen(function* () { - const initialSnapshot = yield* loadAuthAccessSnapshot(); - const revisionRef = yield* Ref.make(1); - const accessChanges: Stream.Stream< - PairingGrantStore.BootstrapCredentialChange | SessionStore.SessionCredentialChange - > = Stream.merge(bootstrapCredentials.streamChanges, sessions.streamChanges); - - const liveEvents: Stream.Stream = accessChanges.pipe( - Stream.mapEffect((change) => - Ref.updateAndGet(revisionRef, (revision) => revision + 1).pipe( - Effect.map((revision) => - toAuthAccessStreamEvent(change, revision, currentSessionId), + const liveEvents: Stream.Stream = accessChanges.pipe( + Stream.mapEffect((change) => + Ref.updateAndGet(revisionRef, (revision) => revision + 1).pipe( + Effect.map((revision) => + toAuthAccessStreamEvent(change, revision, currentSessionId), + ), ), ), - ), - ); - - return Stream.concat( - Stream.make({ - version: 1 as const, - revision: 1, - type: "snapshot" as const, - payload: initialSnapshot, - }), - liveEvents, - ); - }), - { "rpc.aggregate": "auth" }, - ), - }); - }); + ); -const makeWsRpcHandlersLayer = (currentSession: AuthenticatedSession) => - WsRpcGroup.toLayer(makeWsRpcHandlers(currentSession)); + return Stream.concat( + Stream.make({ + version: 1 as const, + revision: 1, + type: "snapshot" as const, + payload: initialSnapshot, + }), + liveEvents, + ); + }), + { "rpc.aggregate": "auth" }, + ), + }); + }), + ); export const websocketRpcRouteLayer = Layer.unwrap( - Effect.sync(() => { - // Fail fast at boot instead of throwing per-request (a request-time throw - // becomes a protocol-level defect that kills the whole WebSocket). - const missingScopes = missingRpcScopeDeclarations(); - if (missingScopes.length > 0) { - throw new Error( - `WS RPC methods missing authorization scope declarations: ${missingScopes.join(", ")}. ` + - "Add entries to RPC_REQUIRED_SCOPE in apps/server/src/ws.ts.", - ); - } - return HttpRouter.add( + Effect.succeed( + HttpRouter.add( "GET", "/ws", Effect.gen(function* () { const request = yield* HttpServerRequest.HttpServerRequest; const serverAuth = yield* EnvironmentAuth.EnvironmentAuth; const sessions = yield* SessionStore.SessionStore; - yield* Effect.logDebug("ws.upgrade received", { - path: request.originalUrl, - hasSessionCookie: typeof request.cookies[sessions.cookieName] === "string", - hasAuthorizationHeader: request.headers.authorization !== undefined, - hasWebSocketTicket: request.originalUrl.includes("wsTicket="), - }); const session = yield* serverAuth.authenticateWebSocketUpgrade(request).pipe( Effect.catchTags({ ServerAuthInvalidCredentialError: (error) => failEnvironmentAuthInvalid(error.reason), ServerAuthInternalError: (error) => failEnvironmentInternal("internal_error", error), }), ); - yield* Effect.logDebug("ws.upgrade authenticated", { - path: request.originalUrl, - sessionId: session.sessionId, - sessionMethod: session.method, - scopeCount: session.scopes.length, - }); const rpcWebSocketHttpEffect = yield* RpcServer.toHttpEffectWebsocket(WsRpcGroup, { disableTracing: true, }).pipe( - Effect.provide(makeWsRpcHandlersLayer(session)), - Effect.provideService(RpcSerialization.RpcSerialization, RpcSerialization.json), + Effect.provide( + makeWsRpcLayer(session).pipe( + Layer.provideMerge(RpcSerialization.layerJson), + Layer.provide(ProviderMaintenanceRunner.layer), + Layer.provide( + SourceControlDiscoveryLayer.layer.pipe( + Layer.provide( + SourceControlProviderRegistry.layer.pipe( + Layer.provide( + Layer.mergeAll( + AzureDevOpsCli.layer, + BitbucketApi.layer, + GitHubCli.layer, + GitLabCli.layer, + ), + ), + Layer.provideMerge(GitVcsDriver.layer), + Layer.provide( + VcsDriverRegistry.layer.pipe(Layer.provide(VcsProjectConfig.layer)), + ), + ), + ), + Layer.provide(VcsProcess.layer), + ), + ), + ), + ), ); return yield* Effect.acquireUseRelease( sessions.markConnected(session.sessionId), @@ -2028,6 +1672,6 @@ export const websocketRpcRouteLayer = Layer.unwrap( EnvironmentInternalError: HttpServerRespondable.toResponse, }), ), - ); - }), + ), + ), ); diff --git a/apps/web/package.json b/apps/web/package.json index 64c59f0e8927..c336dd7735e2 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -1,6 +1,6 @@ { "name": "@t3tools/web", - "version": "0.0.24", + "version": "0.0.26", "private": true, "type": "module", "scripts": { diff --git a/apps/web/src/authBootstrap.test.ts b/apps/web/src/authBootstrap.test.ts index dbc9b714e2ef..6815cd70f8c4 100644 --- a/apps/web/src/authBootstrap.test.ts +++ b/apps/web/src/authBootstrap.test.ts @@ -4,7 +4,6 @@ import { type AuthBrowserSessionResult, type AuthCreatePairingCredentialInput, type AuthSessionState, - type AuthWebSocketTicketResult, type DesktopBridge, } from "@t3tools/contracts"; import * as DateTime from "effect/DateTime"; @@ -86,7 +85,6 @@ async function installAuthApi(input: { readonly browserSession?: ( credential: string, ) => Effect.Effect; - readonly webSocketTicket?: () => Effect.Effect; readonly pairingCredential?: (payload: AuthCreatePairingCredentialInput) => Effect.Effect<{ readonly id: string; readonly credential: string; @@ -99,7 +97,6 @@ async function installAuthApi(input: { ...(input.browserSession ? { browserSession: (payload) => input.browserSession!(payload.credential) } : {}), - ...(input.webSocketTicket ? { webSocketTicket: () => input.webSocketTicket!() } : {}), ...(input.pairingCredential ? { pairingCredential: (payload) => input.pairingCredential!(payload) } : {}), @@ -289,36 +286,6 @@ describe("resolveInitialServerAuthGateState", () => { expect(testApi.calls.session).toBe(2); }); - it("waits for the authenticated session to become observable after manual pairing", async () => { - vi.useFakeTimers(); - const nextSession = sequence( - unauthenticatedSession(LOOPBACK_AUTH), - unauthenticatedSession(LOOPBACK_AUTH), - authenticatedSession(LOOPBACK_AUTH), - ); - const testApi = await installAuthApi({ - session: nextSession, - browserSession: () => Effect.succeed(browserSession(["orchestration:read"])), - }); - const { resolveInitialServerAuthGateState, submitServerAuthCredential } = - await import("./environments/primary"); - - await expect(resolveInitialServerAuthGateState()).resolves.toEqual({ - status: "requires-auth", - auth: LOOPBACK_AUTH, - }); - - const submitPromise = submitServerAuthCredential("retry-token"); - await vi.advanceTimersByTimeAsync(100); - - await expect(submitPromise).resolves.toBeUndefined(); - await expect(resolveInitialServerAuthGateState()).resolves.toEqual({ - status: "authenticated", - }); - expect(testApi.calls.browserSession).toEqual([{ credential: "retry-token" }]); - expect(testApi.calls.session).toBe(3); - }); - it("surfaces a friendly error message when an invalid pairing token is submitted", async () => { const testApi = await installAuthApi({ browserSession: () => @@ -339,22 +306,6 @@ describe("resolveInitialServerAuthGateState", () => { expect(testApi.calls.browserSession).toEqual([{ credential: "bad-token" }]); }); - it("resolves the primary websocket url using an authenticated websocket ticket", async () => { - const testApi = await installAuthApi({ - webSocketTicket: () => - Effect.succeed({ - ticket: "ws-ticket", - expiresAt: SESSION_EXPIRES_AT, - }), - }); - const { resolvePrimaryWebSocketConnectionUrl } = await import("./environments/primary"); - - await expect(resolvePrimaryWebSocketConnectionUrl("ws://localhost:13773")).resolves.toBe( - "ws://localhost:13773/ws?wsTicket=ws-ticket", - ); - expect(testApi.calls.webSocketTicket).toBe(1); - }); - it("waits for the authenticated session to become observable after silent desktop bootstrap", async () => { vi.useFakeTimers(); const nextSession = sequence( diff --git a/apps/web/src/clientPersistenceStorage.ts b/apps/web/src/clientPersistenceStorage.ts index 2da74ae6c452..2838f5028810 100644 --- a/apps/web/src/clientPersistenceStorage.ts +++ b/apps/web/src/clientPersistenceStorage.ts @@ -184,7 +184,7 @@ export function writeBrowserSavedEnvironmentSecret( return record; } found = true; - const nextRecord = { + const nextRecord: BrowserSavedEnvironmentRecord = { environmentId: record.environmentId, label: record.label, httpBaseUrl: record.httpBaseUrl, diff --git a/apps/web/src/cloud/linkEnvironment.test.ts b/apps/web/src/cloud/linkEnvironment.test.ts index 9baae20a686c..dc09a7fa0432 100644 --- a/apps/web/src/cloud/linkEnvironment.test.ts +++ b/apps/web/src/cloud/linkEnvironment.test.ts @@ -514,7 +514,7 @@ describe("web cloud link environment client", () => { expect(fetchMock.mock.calls[0]?.[1]?.credentials).not.toBe("include"); expect(String(fetchMock.mock.calls[1]?.[0])).toBe( - "http://127.0.0.1:3000/api/cloud/link-proof", + "http://127.0.0.1:3000/api/connect/link-proof", ); expect(fetchMock.mock.calls[1]?.[1]).toMatchObject({ method: "POST", @@ -553,7 +553,7 @@ describe("web cloud link environment client", () => { }); expect(String(fetchMock.mock.calls[3]?.[0])).toBe( - "http://127.0.0.1:3000/api/cloud/relay-config", + "http://127.0.0.1:3000/api/connect/relay-config", ); expect(fetchMock.mock.calls[3]?.[1]).toMatchObject({ method: "POST", @@ -615,7 +615,7 @@ describe("web cloud link environment client", () => { publishAgentActivity: false, }); expect(String(fetchMock.mock.calls[0]?.[0])).toBe( - "http://127.0.0.1:3000/api/cloud/link-state", + "http://127.0.0.1:3000/api/connect/link-state", ); expect(fetchMock.mock.calls[0]?.[1]).toMatchObject({ method: "GET", @@ -654,7 +654,7 @@ describe("web cloud link environment client", () => { }), ); - expect(String(fetchMock.mock.calls[0]?.[0])).toBe("http://127.0.0.1:3000/api/cloud/unlink"); + expect(String(fetchMock.mock.calls[0]?.[0])).toBe("http://127.0.0.1:3000/api/connect/unlink"); expect(fetchMock.mock.calls[0]?.[1]).toMatchObject({ method: "POST", credentials: "include", @@ -698,7 +698,7 @@ describe("web cloud link environment client", () => { ); expect(fetchMock).toHaveBeenCalledTimes(2); - expect(String(fetchMock.mock.calls[0]?.[0])).toBe("http://127.0.0.1:3000/api/cloud/unlink"); + expect(String(fetchMock.mock.calls[0]?.[0])).toBe("http://127.0.0.1:3000/api/connect/unlink"); expect(fetchMock.mock.calls[0]?.[1]).toMatchObject({ method: "POST", credentials: "include", diff --git a/apps/web/src/cloud/linkEnvironment.ts b/apps/web/src/cloud/linkEnvironment.ts index f68849e2765a..b13b324a4113 100644 --- a/apps/web/src/cloud/linkEnvironment.ts +++ b/apps/web/src/cloud/linkEnvironment.ts @@ -451,7 +451,7 @@ export function readPrimaryCloudLinkState(): Effect.Effect< return null; } const client = yield* makeEnvironmentHttpApiClient(resolvePrimaryEnvironmentHttpUrl("/")); - return yield* client.cloud + return yield* client.connect .linkState({ headers: {} }) .pipe( withPrimaryEnvironmentRequestInit, @@ -465,7 +465,7 @@ export function updatePrimaryCloudPreferences(input: { }): Effect.Effect { return Effect.gen(function* () { const client = yield* makeEnvironmentHttpApiClient(resolvePrimaryEnvironmentHttpUrl("/")); - return yield* client.cloud + return yield* client.connect .preferences({ headers: {}, payload: input, @@ -488,7 +488,7 @@ export function unlinkPrimaryEnvironmentFromCloud(input: { }); } const client = yield* makeEnvironmentHttpApiClient(resolvePrimaryEnvironmentHttpUrl("/")); - yield* client.cloud + yield* client.connect .unlink({ headers: {} }) .pipe( withPrimaryEnvironmentRequestInit, @@ -568,7 +568,7 @@ export function linkEnvironmentToCloud(input: { ), ), ); - const proof = yield* environmentClient.cloud + const proof = yield* environmentClient.connect .linkProof({ headers, payload: { @@ -604,7 +604,7 @@ export function linkEnvironmentToCloud(input: { link, }); - yield* environmentClient.cloud + yield* environmentClient.connect .relayConfig({ headers, payload: { @@ -656,7 +656,7 @@ export function linkPrimaryEnvironmentToCloud(input: { ), ), ); - const proof = yield* environmentClient.cloud + const proof = yield* environmentClient.connect .linkProof({ headers: {}, payload: { @@ -695,7 +695,7 @@ export function linkPrimaryEnvironmentToCloud(input: { link, }); - yield* environmentClient.cloud + yield* environmentClient.connect .relayConfig({ headers: {}, payload: { diff --git a/apps/web/src/cloud/primaryCloudLinkState.ts b/apps/web/src/cloud/primaryCloudLinkState.ts index ecc2297595dd..095ca8422816 100644 --- a/apps/web/src/cloud/primaryCloudLinkState.ts +++ b/apps/web/src/cloud/primaryCloudLinkState.ts @@ -55,7 +55,7 @@ export function usePrimaryCloudLinkState() { let error: string | null = null; if (result._tag === "Failure") { const cause = Cause.squash(result.cause); - error = cause instanceof Error ? cause.message : "Could not read T3 Cloud link state."; + error = cause instanceof Error ? cause.message : "Could not read T3 Connect link state."; } return { diff --git a/apps/web/src/components/ChatView.browser.tsx b/apps/web/src/components/ChatView.browser.tsx index d037f4e48a55..8cfa843debd5 100644 --- a/apps/web/src/components/ChatView.browser.tsx +++ b/apps/web/src/components/ChatView.browser.tsx @@ -91,8 +91,8 @@ function gitStatusTargetKey(input: { return `${input.environmentId}:${input.cwd}`; } -vi.mock("../lib/gitStatusState", () => ({ - useGitStatus: (input: { environmentId: EnvironmentId | null; cwd: string | null }) => { +vi.mock("../lib/vcsStatusState", () => ({ + getVcsStatusSnapshot: (input: { environmentId: EnvironmentId | null; cwd: string | null }) => { const targetKey = gitStatusTargetKey(input); return { data: targetKey ? (mockedGitStatusesRef.current.get(targetKey) ?? null) : null, @@ -101,44 +101,20 @@ vi.mock("../lib/gitStatusState", () => ({ isPending: false, }; }, - useGitStatuses: () => new Map(), - refreshGitStatus: () => Promise.resolve(null), - resetGitStatusStateForTests: () => undefined, + useVcsStatus: (input: { environmentId: EnvironmentId | null; cwd: string | null }) => { + const targetKey = gitStatusTargetKey(input); + return { + data: targetKey ? (mockedGitStatusesRef.current.get(targetKey) ?? null) : null, + error: null, + cause: null, + isPending: false, + }; + }, + useVcsStatuses: () => new Map(), + refreshVcsStatus: () => Promise.resolve(null), + resetVcsStatusStateForTests: () => undefined, })); -vi.mock("../lib/vcsStatusState", () => { - const status = { - data: { - isRepo: true, - sourceControlProvider: { - kind: "github", - name: "GitHub", - baseUrl: "https://github.com", - }, - hasPrimaryRemote: true, - isDefaultRef: true, - refName: "main", - hasWorkingTreeChanges: false, - workingTree: { files: [], insertions: 0, deletions: 0 }, - hasUpstream: true, - aheadCount: 0, - behindCount: 0, - pr: null, - }, - error: null, - cause: null, - isPending: false, - }; - - return { - getVcsStatusSnapshot: () => status, - useVcsStatus: () => status, - useVcsStatuses: () => new Map(), - refreshVcsStatus: () => Promise.resolve(null), - resetVcsStatusStateForTests: () => undefined, - }; -}); - const THREAD_ID = "thread-browser-test" as ThreadId; const THREAD_TITLE = "Browser test thread"; const ARCHIVED_SECONDARY_THREAD_ID = "thread-secondary-project-archived" as ThreadId; @@ -284,6 +260,7 @@ function createMockEnvironmentApi(input: { sourceControl: {} as EnvironmentApi["sourceControl"], vcs: {} as EnvironmentApi["vcs"], git: {} as EnvironmentApi["git"], + review: {} as EnvironmentApi["review"], mcp: { listServers: (() => { throw new Error("Not implemented in browser test."); @@ -292,8 +269,6 @@ function createMockEnvironmentApi(input: { throw new Error("Not implemented in browser test."); }) as EnvironmentApi["mcp"]["toggleServer"], }, - review: {} as EnvironmentApi["review"], - changeRequest: {} as EnvironmentApi["changeRequest"], orchestration: { dispatchCommand: input.dispatchCommand, getTurnDiff: (() => { @@ -444,10 +419,10 @@ function createSnapshotForTargetUser(options: { archivedAt: null, deletedAt: null, messages, + contextTrimPoints: [], activities: [], proposedPlans: [], checkpoints: [], - contextTrimPoints: [], session: { threadId: THREAD_ID, status: options.sessionStatus ?? "ready", @@ -511,10 +486,10 @@ function addThreadToSnapshot( archivedAt: null, deletedAt: null, messages: [], + contextTrimPoints: [], activities: [], proposedPlans: [], checkpoints: [], - contextTrimPoints: [], session: { threadId, status: "ready", @@ -534,7 +509,6 @@ function toShellThread(thread: OrchestrationReadModel["threads"][number]) { id: thread.id, projectId: thread.projectId, title: thread.title, - ...(thread.managerMetadata ? { managerMetadata: thread.managerMetadata } : {}), modelSelection: thread.modelSelection, runtimeMode: thread.runtimeMode, interactionMode: thread.interactionMode, @@ -560,7 +534,6 @@ function toShellSnapshot(snapshot: OrchestrationReadModel) { id: project.id, title: project.title, workspaceRoot: project.workspaceRoot, - ...(project.managerMetadata ? { managerMetadata: project.managerMetadata } : {}), repositoryIdentity: project.repositoryIdentity ?? null, defaultModelSelection: project.defaultModelSelection, scripts: project.scripts, @@ -848,10 +821,10 @@ function createSnapshotWithSecondaryProject(options?: { updatedAt: isoAt(31), deletedAt: null, messages: [], + contextTrimPoints: [], activities: [], proposedPlans: [], checkpoints: [], - contextTrimPoints: [], session: { threadId: "thread-secondary-project" as ThreadId, status: "ready", @@ -881,10 +854,10 @@ function createSnapshotWithSecondaryProject(options?: { updatedAt: isoAt(25), deletedAt: null, messages: [], + contextTrimPoints: [], activities: [], proposedPlans: [], checkpoints: [], - contextTrimPoints: [], session: { threadId: ARCHIVED_SECONDARY_THREAD_ID, status: "ready", @@ -918,74 +891,6 @@ function createSnapshotWithSecondaryProject(options?: { }; } -function createSnapshotWithManagerConsole(): OrchestrationReadModel { - const snapshot = createSnapshotForTargetUser({ - targetMessageId: "msg-user-manager-console-target" as MessageId, - targetText: "manager console", - }); - - return { - ...snapshot, - projects: [ - { - id: "manager-workspace-1" as ProjectId, - title: "Manager Workspace", - workspaceRoot: "/repo/.t3/manager", - managerMetadata: { - role: "workspace", - }, - defaultModelSelection: { instanceId: ProviderInstanceId.make("codex"), model: "gpt-5" }, - scripts: [], - createdAt: isoAt(5), - updatedAt: isoAt(5), - deletedAt: null, - }, - ...snapshot.projects, - ], - threads: [ - { - id: "manager-console-1" as ThreadId, - projectId: "manager-workspace-1" as ProjectId, - title: "Manager Console", - managerMetadata: { - role: "console", - }, - modelSelection: { instanceId: ProviderInstanceId.make("codex"), model: "gpt-5" }, - interactionMode: "default", - runtimeMode: "full-access", - branch: null, - worktreePath: null, - latestTurn: null, - createdAt: isoAt(6), - updatedAt: isoAt(7), - archivedAt: null, - deletedAt: null, - messages: [ - createUserMessage({ - id: "msg-user-manager-console" as MessageId, - text: "Manager inbox work", - offsetSeconds: 6, - }), - ], - activities: [], - proposedPlans: [], - checkpoints: [], - contextTrimPoints: [], - session: { - threadId: "manager-console-1" as ThreadId, - status: "ready", - providerName: "codex", - runtimeMode: "full-access", - activeTurnId: null, - lastError: null, - updatedAt: isoAt(7), - }, - }, - ...snapshot.threads, - ], - }; -} - function createSnapshotWithPendingUserInput(): OrchestrationReadModel { const snapshot = createSnapshotForTargetUser({ targetMessageId: "msg-user-pending-input-target" as MessageId, @@ -1327,18 +1232,6 @@ async function waitForComposerEditor(): Promise { ); } -function readComposerSelectionOffset(): number { - const composerEditor = document.querySelector('[data-testid="composer-editor"]'); - const selection = window.getSelection(); - if (!composerEditor || !selection || selection.rangeCount === 0 || !selection.focusNode) { - throw new Error("Unable to resolve composer selection."); - } - const range = selection.getRangeAt(0).cloneRange(); - range.selectNodeContents(composerEditor); - range.setEnd(selection.focusNode, selection.focusOffset); - return range.toString().length; -} - async function pressComposerKey(key: string): Promise { const composerEditor = await waitForComposerEditor(); composerEditor.focus(); @@ -1633,33 +1526,6 @@ function dispatchChatNewShortcut(): void { ); } -function dispatchProjectPickerShortcut(): void { - const useMetaForMod = isMacPlatform(navigator.platform); - window.dispatchEvent( - new KeyboardEvent("keydown", { - key: "n", - altKey: true, - metaKey: useMetaForMod, - ctrlKey: !useMetaForMod, - bubbles: true, - cancelable: true, - }), - ); -} - -function dispatchFocusChatShortcut(): void { - const useMetaForMod = isMacPlatform(navigator.platform); - window.dispatchEvent( - new KeyboardEvent("keydown", { - key: "i", - metaKey: useMetaForMod, - ctrlKey: !useMetaForMod, - bubbles: true, - cancelable: true, - }), - ); -} - function dispatchRenameCurrentThreadShortcut(): void { const useMetaForMod = isMacPlatform(navigator.platform); window.dispatchEvent( @@ -2772,7 +2638,7 @@ describe("ChatView timeline estimator parity (full app)", () => { } }); - it("shows the pull request badge for a worktree-backed thread row even when stored branch metadata is stale", async () => { + it("shows the pull request badge for a worktree-backed thread row", async () => { const snapshotBase = createSnapshotForTargetUser({ targetMessageId: "msg-user-pr-badge-target" as MessageId, targetText: "show pr badge", @@ -2780,14 +2646,15 @@ describe("ChatView timeline estimator parity (full app)", () => { const worktreePath = "/repo/worktrees/pr-1359"; const snapshot = { ...snapshotBase, - threads: snapshotBase.threads.map((thread) => { - if (thread.id !== THREAD_ID) return thread; - const copy = Object.assign({}, thread, { - branch: "feature/archive-settings-overhaul", - worktreePath, - }); - return copy; - }), + threads: snapshotBase.threads.map((thread) => + thread.id === THREAD_ID + ? { + ...thread, + branch: "archive-settings-overhaul", + worktreePath, + } + : thread, + ), }; mockedGitStatusesRef.current.set(`${LOCAL_ENVIRONMENT_ID}:${worktreePath}`, { @@ -4167,43 +4034,6 @@ describe("ChatView timeline estimator parity (full app)", () => { } }); - it("renders the manager console in a dedicated manager inbox sidebar section", async () => { - const mounted = await mountChatView({ - viewport: DEFAULT_VIEWPORT, - snapshot: createSnapshotWithManagerConsole(), - }); - - try { - await expect.element(page.getByText("Manager Inbox", { exact: true })).toBeInTheDocument(); - await expect.element(page.getByTestId("thread-title-manager-console-1")).toBeInTheDocument(); - await expect.element(page.getByTestId(`thread-title-${THREAD_ID}`)).toBeInTheDocument(); - } finally { - await mounted.cleanup(); - } - }); - - it("opens the manager console conversation when selected from the manager inbox", async () => { - const mounted = await mountChatView({ - viewport: DEFAULT_VIEWPORT, - snapshot: createSnapshotWithManagerConsole(), - }); - - try { - await page.getByTestId("thread-row-manager-console-1").click(); - - const nextPath = await waitForURL( - mounted.router, - (path) => path === serverThreadPath("manager-console-1" as ThreadId), - "Route should change to the manager console thread.", - ); - - expect(nextPath).toBe(serverThreadPath("manager-console-1" as ThreadId)); - await expect.element(page.getByText("Manager inbox work", { exact: true })).toBeVisible(); - } finally { - await mounted.cleanup(); - } - }); - it("shows the sidebar terminal indicator from terminal metadata activity", async () => { const mounted = await mountChatView({ viewport: DEFAULT_VIEWPORT, @@ -5008,119 +4838,6 @@ describe("ChatView timeline estimator parity (full app)", () => { } }); - it("opens the project picker flow from a dedicated shortcut", async () => { - const mounted = await mountChatView({ - viewport: DEFAULT_VIEWPORT, - snapshot: createSnapshotForTargetUser({ - targetMessageId: "msg-user-project-picker-shortcut-test" as MessageId, - targetText: "project picker shortcut test", - }), - configureFixture: (nextFixture) => { - nextFixture.serverConfig = { - ...nextFixture.serverConfig, - keybindings: [ - { - command: "chat.newInProject", - shortcut: { - key: "n", - metaKey: false, - ctrlKey: false, - shiftKey: false, - altKey: true, - modKey: true, - }, - whenAst: { - type: "not", - node: { type: "identifier", name: "terminalFocus" }, - }, - }, - ], - }; - }, - }); - - try { - await waitForServerConfigToApply(); - dispatchProjectPickerShortcut(); - - const palette = page.getByTestId("command-palette"); - await expect.element(palette).toBeInTheDocument(); - await expect.element(palette.getByText("Project", { exact: true })).toBeInTheDocument(); - await palette.getByText("Project", { exact: true }).click(); - - await waitForURL( - mounted.router, - (path) => UUID_ROUTE_RE.test(path), - "Route should have changed to a new draft thread UUID from the project picker shortcut.", - ); - } finally { - await mounted.cleanup(); - } - }); - - it("focuses the composer at the end of the draft and does not steal modal input focus", async () => { - const mounted = await mountChatView({ - viewport: DEFAULT_VIEWPORT, - snapshot: createSnapshotForTargetUser({ - targetMessageId: "msg-user-focus-chat-shortcut-test" as MessageId, - targetText: "focus chat shortcut test", - }), - configureFixture: (nextFixture) => { - nextFixture.serverConfig = { - ...nextFixture.serverConfig, - keybindings: [ - { - command: "chat.focus", - shortcut: { - key: "i", - metaKey: false, - ctrlKey: false, - shiftKey: false, - altKey: false, - modKey: true, - }, - whenAst: { - type: "not", - node: { type: "identifier", name: "terminalFocus" }, - }, - }, - ], - }; - }, - }); - - try { - await waitForServerConfigToApply(); - useComposerDraftStore.getState().setPrompt(THREAD_REF, "Focus shortcut draft"); - await waitForLayout(); - - const threadRow = page.getByTestId(`thread-row-${THREAD_ID}`); - await expect.element(threadRow).toBeInTheDocument(); - (threadRow.element() as HTMLElement).focus(); - - dispatchFocusChatShortcut(); - await waitForLayout(); - - const composerEditor = await waitForComposerEditor(); - expect(document.activeElement).toBe(composerEditor); - expect(readComposerSelectionOffset()).toBe("Focus shortcut draft".length); - - await openCommandPaletteFromTrigger(); - const paletteInput = await waitForElement( - () => document.querySelector('[data-testid="command-palette"] input'), - "Command palette input did not render.", - ); - paletteInput.focus(); - - dispatchFocusChatShortcut(); - await waitForLayout(); - - expect(document.activeElement).toBe(paletteInput); - } finally { - await mounted.cleanup(); - } - }); - it("opens inline rename for the current thread and selects the full title", async () => { const mounted = await mountChatView({ viewport: DEFAULT_VIEWPORT, diff --git a/apps/web/src/components/ChatView.logic.test.ts b/apps/web/src/components/ChatView.logic.test.ts index 48c01bf5196b..21dac1f6a2d4 100644 --- a/apps/web/src/components/ChatView.logic.test.ts +++ b/apps/web/src/components/ChatView.logic.test.ts @@ -16,6 +16,7 @@ import { buildExpiredTerminalContextToastCopy, createLocalDispatchSnapshot, deriveComposerSendState, + getStartedThreadModelChangeBlockReason, hasServerAcknowledgedLocalDispatch, reconcileMountedTerminalThreadIds, resolveSendEnvMode, @@ -90,6 +91,73 @@ describe("buildExpiredTerminalContextToastCopy", () => { }); }); +describe("getStartedThreadModelChangeBlockReason", () => { + const providers = [ + { + instanceId: ProviderInstanceId.make("codex"), + }, + { + instanceId: ProviderInstanceId.make("grok"), + requiresNewThreadForModelChange: true, + }, + ]; + + it("allows model changes before a provider session has started", () => { + expect( + getStartedThreadModelChangeBlockReason({ + providers, + hasStartedSession: false, + currentModelSelection: { + instanceId: ProviderInstanceId.make("grok"), + model: "grok-build", + }, + nextModelSelection: { + instanceId: ProviderInstanceId.make("grok"), + model: "grok-other", + }, + }), + ).toBeNull(); + }); + + it("allows unchanged model selections for restricted providers", () => { + expect( + getStartedThreadModelChangeBlockReason({ + providers, + hasStartedSession: true, + currentModelSelection: { + instanceId: ProviderInstanceId.make("grok"), + model: "grok-build", + }, + nextModelSelection: { + instanceId: ProviderInstanceId.make("grok"), + model: "grok-build", + }, + }), + ).toBeNull(); + }); + + it("blocks started-session model changes when either provider requires a new thread", () => { + expect( + getStartedThreadModelChangeBlockReason({ + providers, + hasStartedSession: true, + currentModelSelection: { + instanceId: ProviderInstanceId.make("codex"), + model: "gpt-5.4", + }, + nextModelSelection: { + instanceId: ProviderInstanceId.make("grok"), + model: "grok-build", + }, + }), + ).toEqual({ + title: "Start a new chat to change models", + description: + "This provider does not allow switching models after a conversation has started.", + }); + }); +}); + describe("resolveSendEnvMode", () => { it("keeps worktree mode for git repositories", () => { expect(resolveSendEnvMode({ requestedEnvMode: "worktree", isGitRepo: true })).toBe("worktree"); diff --git a/apps/web/src/components/ChatView.logic.ts b/apps/web/src/components/ChatView.logic.ts index 8a9ec0887bf0..ddae9ff00cf0 100644 --- a/apps/web/src/components/ChatView.logic.ts +++ b/apps/web/src/components/ChatView.logic.ts @@ -4,6 +4,7 @@ import { ProjectId, type ModelSelection, type ProviderDriverKind, + type ServerProvider, type ScopedThreadRef, type ThreadId, type TurnId, @@ -41,6 +42,7 @@ export function buildLocalDraftThread( interactionMode: draftThread.interactionMode, session: null, messages: [], + contextTrimPoints: [], error, createdAt: draftThread.createdAt, archivedAt: null, @@ -50,7 +52,6 @@ export function buildLocalDraftThread( turnDiffSummaries: [], activities: [], proposedPlans: [], - contextTrimPoints: [], }; } @@ -263,6 +264,44 @@ export function deriveLockedProvider(input: { return narrowedThreadProvider ?? narrowedSelectedProvider ?? null; } +export function getStartedThreadModelChangeBlockReason(input: { + providers: ReadonlyArray>; + hasStartedSession: boolean; + currentModelSelection: ModelSelection; + currentProviderInstanceId?: ModelSelection["instanceId"] | null | undefined; + nextModelSelection: ModelSelection; +}): { title: string; description: string } | null { + if (!input.hasStartedSession) { + return null; + } + const currentModelSelection = { + ...input.currentModelSelection, + instanceId: input.currentProviderInstanceId ?? input.currentModelSelection.instanceId, + }; + if ( + currentModelSelection.instanceId === input.nextModelSelection.instanceId && + currentModelSelection.model === input.nextModelSelection.model + ) { + return null; + } + const currentProvider = input.providers.find( + (snapshot) => snapshot.instanceId === currentModelSelection.instanceId, + ); + const nextProvider = input.providers.find( + (snapshot) => snapshot.instanceId === input.nextModelSelection.instanceId, + ); + if ( + currentProvider?.requiresNewThreadForModelChange !== true && + nextProvider?.requiresNewThreadForModelChange !== true + ) { + return null; + } + return { + title: "Start a new chat to change models", + description: "This provider does not allow switching models after a conversation has started.", + }; +} + export async function waitForStartedServerThread( threadRef: ScopedThreadRef, timeoutMs = 1_000, diff --git a/apps/web/src/components/ChatView.tsx b/apps/web/src/components/ChatView.tsx index 09c9c6c06f54..d3f69563a15c 100644 --- a/apps/web/src/components/ChatView.tsx +++ b/apps/web/src/components/ChatView.tsx @@ -119,10 +119,6 @@ import { newCommandId, newDraftId, newMessageId, newThreadId } from "~/lib/utils import { getProviderModelCapabilities, resolveSelectableProvider } from "../providerModels"; import { useSettings } from "../hooks/useSettings"; import { resolveAppModelSelectionForInstance } from "../modelSelection"; -import { - isEditableShortcutTarget, - isModalShortcutCaptureActive, -} from "../lib/globalShortcutGuards"; import { isTerminalFocused } from "../lib/terminalFocus"; import { deriveLogicalProjectKeyFromSettings, @@ -133,7 +129,7 @@ import { useSavedEnvironmentRegistryStore, useSavedEnvironmentRuntimeStore, } from "../environments/runtime"; -import { buildDraftThreadRouteParams, buildThreadRouteParams } from "../threadRoutes"; +import { buildDraftThreadRouteParams } from "../threadRoutes"; import { type ComposerImageAttachment, type DraftThreadEnvMode, @@ -1772,13 +1768,9 @@ export default function ChatView(props: ChatViewProps) { timelineMessages, activeThread?.proposedPlans ?? [], workLogEntries, - activeThread?.managerMetadata, - activeThread?.createdAt, activeThread?.contextTrimPoints, ), [ - activeThread?.managerMetadata, - activeThread?.createdAt, activeThread?.proposedPlans, activeThread?.contextTrimPoints, timelineMessages, @@ -2720,19 +2712,6 @@ export default function ChatView(props: ChatViewProps) { }); if (!command) return; - if (command === "chat.focus") { - if ( - isModalShortcutCaptureActive(event.target) || - isEditableShortcutTarget(event.target, { allowComposer: true }) - ) { - return; - } - event.preventDefault(); - event.stopPropagation(); - focusComposer(); - return; - } - if (command === "terminal.toggle") { event.preventDefault(); event.stopPropagation(); @@ -2941,7 +2920,10 @@ export default function ChatView(props: ChatViewProps) { ); return; } - if (typeof standaloneSlashCommand === "object") { + if ( + typeof standaloneSlashCommand === "object" && + standaloneSlashCommand.command === "clear" + ) { api.orchestration .dispatchCommand({ type: "thread.context.trim", @@ -2984,7 +2966,7 @@ export default function ChatView(props: ChatViewProps) { }); void navigate({ to: "/$environmentId/$threadId", - params: buildThreadRouteParams(scopeThreadRef(activeThread.environmentId, nextThreadId)), + params: { environmentId: activeThread.environmentId, threadId: nextThreadId }, }); } else if (standaloneSlashCommand === "compact") { api.orchestration @@ -3004,7 +2986,7 @@ export default function ChatView(props: ChatViewProps) { }), ); }); - } else { + } else if (standaloneSlashCommand === "default" || standaloneSlashCommand === "plan") { handleInteractionModeChange(standaloneSlashCommand); } promptRef.current = ""; diff --git a/apps/web/src/components/CommandPalette.tsx b/apps/web/src/components/CommandPalette.tsx index 81aa9c85d2e3..af8581a6fd02 100644 --- a/apps/web/src/components/CommandPalette.tsx +++ b/apps/web/src/components/CommandPalette.tsx @@ -1019,7 +1019,6 @@ function OpenCommandPaletteDialog() { title: "New thread in...", icon: , addonIcon: , - shortcutCommand: "chat.newInProject", groups: [{ value: "projects", label: "Projects", items: projectThreadItems }], }); } @@ -1077,27 +1076,9 @@ function OpenCommandPaletteDialog() { const handleAddProject = useCallback( async (rawCwd: string) => { - if (!browseEnvironmentId) { - toastManager.add( - stackedThreadToast({ - type: "error", - title: "Failed to add project", - description: "No environment selected. Ensure a backend is paired and connected.", - }), - ); - return; - } + if (!browseEnvironmentId) return; const api = readEnvironmentApi(browseEnvironmentId); - if (!api) { - toastManager.add( - stackedThreadToast({ - type: "error", - title: "Failed to add project", - description: `Environment API not available for this environment. The WebSocket connection may not be established.`, - }), - ); - return; - } + if (!api) return; if (isUnsupportedWindowsProjectPath(rawCwd.trim(), browseEnvironmentPlatform)) { toastManager.add( diff --git a/apps/web/src/components/DiffCommentPanel.test.tsx b/apps/web/src/components/DiffCommentPanel.test.tsx deleted file mode 100644 index d2f66fd01136..000000000000 --- a/apps/web/src/components/DiffCommentPanel.test.tsx +++ /dev/null @@ -1,405 +0,0 @@ -import type { ReviewComment } from "@t3tools/contracts"; -import { renderToStaticMarkup } from "react-dom/server"; -import { describe, expect, it } from "vite-plus/test"; - -import { DiffCommentPanel } from "./DiffCommentPanel"; - -function makeComment(overrides: Partial = {}): ReviewComment { - return { - id: "test-1", - file: "src/app.ts", - line: 42, - commitSHA: "abc123", - body: "Test comment body.", - author: { login: "tester" }, - createdAt: "2025-06-01T12:00:00Z", - ...overrides, - }; -} - -describe("DiffCommentPanel", () => { - it("renders an existing comment with body and author", () => { - const comment = makeComment(); - const markup = renderToStaticMarkup( - {}} - onCancelEditing={() => {}} - onSaveComment={async () => {}} - onDeleteComment={() => {}} - savePending={false} - saveError={null} - />, - ); - - expect(markup).toContain("Test comment body."); - expect(markup).toContain("tester"); - expect(markup).toContain("Line 42"); - }); - - it("renders file-level comment without line number", () => { - const comment = makeComment({ line: undefined }); - const markup = renderToStaticMarkup( - {}} - onCancelEditing={() => {}} - onSaveComment={async () => {}} - onDeleteComment={() => {}} - savePending={false} - saveError={null} - />, - ); - - expect(markup).toContain("Test comment body."); - expect(markup).not.toContain("Line 42"); - }); - - it("applies GitHub badge styling for non-local comments", () => { - const comment = makeComment({ author: { login: "github-bot" } }); - const markup = renderToStaticMarkup( - {}} - onCancelEditing={() => {}} - onSaveComment={async () => {}} - onDeleteComment={() => {}} - savePending={false} - saveError={null} - />, - ); - - expect(markup).toContain("GitHub"); - expect(markup).toContain("github-bot"); - }); - - it("shows edit form when editing comment for matching file", () => { - const markup = renderToStaticMarkup( - {}} - onCancelEditing={() => {}} - onSaveComment={async () => {}} - onDeleteComment={() => {}} - savePending={false} - saveError={null} - />, - ); - - expect(markup).toContain("Write a comment"); - expect(markup).toContain("src/app.ts:10"); - }); - - it("uses filePath only for file-level editing comment", () => { - const markup = renderToStaticMarkup( - {}} - onCancelEditing={() => {}} - onSaveComment={async () => {}} - onDeleteComment={() => {}} - savePending={false} - saveError={null} - />, - ); - - expect(markup).toContain("Write a comment"); - expect(markup).toContain("src/app.ts"); - expect(markup).not.toContain("src/app.ts:"); - }); - - it("renders multiple comments for the same file", () => { - const comment1 = makeComment({ id: "c1", body: "First" }); - const comment2 = makeComment({ id: "c2", body: "Second", author: { login: "github-bot" } }); - const otherComment = makeComment({ id: "c3", file: "other.ts", body: "Other file" }); - - const markup = renderToStaticMarkup( - {}} - onCancelEditing={() => {}} - onSaveComment={async () => {}} - onDeleteComment={() => {}} - savePending={false} - saveError={null} - />, - ); - - expect(markup).toContain("First"); - expect(markup).toContain("Second"); - expect(markup).not.toContain("Other file"); - }); - - it("filters comments to matching file only", () => { - const comments = [ - makeComment({ id: "a", file: "a.ts", body: "File A" }), - makeComment({ id: "b", file: "b.ts", body: "File B" }), - ]; - - const markup = renderToStaticMarkup( - {}} - onCancelEditing={() => {}} - onSaveComment={async () => {}} - onDeleteComment={() => {}} - savePending={false} - saveError={null} - />, - ); - - expect(markup).toContain("File A"); - expect(markup).not.toContain("File B"); - }); - - it("shows save error when present", () => { - const markup = renderToStaticMarkup( - {}} - onCancelEditing={() => {}} - onSaveComment={async () => {}} - onDeleteComment={() => {}} - savePending={false} - saveError="Failed to save comment" - />, - ); - - expect(markup).toContain("Failed to save comment"); - }); - - it("shows comment-on-file button when not editing", () => { - const markup = renderToStaticMarkup( - {}} - onCancelEditing={() => {}} - onSaveComment={async () => {}} - onDeleteComment={() => {}} - savePending={false} - saveError={null} - />, - ); - - expect(markup).toContain("Comment on file"); - }); - - it("hides add comment buttons while editing", () => { - const markup = renderToStaticMarkup( - {}} - onCancelEditing={() => {}} - onSaveComment={async () => {}} - onDeleteComment={() => {}} - savePending={false} - saveError={null} - />, - ); - - expect(markup).toContain("Write a comment"); - expect(markup).not.toContain("Comment on file"); - expect(markup).not.toContain("Comment on line"); - }); - - it("collapses outdated comments under toggle when PR head SHA changed", () => { - const currentSHA = "def456"; - const storedSHA = "abc123"; - const outdatedComment = makeComment({ - id: "old", - commitSHA: storedSHA, - body: "Old review comment.", - }); - const currentComment = makeComment({ - id: "new", - commitSHA: currentSHA, - body: "Current review comment.", - }); - - const markup = renderToStaticMarkup( - {}} - onCancelEditing={() => {}} - onSaveComment={async () => {}} - onDeleteComment={() => {}} - savePending={false} - saveError={null} - currentPrHeadSHA={currentSHA} - storedPrHeadSHA={storedSHA} - />, - ); - - expect(markup).toContain("Show 1 outdated"); - expect(markup).toContain("Current review comment."); - expect(markup).toContain("1 outdated"); - }); - - it("renders outdated comments with body and Outdated badge when expanded", () => { - const currentSHA = "def456"; - const storedSHA = "abc123"; - const outdatedComment = makeComment({ - id: "old", - commitSHA: storedSHA, - body: "Old review comment.", - }); - - // Verify that the outdated comment body and Outdated badge exist - // in the component logic (even though SSR has collapsed state) - const markup = renderToStaticMarkup( - {}} - onCancelEditing={() => {}} - onSaveComment={async () => {}} - onDeleteComment={() => {}} - savePending={false} - saveError={null} - currentPrHeadSHA={currentSHA} - storedPrHeadSHA={storedSHA} - />, - ); - - expect(markup).toContain("Show 1 outdated"); - expect(markup).toContain("1 outdated"); - expect(markup).toContain("Old review comment."); - expect(markup).toContain("Outdated"); - }); - - it("does not show outdated toggle when PR head SHA is unchanged", () => { - const sha = "abc123"; - const comment = makeComment({ commitSHA: sha, body: "My comment." }); - - const markup = renderToStaticMarkup( - {}} - onCancelEditing={() => {}} - onSaveComment={async () => {}} - onDeleteComment={() => {}} - savePending={false} - saveError={null} - currentPrHeadSHA={sha} - storedPrHeadSHA={sha} - />, - ); - - expect(markup).not.toContain("Show"); - expect(markup).not.toContain("Outdated"); - expect(markup).toContain("My comment."); - }); - - it("does not show outdated toggle when currentPrHeadSHA is not provided", () => { - const sha = "abc123"; - const comment = makeComment({ commitSHA: sha, body: "My comment." }); - - const markup = renderToStaticMarkup( - {}} - onCancelEditing={() => {}} - onSaveComment={async () => {}} - onDeleteComment={() => {}} - savePending={false} - saveError={null} - />, - ); - - expect(markup).not.toContain("Outdated"); - expect(markup).toContain("My comment."); - }); - - it("file-level comments without line number are not stale when file is unmodified", () => { - const currentSHA = "def456"; - const storedSHA = "abc123"; - const fileComment = makeComment({ - id: "unmod", - file: "src/unmodified.ts", - commitSHA: storedSHA, - body: "Unmodified file comment.", - line: undefined, - }); - - const markup = renderToStaticMarkup( - {}} - onCancelEditing={() => {}} - onSaveComment={async () => {}} - onDeleteComment={() => {}} - savePending={false} - saveError={null} - currentPrHeadSHA={currentSHA} - storedPrHeadSHA={storedSHA} - modifiedFiles={new Set(["src/modified.ts"])} - />, - ); - - expect(markup).toContain("Unmodified file comment."); - expect(markup).not.toContain("Outdated"); - expect(markup).not.toContain("Show"); - }); - - it("file-level comments are stale when their file was modified", () => { - const currentSHA = "def456"; - const storedSHA = "abc123"; - const fileComment = makeComment({ - id: "mod", - file: "src/modified.ts", - commitSHA: storedSHA, - body: "Modified file comment.", - line: undefined, - }); - - const markup = renderToStaticMarkup( - {}} - onCancelEditing={() => {}} - onSaveComment={async () => {}} - onDeleteComment={() => {}} - savePending={false} - saveError={null} - currentPrHeadSHA={currentSHA} - storedPrHeadSHA={storedSHA} - modifiedFiles={new Set(["src/modified.ts"])} - />, - ); - - expect(markup).toContain("Show 1 outdated"); - expect(markup).toContain("Modified file comment."); - expect(markup).toContain("Outdated"); - }); -}); diff --git a/apps/web/src/components/DiffCommentPanel.tsx b/apps/web/src/components/DiffCommentPanel.tsx deleted file mode 100644 index 65e83702ddd4..000000000000 --- a/apps/web/src/components/DiffCommentPanel.tsx +++ /dev/null @@ -1,481 +0,0 @@ -import type { ReviewComment } from "@t3tools/contracts"; -import { - Loader2Icon, - CheckIcon, - XIcon, - BotIcon, - ChevronDownIcon, - ChevronRightIcon, - PlusIcon, - ReplyIcon, - Trash2Icon, -} from "lucide-react"; -import { useCallback, useState } from "react"; -import { cn } from "~/lib/utils"; -import { formatShortTimestamp } from "../timestampFormat"; -import type { BackgroundAgentEvent } from "../hooks/useReviewComments"; - -interface InlineCommentInputProps { - filePath: string; - lineNumber: number | null; - prefillBody: string; - onSave: (body: string) => Promise; - onCancel: () => void; - pending: boolean; - error: string | null; -} - -function InlineCommentInput({ - filePath, - lineNumber, - prefillBody, - onSave, - onCancel, - pending, - error, -}: InlineCommentInputProps) { - const [body, setBody] = useState(prefillBody); - const trimmed = body.trim(); - - const handleSave = useCallback(() => { - if (!trimmed) return; - void onSave(trimmed); - }, [trimmed, onSave]); - - return ( -
-
- - {filePath} - {lineNumber !== null ? `:${lineNumber}` : ""} - - -
-