From ed4eb011aeed6adc1a0da63a81defeedd4fee4f5 Mon Sep 17 00:00:00 2001 From: Chris Green Date: Tue, 21 Jul 2026 14:45:18 -0500 Subject: [PATCH 1/7] build(devcontainer): refine workspace paths and VS Code configuration Improve the development container setup to better support co-located repositories and hybrid host/container workflows. Changes include: - Update `codespace.code-workspace` to use relative paths and workspace folder variables, ensuring compatibility with host-side checkouts. - Enhance `devcontainer.json` with dynamic workspace folder naming and comprehensive Python analysis paths, including build and dependency directories. - Update `docker-compose.yml` with SELinux `:Z` flags for all volume mounts and introduce a dedicated `phlex-kilo-data` volume for Kilo Code data. - Refine `setup-repos.sh` to mark cloned repositories as safe directories and ensure reliable execution. - Add a global `.gitignore` to the container image to reduce noise from build artifacts. - Clean up redundant extension recommendations in `phlex.code-workspace`. --- .devcontainer/Dockerfile | 6 +- .devcontainer/codespace.code-workspace | 59 ++++++++++-------- .devcontainer/devcontainer.json | 84 ++++++++++++++++---------- .devcontainer/docker-compose.yml | 24 ++++---- .devcontainer/gitignore-global | 4 ++ .devcontainer/post-create.sh | 6 -- .devcontainer/setup-repos.sh | 33 +++++----- phlex.code-workspace | 31 ---------- 8 files changed, 127 insertions(+), 120 deletions(-) create mode 100644 .devcontainer/gitignore-global diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 08bc3653d..638049a03 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -93,9 +93,8 @@ INSTALL_MAN_TOOLS RUN bash <<'INSTALL_DEV_UTILS' set -euo pipefail apt-get update -apt-get install -y --no-install-recommends jq podman ssh socat tree yq apt purge nodejs npm -y && apt autoremove -y || true -apt-get install -y curl --no-install-recommends --autoremove +apt-get install -y --no-install-recommends chrpath curl jq patchelf nano podman ssh socat tree vim yq curl -fsSL https://deb.nodesource.com/setup_26.x | bash - apt-get install -y nodejs apt-get clean @@ -115,3 +114,6 @@ RUN printf '. /entrypoint.sh\n' >> /root/.bashrc # Ensure /run/user/0 exists and is owned by root with 700 permissions to # allow GPG agent to function correctly when running as root. RUN mkdir -p /run/user/0 && chmod 700 /run/user/0 && chown root:root /run/user/0 + +COPY gitignore-global /root/.gitignore-global +RUN git config --global core.excludesfile '/root/.gitignore-global' diff --git a/.devcontainer/codespace.code-workspace b/.devcontainer/codespace.code-workspace index b7b289bf1..e8d72fbf9 100644 --- a/.devcontainer/codespace.code-workspace +++ b/.devcontainer/codespace.code-workspace @@ -2,23 +2,23 @@ "folders": [ { "name": "Phlex", - "path": "/workspaces/phlex" + "path": ".." }, { "name": "Phlex Design", - "path": "/workspaces/phlex-design" + "path": "../../phlex-design" }, { "name": "Phlex Examples", - "path": "/workspaces/phlex-examples" + "path": "../../phlex-examples" }, { "name": "Phlex Coding Guidelines", - "path": "/workspaces/phlex-coding-guidelines" + "path": "../../phlex-coding-guidelines" }, { "name": "Phlex Spack Recipes", - "path": "/workspaces/phlex-spack-recipes" + "path": "../../phlex-spack-recipes" } ], "settings": { @@ -63,38 +63,49 @@ }, "python.languageServer": "Pylance", "python.terminal.activateEnvironment": false, - "python.defaultInterpreterPath": "/opt/spack-environments/phlex-ci/.spack-env/view/bin/python", - "esbonio.server.pythonPath": "/opt/spack-environments/phlex-ci/.spack-env/view/bin/python", + // Container-only interpreter paths (python.defaultInterpreterPath, + // esbonio.server.pythonPath) are intentionally not set here: this file + // is shared with host (non-devcontainer) checkouts, where + // /opt/spack-environments does not exist. The devcontainer supplies + // them via the Remote scope in devcontainer.json (Remote settings only + // apply when actually connected to that container). Host users should + // set their own interpreter in a local .vscode/settings.json (Folder + // scope overrides this Workspace scope) -- see + // .vscode/settings.json.example. "esbonio.logging.level": "debug", "python.analysis.typeCheckingMode": "basic", "python.analysis.diagnosticMode": "workspace", "python.analysis.include": [ - "/workspaces/phlex" + "${workspaceFolder:Phlex}" ], "python.analysis.extraPaths": [ - "/workspaces/phlex/plugins/python/python", + "${workspaceFolder:Phlex}/plugins/python/python", + "${workspaceFolder:Phlex}/scripts", + "${workspaceFolder:Phlex}/build/_deps", + "${workspaceFolder:Phlex}/out/build/*/_deps", "/opt/spack-environments/phlex-ci/.spack-env/view/lib/root", - "/opt/spack-environments/phlex-ci/.spack-env/view/lib/python/site-packages" + "/opt/spack-environments/phlex-ci/.spack-env/view/lib/python/site-packages", + "/spack/lib/spack" ], "python.analysis.exclude": [ "/opt/spack-environments", - "/workspaces/phlex/local", - "/workspaces/phlex/build/_deps", - "/workspaces/phlex/build/CMakeFiles", - "/workspaces/phlex/**/.venv", - "/workspaces/phlex/**/py_virtual_env" + "${workspaceFolder:Phlex}/local", + "${workspaceFolder:Phlex}/build/_deps", + "${workspaceFolder:Phlex}/build/CMakeFiles", + "${workspaceFolder:Phlex}/**/.venv", + "${workspaceFolder:Phlex}/**/py_virtual_env" ], "python.analysis.ignore": [ "/opt/spack-environments", - "/workspaces/phlex-design", - "/workspaces/phlex-examples", - "/workspaces/phlex-coding-guidelines", - "/workspaces/phlex-spack-recipes", - "/workspaces/phlex/local", - "/workspaces/phlex/build/_deps", - "/workspaces/phlex/build/CMakeFiles", - "/workspaces/phlex/**/.venv", - "/workspaces/phlex/**/py_virtual_env" + "${workspaceFolder:Phlex Design}", + "${workspaceFolder:Phlex Examples}", + "${workspaceFolder:Phlex Coding Guidelines}", + "${workspaceFolder:Phlex Spack Recipes}", + "${workspaceFolder:Phlex}/local", + "${workspaceFolder:Phlex}/build/_deps", + "${workspaceFolder:Phlex}/build/CMakeFiles", + "${workspaceFolder:Phlex}/**/.venv", + "${workspaceFolder:Phlex}/**/py_virtual_env" ], "flake8.enabled": false, "pylint.enabled": false, diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 91b3276d7..cbeebe038 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -2,63 +2,82 @@ "name": "Phlex CI Dev Container", "dockerComposeFile": "docker-compose.yml", "service": "phlex-dev", - "workspaceFolder": "/workspaces/phlex", + "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}", "remoteUser": "root", "remoteEnv": { "KILO_API_KEY": "${localEnv:HEADROOM_UPSTREAM_KEY}" }, - "initializeCommand": "bash .devcontainer/ensure-repos.sh", - "onCreateCommand": "bash .devcontainer/setup-repos.sh /workspaces", - "postCreateCommand": "bash -lc 'bash .devcontainer/post-create.sh'", + "initializeCommand": ".devcontainer/ensure-repos.sh", + "onCreateCommand": ".devcontainer/setup-repos.sh /workspaces", + "postCreateCommand": "git config --global --add safe.directory '${containerWorkspaceFolder}' && bash -lc '.devcontainer/post-create.sh'", "customizations": { - "vscode": { "settings": { - "terminal.integrated.defaultProfile.linux": "bash", - "terminal.integrated.profiles.linux": { - "bash": { - "path": "/bin/bash", - "args": [ - "-i" - ], - "icon": "terminal-bash" - } - }, - "terminal.integrated.shellIntegration.suggestEnablement": false, - "python.terminal.activateEnvironment": false, - "python.defaultInterpreterPath": "/opt/spack-environments/phlex-ci/.spack-env/view/bin/python", - "python.analysis.extraPaths": [ - "${workspaceFolder}/build", - "/opt/spack-environments/phlex-ci/.spack-env/view/lib/root", - "/opt/spack-environments/phlex-ci/.spack-env/view/lib/python/site-packages" - ], - "cmake.defaultConfigurePreset": "default", + "chat.agent.sandbox.enabled": "off", "cmake.buildDirectory": "${workspaceFolder}/build", + "cmake.defaultConfigurePreset": "default", "cmake.generator": "Ninja", + "cmake.useCMakePresets": "always", "C_Cpp.default.cStandard": "c17", + "C_Cpp.default.compileCommands": "${workspaceFolder}/build/compile_commands.json", "C_Cpp.default.cppStandard": "c++23", "C_Cpp.default.intelliSenseMode": "linux-gcc-x64", - "C_Cpp.default.compileCommands": "${workspaceFolder}/build/compile_commands.json", - "python.languageServer": "Pylance", - "python.analysis.typeCheckingMode": "basic", + "files.watcherExclude": { + "**/.venv/**": true, + "**/py_virtual_env/**": true + }, + "git.autoRepositoryDetection": "subFolders", + "git.repositoryScanMaxDepth": 1, + "git.scanRepositories": [ + "/workspaces/phlex", + "/workspaces/phlex-coding-guidelines", + "/workspaces/phlex-design", + "/workspaces/phlex-examples", + "/workspaces/phlex-spack-recipes" + ], + "kilocode.new.extraCaCerts": "", "python.analysis.diagnosticMode": "workspace", "python.analysis.exclude": [ "**/.venv/**", - "**/py_virtual_env/**" + "**/py_virtual_env/**", + "**/build/_deps/**", + "**/out/build/*/_deps/**" ], "python.analysis.ignore": [ "**/.venv/**", "**/py_virtual_env/**" ], + "python.analysis.extraPaths": [ + "${workspaceFolder}/plugins/python/python", + "${workspaceFolder}/scripts", + "${workspaceFolder}/build", + "${workspaceFolder}/build/_deps", + "${workspaceFolder}/out/build/*/_deps", + "/opt/spack-environments/phlex-ci/.spack-env/view/lib/root", + "/opt/spack-environments/phlex-ci/.spack-env/view/lib/python/site-packages", + "/spack/lib/spack" + ], + "python.analysis.typeCheckingMode": "basic", + "python.defaultInterpreterPath": "/opt/spack-environments/phlex-ci/.spack-env/view/bin/python", + "python.languageServer": "Pylance", + "python.terminal.activateEnvironment": false, + "esbonio.server.pythonPath": "/opt/spack-environments/phlex-ci/.spack-env/view/bin/python", + "esbonio.logging.level": "debug", "search.exclude": { "**/.venv/**": true, "**/py_virtual_env/**": true }, - "files.watcherExclude": { - "**/.venv/**": true, - "**/py_virtual_env/**": true + "terminal.integrated.defaultProfile.linux": "bash", + "terminal.integrated.profiles.linux": { + "bash": { + "path": "/bin/bash", + "args": [ + "-i" + ], + "icon": "terminal-bash" + } }, - "kilocode.new.extraCaCerts": "" + "terminal.integrated.shellIntegration.suggestEnablement": false }, "extensions": [ "charliermarsh.ruff", @@ -82,6 +101,7 @@ "ms-python.vscode-pylance", "ms-python.vscode-python-envs", "ms-vscode.cmake-tools", + "ms-vscode.cpptools", "ms-vscode.cpptools-extension-pack", "ms-vscode.cpptools-themes", "ms-vscode.hexeditor", diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index 49ac938b8..806a8a096 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -6,17 +6,18 @@ services: context: . dockerfile: Dockerfile volumes: - - ..:/workspaces/phlex - - ../../phlex-coding-guidelines:/workspaces/phlex-coding-guidelines - - ../../phlex-design:/workspaces/phlex-design - - ../../phlex-examples:/workspaces/phlex-examples - - ../../phlex-spack-recipes:/workspaces/phlex-spack-recipes - - ${HOME}/.config/gh:/root/.config/gh:ro - - ${HOME}/.config/kilo:/root/.config/kilo - - ${HOME}/.gnupg:/root/.gnupg - - ${HOME}/.podman-proxy/podman.sock:/tmp/podman.sock - - ${HOME}/.local/share/kilo:/root/.local/share/kilo:ro - - phlex-vscode-user-data:/root/.vscode-server-insiders/data/User + - ..:/workspaces/phlex:Z + - ../../phlex-coding-guidelines:/workspaces/phlex-coding-guidelines:Z + - ../../phlex-design:/workspaces/phlex-design:Z + - ../../phlex-examples:/workspaces/phlex-examples:Z + - ../../phlex-spack-recipes:/workspaces/phlex-spack-recipes:Z + - ${HOME}/.config/gh:/root/.config/gh:ro,Z + - ${HOME}/.config/kilo:/root/.config/kilo:ro,Z + - ${HOME}/.gnupg:/root/.gnupg:ro,Z + - ${HOME}/.podman-proxy/podman.sock:/tmp/podman.sock:Z + - phlex-kilo-data:/root/.local/share/kilo:Z + - ${HOME}/.local/share/kilo/auth.json:/root/.local/share/kilo/auth.json:ro,Z + - phlex-vscode-user-data:/root/.vscode-server-insiders/data/User:Z environment: - CMAKE_GENERATOR=Ninja - GH_CONFIG_DIR=/root/.config/gh @@ -29,3 +30,4 @@ services: volumes: phlex-vscode-user-data: + phlex-kilo-data: diff --git a/.devcontainer/gitignore-global b/.devcontainer/gitignore-global new file mode 100644 index 000000000..a8dd7f5fc --- /dev/null +++ b/.devcontainer/gitignore-global @@ -0,0 +1,4 @@ +build/ +out/ +_deps/ +_build/ diff --git a/.devcontainer/post-create.sh b/.devcontainer/post-create.sh index 75fecde39..59dc9ed40 100755 --- a/.devcontainer/post-create.sh +++ b/.devcontainer/post-create.sh @@ -11,12 +11,6 @@ cat > ~/.actrc <<'EOF' --container-options --userns=keep-id EOF -# Clear the VS Code extension-install marker so that VS Code always installs the -# extensions listed in devcontainer.json on a fresh container. Without this, the -# marker persists on the host via the Machine data bind-mount and VS Code skips -# installation on every rebuild. -rm -f /root/.vscode-server-insiders/data/Machine/.installExtensionsMarker - # Seed the Kilo Code auth token into the container-private data volume. # The volume is not shared with the host to avoid SQLite conflicts between # the Remote-SSH and devcontainer Kilo Code instances. The API key is diff --git a/.devcontainer/setup-repos.sh b/.devcontainer/setup-repos.sh index ec618b731..9086edc6e 100755 --- a/.devcontainer/setup-repos.sh +++ b/.devcontainer/setup-repos.sh @@ -5,8 +5,6 @@ # # Intended to be called from devcontainer.json onCreateCommand. -set -euo pipefail - WORKSPACE_ROOT="${1:-/workspaces}" if [ ! -d "$WORKSPACE_ROOT" ]; then @@ -17,28 +15,35 @@ fi clone_if_absent() { local repo=$1 local dest="${WORKSPACE_ROOT}/${repo}" + local need_clone=1 if [ -e "$dest/.git" ]; then echo "Repository already present: $dest" - return + need_clone=0 elif [ -e "$dest" ]; then echo "WARNING: refusing to overwrite non-repository $dest:" ls -ld "$dest" - return + return 1 fi - echo "Cloning Framework-R-D/${repo} into ${dest} ..." - local max_tries=5 current_try=0 - while ! git clone --depth 1 "https://github.com/Framework-R-D/${repo}.git" "$dest"; do - (( ++current_try )) - echo "Attempt $current_try/$max_tries to clone $repo from GitHub FAILED" - (( current_try < max_tries )) || break - sleep 5 - done - if (( current_try == max_tries )); then - echo "WARNING: unable to check out $repo to $dest from GitHub" 1>&2 + if (( need_clone )); then + echo "Cloning Framework-R-D/${repo} into ${dest} ..." + local max_tries=5 current_try=0 + while ! git clone --depth 1 "https://github.com/Framework-R-D/${repo}.git" "$dest"; do + (( ++current_try )) + echo "Attempt $current_try/$max_tries to clone $repo from GitHub FAILED" + (( current_try < max_tries )) || break + sleep 5 + done + if (( current_try == max_tries )); then + echo "WARNING: unable to check out $repo to $dest from GitHub" 1>&2 + return 1 + fi fi + git config --global --add safe.directory "$dest" } clone_if_absent phlex-design clone_if_absent phlex-examples clone_if_absent phlex-coding-guidelines clone_if_absent phlex-spack-recipes + +exit 0 diff --git a/phlex.code-workspace b/phlex.code-workspace index 043c61b3c..fce0252c7 100644 --- a/phlex.code-workspace +++ b/phlex.code-workspace @@ -77,36 +77,5 @@ "https://json.schemastore.org/github-workflow.json": "./.github/workflows/*", "https://json.schemastore.org/github-action.json": "./.github/actions/*/action.yaml" } - }, - "extensions": { - "recommendations": [ - "ms-vscode.cmake-tools", - "ms-vscode.cpptools", - "ms-vscode.cpptools-extension-pack", - "twxs.cmake", - "ms-vscode.vscode-json", - "redhat.vscode-yaml", - "charliermarsh.ruff", - "github.vscode-actions", - "github.copilot", - "github.copilot-chat", - "github.vscode-pull-request-github", - "ms-vscode.hexeditor" - ], - "unwantedRecommendations": [ - "reditorsupport.r", - "ms-vscode.r", - "ikuyadeu.r", - "ms-vscode.r-debugger", - "vscjava.vscode-java-pack", - "redhat.java", - "vscjava.vscode-java-debug", - "vscjava.vscode-java-test", - "vscjava.vscode-maven", - "vscjava.vscode-gradle", - "ms-python.python", - "ms-toolsai.jupyter", - "ms-python.flake8" - ] } } From 6fd60765ee10ae6f02811ce95b2aee1fe42f01f7 Mon Sep 17 00:00:00 2001 From: Chris Green Date: Wed, 22 Jul 2026 08:41:50 -0500 Subject: [PATCH 2/7] build(devcontainer): update script execution and Pyright paths Explicitly invoke bash for devcontainer lifecycle scripts to ensure consistent execution. Expand `extraPaths` in `pyproject.toml` for Pyright/Pylance to resolve dependencies from build directories and Spack environments within the devcontainer, improving IDE type checking and navigation. --- .devcontainer/devcontainer.json | 6 +++--- pyproject.toml | 19 ++++++++++++++++++- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index cbeebe038..26aef4c19 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -7,9 +7,9 @@ "remoteEnv": { "KILO_API_KEY": "${localEnv:HEADROOM_UPSTREAM_KEY}" }, - "initializeCommand": ".devcontainer/ensure-repos.sh", - "onCreateCommand": ".devcontainer/setup-repos.sh /workspaces", - "postCreateCommand": "git config --global --add safe.directory '${containerWorkspaceFolder}' && bash -lc '.devcontainer/post-create.sh'", + "initializeCommand": "bash .devcontainer/ensure-repos.sh", + "onCreateCommand": "bash .devcontainer/setup-repos.sh /workspaces", + "postCreateCommand": "git config --global --add safe.directory '${containerWorkspaceFolder}' && bash -lc 'bash .devcontainer/post-create.sh'", "customizations": { "vscode": { "settings": { diff --git a/pyproject.toml b/pyproject.toml index 274287260..0b29feb05 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,24 @@ warn_unreachable = true disable_error_code = "annotation-unchecked" [tool.pyright] -extraPaths = ["plugins/python/python", "scripts"] +# NOTE: this table is Pylance/Pyright's highest-precedence configuration +# source: once it exists, python.analysis.extraPaths (and include/exclude/ +# ignore/typeCheckingMode/etc.) set via VS Code settings.json or a +# .code-workspace file are ignored entirely. Update extraPaths here, not +# there. Paths are relative to this file's directory (the repo root) unless +# absolute; VS Code variables like ${workspaceFolder} are NOT substituted +# here. The Spack-specific absolute paths only exist inside the phlex-dev +# devcontainer and are harmless no-ops elsewhere. +extraPaths = [ + "plugins/python/python", + "scripts", + "build/_deps", + "out/build/*/_deps", + "/opt/spack-environments/phlex-ci/.spack-env/view/lib/root", + "/opt/spack-environments/phlex-ci/.spack-env/view/lib/python/site-packages", + "/spack/lib/spack", +] + [tool.ruff] target-version = "py312" From 56032a55977e493a19dd7dfb864f64885eb47be6 Mon Sep 17 00:00:00 2001 From: Chris Green Date: Thu, 23 Jul 2026 14:06:27 -0500 Subject: [PATCH 3/7] build(devcontainer): move Kilo config rewriting to global profile script Relocate the logic for rewriting Kilo's `baseURL` from `post-create.sh` to a dedicated script in `/etc/profile.d/`. This ensures that `KILO_CONFIG_CONTENT` is correctly exported for all shells and processes within the container runtime, rather than only being appended to `.bashrc` during container creation. --- .devcontainer/Dockerfile | 4 ++++ .devcontainer/kilo-env.sh | 22 ++++++++++++++++++++++ .devcontainer/post-create.sh | 30 +----------------------------- 3 files changed, 27 insertions(+), 29 deletions(-) create mode 100644 .devcontainer/kilo-env.sh diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 638049a03..48dff14a2 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -117,3 +117,7 @@ RUN mkdir -p /run/user/0 && chmod 700 /run/user/0 && chown root:root /run/user/0 COPY gitignore-global /root/.gitignore-global RUN git config --global core.excludesfile '/root/.gitignore-global' + +# Install Kilo environment script that sets KILO_CONFIG_CONTENT globally +COPY .devcontainer/kilo-env.sh /etc/profile.d/kilo-env.sh +RUN chmod +x /etc/profile.d/kilo-env.sh diff --git a/.devcontainer/kilo-env.sh b/.devcontainer/kilo-env.sh new file mode 100644 index 000000000..6184a4c16 --- /dev/null +++ b/.devcontainer/kilo-env.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +# Prepare KILO_CONFIG_CONTENT with rewritten headroom base URLs for container runtime. +# This script is sourced by /etc/profile.d/ so the variable is available to all processes. + +# Unset any previous KILO_CONFIG_CONTENT to ensure a clean slate. +unset KILO_CONFIG_CONTENT + +# If the headroom proxy ports (9797, 9798) are active via socat relays, +# Kilo needs a modified config with baseURL pointing to host.docker.internal. +# Parse the host config, rewrite baseURLs, and export as KILO_CONFIG_CONTENT. +if command -v kilo >/dev/null 2>&1 && command -v jq >/dev/null 2>&1; then + # Only rewrite if we have a working Kilo config to work with. + KILO_CONFIG_CONTENT="$(perl -pe 's{("(?:[^"\\]|\\.)*"|'"'"'(?:[^'"'"'\\]|\\.)*'"'"')|//.*}{$1 // ""}ge' "${HOME}/.config/kilo/kilo.jsonc" | jq -c '.provider |= with_entries( + .value.options.baseURL = + (if .value.options.baseURL == null then null + elif (.value.options.baseURL | test("^https?://127\\.0\\.0\\.1:")) + then (.value.options.baseURL | capture("https?://127\\.0\\.0\\.1:(?[0-9]+)(?.*)") | "http://host.docker.internal:" + ((.port | tonumber + 10000) | tostring) + .rest) + else .value.options.baseURL + end) + )')" + export KILO_CONFIG_CONTENT +fi diff --git a/.devcontainer/post-create.sh b/.devcontainer/post-create.sh index 59dc9ed40..5da240287 100755 --- a/.devcontainer/post-create.sh +++ b/.devcontainer/post-create.sh @@ -92,32 +92,4 @@ elif command -v pre-commit >/dev/null 2>&1; then pre-commit install || true fi -# Configure Kilo to use host.docker.internal for headroom proxy ports. -# The headroom SSH tunnels bind to 127.0.0.1 only, but rootless Podman's -# pasta networking only routes host.docker.internal to ports listening on -# 0.0.0.0. We use socat relays (set up in ensure-repos.sh) to forward -# 127.0.0.1:9797 -> 0.0.0.0:19797 and 127.0.0.1:9798 -> 0.0.0.0:19798. -# This code rewrites Kilo's baseURL from 127.0.0.1: to -# host.docker.internal: for the relays to work. -cat >> /root/.bashrc <<'EOF' - -# Unset any previous KILO_CONFIG_CONTENT to ensure a clean slate. -unset KILO_CONFIG_CONTENT - -# If the headroom proxy ports (9797, 9798) are active via socat relays, -# Kilo needs a modified config with baseURL pointing to host.docker.internal. -# Parse 'kilo debug config', rewrite baseURLs, and export as KILO_CONFIG_CONTENT. -if command -v kilo >/dev/null 2>&1 && command -v jq >/dev/null 2>&1; then - # Only rewrite if we have a working Kilo config to work with. - if KILO_CONFIG_CONTENT="$(perl -pe 's{("(?:[^"\\]|\\.)*"|'"'"'(?:[^'"'"'\\]|\\.)*'"'"')|//.*}{$1 // ""}ge' "${HOME}/.config/kilo/kilo.jsonc" | jq -c '.provider |= with_entries( - .value.options.baseURL = - (if .value.options.baseURL == null then null - elif (.value.options.baseURL | test("^https?://127\\.0\\.0\\.1:")) - then (.value.options.baseURL | capture("https?://127\\.0\\.0\\.1:(?[0-9]+)(?.*)") | "http://host.docker.internal:" + ((.port | tonumber + 10000) | tostring) + .rest) - else .value.options.baseURL - end) - )')"; then - export KILO_CONFIG_CONTENT - fi -fi -EOF +# KILO configuration now provided by /etc/profile.d/kilo-env.sh From d9bb6cc929b9b830d92f48f6332a265a2d69bad4 Mon Sep 17 00:00:00 2001 From: Chris Green Date: Thu, 23 Jul 2026 15:38:50 -0500 Subject: [PATCH 4/7] build(devcontainer): pin base image and fix Kilo config mount Pin the `phlex-dev` base image to a specific date tag to ensure build reproducibility. Additionally: - Fix the path for `kilo-env.sh` in the Dockerfile to remove the unnecessary `.devcontainer/` prefix during the COPY command. - Remove the read-only (`ro`) flag from the Kilo configuration mount in `docker-compose.yml` to allow the environment script to modify the configuration within the container. --- .devcontainer/Dockerfile | 4 ++-- .devcontainer/docker-compose.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 48dff14a2..f778fba6f 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,4 +1,4 @@ -FROM ghcr.io/framework-r-d/phlex-dev:latest +FROM ghcr.io/framework-r-d/phlex-dev:2026-07-23 # Validate Python site-packages symlink. # Invoke bash explicitly: the script uses bash features (pipefail, arrays, @@ -119,5 +119,5 @@ COPY gitignore-global /root/.gitignore-global RUN git config --global core.excludesfile '/root/.gitignore-global' # Install Kilo environment script that sets KILO_CONFIG_CONTENT globally -COPY .devcontainer/kilo-env.sh /etc/profile.d/kilo-env.sh +COPY kilo-env.sh /etc/profile.d/kilo-env.sh RUN chmod +x /etc/profile.d/kilo-env.sh diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index 806a8a096..129ac8909 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -12,7 +12,7 @@ services: - ../../phlex-examples:/workspaces/phlex-examples:Z - ../../phlex-spack-recipes:/workspaces/phlex-spack-recipes:Z - ${HOME}/.config/gh:/root/.config/gh:ro,Z - - ${HOME}/.config/kilo:/root/.config/kilo:ro,Z + - ${HOME}/.config/kilo:/root/.config/kilo:Z - ${HOME}/.gnupg:/root/.gnupg:ro,Z - ${HOME}/.podman-proxy/podman.sock:/tmp/podman.sock:Z - phlex-kilo-data:/root/.local/share/kilo:Z From 4e3ae7e8cbdc75950c5509161bcbb3264285c2ee Mon Sep 17 00:00:00 2001 From: Chris Green Date: Fri, 24 Jul 2026 14:36:10 -0500 Subject: [PATCH 5/7] build(devcontainer): enable and configure VS Code Agent sandbox Changed from disabling the sandbox entirely to enabling it with network access allowed and weaker nested sandbox disabled for security. This aligns with the global Kilo configuration which requires sandbox enabled for proper Agent Manager operation. --- .devcontainer/devcontainer.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 26aef4c19..3386d6e0c 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -13,7 +13,11 @@ "customizations": { "vscode": { "settings": { - "chat.agent.sandbox.enabled": "off", + "chat.agent.sandbox.enabled": "on", + "chat.agent.sandbox.allowNetwork": true, + "chat.agent.sandbox.advanced.runtime": { + "enableWeakerNestedSandbox": false + }, "cmake.buildDirectory": "${workspaceFolder}/build", "cmake.defaultConfigurePreset": "default", "cmake.generator": "Ninja", From 35e1c5cc2aa0296353ffec813150118c068fc708 Mon Sep 17 00:00:00 2001 From: Chris Green Date: Fri, 24 Jul 2026 14:48:17 -0500 Subject: [PATCH 6/7] build(devcontainer): track failed repo clones and exit with error Track repositories that fail to clone (non-repository files in place or checkout failures) in an array, and exit non-zero with a summary listing all failed repositories. This ensures failed companion repository clones are detected as build failures rather than silently ignored. --- .devcontainer/setup-repos.sh | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.devcontainer/setup-repos.sh b/.devcontainer/setup-repos.sh index 9086edc6e..164327fcc 100755 --- a/.devcontainer/setup-repos.sh +++ b/.devcontainer/setup-repos.sh @@ -1,17 +1,17 @@ #!/bin/bash - # Clone companion repositories into the codespace so they are available # for reference by developers and AI agents. # # Intended to be called from devcontainer.json onCreateCommand. WORKSPACE_ROOT="${1:-/workspaces}" - if [ ! -d "$WORKSPACE_ROOT" ]; then echo "Error: workspace root does not exist: $WORKSPACE_ROOT" >&2 exit 1 fi +FAILED_REPOS=() + clone_if_absent() { local repo=$1 local dest="${WORKSPACE_ROOT}/${repo}" @@ -22,6 +22,7 @@ clone_if_absent() { elif [ -e "$dest" ]; then echo "WARNING: refusing to overwrite non-repository $dest:" ls -ld "$dest" + FAILED_REPOS+=("$repo") return 1 fi if (( need_clone )); then @@ -35,6 +36,7 @@ clone_if_absent() { done if (( current_try == max_tries )); then echo "WARNING: unable to check out $repo to $dest from GitHub" 1>&2 + FAILED_REPOS+=("$repo") return 1 fi fi @@ -46,4 +48,7 @@ clone_if_absent phlex-examples clone_if_absent phlex-coding-guidelines clone_if_absent phlex-spack-recipes -exit 0 +if (( ${#FAILED_REPOS[@]} > 0 )); then + echo "Error: Failed to clone repositories: ${FAILED_REPOS[*]}" >&2 + exit 1 +fi From baac50f3832dbfffb747197f6116a6cae1df9b42 Mon Sep 17 00:00:00 2001 From: Chris Green Date: Fri, 24 Jul 2026 14:56:45 -0500 Subject: [PATCH 7/7] chore(pyright): replace VS Code workspace settings with pyproject.toml config Move Pyright configuration from .devcontainer/codespace.code-workspace and .devcontainer/devcontainer.json to pyproject.toml. The workspace-level settings are redundant since Pyright now reads configuration from the root pyproject.toml file. The changes: - Remove duplicate python.analysis.* settings from devcontainer configs - Add pyproject.toml sections: diagnosticMode, extraPaths, exclude, ignore typeCheckingMode - Update extraPaths to use specific build preset directories (default clang-tidy) instead of wildcard pattern --- .devcontainer/codespace.code-workspace | 34 -------------------------- .devcontainer/devcontainer.json | 22 ----------------- pyproject.toml | 19 +++++++++++--- 3 files changed, 16 insertions(+), 59 deletions(-) diff --git a/.devcontainer/codespace.code-workspace b/.devcontainer/codespace.code-workspace index e8d72fbf9..81a554751 100644 --- a/.devcontainer/codespace.code-workspace +++ b/.devcontainer/codespace.code-workspace @@ -73,40 +73,6 @@ // scope overrides this Workspace scope) -- see // .vscode/settings.json.example. "esbonio.logging.level": "debug", - "python.analysis.typeCheckingMode": "basic", - "python.analysis.diagnosticMode": "workspace", - "python.analysis.include": [ - "${workspaceFolder:Phlex}" - ], - "python.analysis.extraPaths": [ - "${workspaceFolder:Phlex}/plugins/python/python", - "${workspaceFolder:Phlex}/scripts", - "${workspaceFolder:Phlex}/build/_deps", - "${workspaceFolder:Phlex}/out/build/*/_deps", - "/opt/spack-environments/phlex-ci/.spack-env/view/lib/root", - "/opt/spack-environments/phlex-ci/.spack-env/view/lib/python/site-packages", - "/spack/lib/spack" - ], - "python.analysis.exclude": [ - "/opt/spack-environments", - "${workspaceFolder:Phlex}/local", - "${workspaceFolder:Phlex}/build/_deps", - "${workspaceFolder:Phlex}/build/CMakeFiles", - "${workspaceFolder:Phlex}/**/.venv", - "${workspaceFolder:Phlex}/**/py_virtual_env" - ], - "python.analysis.ignore": [ - "/opt/spack-environments", - "${workspaceFolder:Phlex Design}", - "${workspaceFolder:Phlex Examples}", - "${workspaceFolder:Phlex Coding Guidelines}", - "${workspaceFolder:Phlex Spack Recipes}", - "${workspaceFolder:Phlex}/local", - "${workspaceFolder:Phlex}/build/_deps", - "${workspaceFolder:Phlex}/build/CMakeFiles", - "${workspaceFolder:Phlex}/**/.venv", - "${workspaceFolder:Phlex}/**/py_virtual_env" - ], "flake8.enabled": false, "pylint.enabled": false, "[python]": { diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 3386d6e0c..ce8ebdc57 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -40,28 +40,6 @@ "/workspaces/phlex-spack-recipes" ], "kilocode.new.extraCaCerts": "", - "python.analysis.diagnosticMode": "workspace", - "python.analysis.exclude": [ - "**/.venv/**", - "**/py_virtual_env/**", - "**/build/_deps/**", - "**/out/build/*/_deps/**" - ], - "python.analysis.ignore": [ - "**/.venv/**", - "**/py_virtual_env/**" - ], - "python.analysis.extraPaths": [ - "${workspaceFolder}/plugins/python/python", - "${workspaceFolder}/scripts", - "${workspaceFolder}/build", - "${workspaceFolder}/build/_deps", - "${workspaceFolder}/out/build/*/_deps", - "/opt/spack-environments/phlex-ci/.spack-env/view/lib/root", - "/opt/spack-environments/phlex-ci/.spack-env/view/lib/python/site-packages", - "/spack/lib/spack" - ], - "python.analysis.typeCheckingMode": "basic", "python.defaultInterpreterPath": "/opt/spack-environments/phlex-ci/.spack-env/view/bin/python", "python.languageServer": "Pylance", "python.terminal.activateEnvironment": false, diff --git a/pyproject.toml b/pyproject.toml index 0b29feb05..d860642a3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,16 +16,29 @@ disable_error_code = "annotation-unchecked" # absolute; VS Code variables like ${workspaceFolder} are NOT substituted # here. The Spack-specific absolute paths only exist inside the phlex-dev # devcontainer and are harmless no-ops elsewhere. + +diagnosticMode = "workspace" extraPaths = [ "plugins/python/python", "scripts", "build/_deps", - "out/build/*/_deps", + "out/build/default/_deps", + "out/build/clang-tidy/_deps", "/opt/spack-environments/phlex-ci/.spack-env/view/lib/root", "/opt/spack-environments/phlex-ci/.spack-env/view/lib/python/site-packages", - "/spack/lib/spack", + "/spack/lib/spack" ] - +exclude = [ + "**/.venv/**", + "**/py_virtual_env/**", + "**/build/_deps/**", + "**/out/build/*/_deps/**" +] +ignore = [ + "**/.venv/**", + "**/py_virtual_env/**" +] +typeCheckingMode = "basic" [tool.ruff] target-version = "py312"