Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ frontend/.vite/
!/.vscode/launch.json
!/.vscode/tasks.json

# VS Code plugin experiment (belongs on exp/vscode-plugin, not main)
switchbay.code-workspace
extensions/switchbay/
extensions/switchbay-sketch/

# ── vscode plugin compiled output (source under extensions/ is tracked) ──
extensions/**/out/
extensions/**/media/graph/
Expand Down
20 changes: 0 additions & 20 deletions extensions/switchbay-sketch/README.md

This file was deleted.

25 changes: 0 additions & 25 deletions extensions/switchbay-sketch/package.json

This file was deleted.

1 change: 1 addition & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/switchbay/ce_toolscope.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ def fs_rules(workspace: Path) -> list[str]:
log.exception("skill read-scope failed")
try:
mirrors = Path(workspace).resolve() / ".workbench" / "skill-mirrors"
rules.append(f"Read({mirrors}/**)")
rules.append(f"Read({mirrors.as_posix()}/**)")
except OSError:
pass
return _dedup(rules)
Expand Down
7 changes: 5 additions & 2 deletions src/switchbay/kernel/harness_pi.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,11 @@ def pi_argv(req: NodeRequest, *, binary: str, ext: Path) -> list[str]:

def _killpg(proc: asyncio.subprocess.Process, sig: int = signal.SIGTERM) -> None:
try:
os.killpg(proc.pid, sig)
except (ProcessLookupError, PermissionError, OSError):
if hasattr(os, "killpg") and proc.pid is not None:
os.killpg(proc.pid, sig)
elif proc.returncode is None:
proc.kill()
except (ProcessLookupError, PermissionError, OSError, AttributeError):
try:
proc.kill()
except Exception: # noqa: BLE001
Expand Down
4 changes: 4 additions & 0 deletions src/switchbay/kernel/hire.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,9 +222,13 @@ def pair(r: dict[str, Any]) -> tuple[str, str | None]:
pool = others or allowed
if s <= 0.25:
# Cheapest (local / flash / mini). Strength 0 is local.
# Prefer independence from the chief's provider on ties so
# Economy workers burn gemini/mlx flash-class rather than
# anthropic haiku when both score the same.
chosen = min(pool, key=lambda r: (
0 if r.get("local") else 1,
float(r.get("strength") or 0),
1 if str(r.get("provider")) == chief_pid else 0,
))
elif s >= 0.8:
# Strong but leave the very top for the kernel when possible.
Expand Down
43 changes: 0 additions & 43 deletions switchbay.code-workspace

This file was deleted.

8 changes: 4 additions & 4 deletions tests/unit/test_ce_toolscope.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,9 @@ def test_fs_rules_allow_reading_any_discovered_skill(tmp_path, monkeypatch):
monkeypatch.setattr(
"switchbay.skillkit.cebridge.ce_root", lambda: tmp_path / "no-ce")
rules = ce_toolscope.fs_rules(ws)
assert any(str(user) in r and r.startswith("Read(") for r in rules)
assert any(user.as_posix() in r and r.startswith("Read(") for r in rules)
mirrors = ws.resolve() / ".workbench" / "skill-mirrors"
assert any(str(mirrors) in r for r in rules)
assert any(mirrors.as_posix() in r for r in rules)


def test_write_scope_is_curation_dirs_only(fake_ce):
Expand Down Expand Up @@ -121,5 +121,5 @@ def test_rules_render_both_symlink_forms(tmp_path, monkeypatch):
monkeypatch.setattr(
ce_toolscope, "skill_roots", lambda _ws: [logical, physical])
prefixes = ce_toolscope.command_prefixes(ws)
assert any(str(logical) in p for p in prefixes)
assert any(str(physical) in p for p in prefixes)
assert any(logical.as_posix() in p for p in prefixes)
assert any(physical.as_posix() in p for p in prefixes)
18 changes: 13 additions & 5 deletions tests/unit/test_kernel_harness.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

from __future__ import annotations

import os
import sys
from pathlib import Path

import pytest
Expand Down Expand Up @@ -50,8 +52,13 @@ async def test_grok_harness_runs_curator_package(tmp_path: Path, monkeypatch):


@pytest.mark.asyncio
@pytest.mark.skipif(
sys.platform == "win32",
reason="fake Pi probe uses select.select on stdin; Windows select is sockets-only",
)
async def test_pi_rpc_keeps_stdin_open_until_settled(tmp_path: Path, monkeypatch):
"""EOF on Pi stdin aborts the model turn; the harness must not close early."""
import os
import sys
script = tmp_path / "fake_pi.py"
script.write_text(
Expand Down Expand Up @@ -157,8 +164,9 @@ def test_spawn_env_pythonpath_is_absolute(tmp_path: Path):
provider_id="xai", model="grok-4.5", workspace=tmp_path,
)
env = spawn_env(req)
assert env["PYTHONPATH"].endswith("/src")
assert env["PYTHONPATH"].startswith("/")
src_path = Path(env["PYTHONPATH"])
assert src_path.name == "src"
assert src_path.is_absolute()
assert env["SWITCHBAY_SRC"] == env["PYTHONPATH"]
assert "ce_wave_prime" in env["SWITCHBAY_PACKAGE_TOOLS"].split(",")
assert env["SWITCHBAY_PACKAGE_ID"] == CURATOR_ID
Expand Down Expand Up @@ -287,10 +295,10 @@ def test_spawn_env_path_includes_homebrew(tmp_path: Path, monkeypatch):
from switchbay.kernel.harness_pi import enrich_path, shebang_wants_node
brew = tmp_path / "opt" / "homebrew" / "bin"
brew.mkdir(parents=True)
env = {"PATH": "/usr/bin:/bin"}
env = {"PATH": os.pathsep.join(["/usr/bin", "/bin"])}
enrich_path(env, extra_dirs=(str(brew),))
assert str(brew) in env["PATH"].split(":")
assert env["PATH"].startswith(str(brew))
assert str(brew) in env["PATH"].split(os.pathsep)
assert env["PATH"].split(os.pathsep)[0] == str(brew)
script = tmp_path / "pi"
script.write_text("#!/usr/bin/env node\nconsole.log(1)\n", encoding="utf-8")
assert shebang_wants_node(str(script)) is True
Expand Down
3 changes: 2 additions & 1 deletion tests/unit/test_version_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from __future__ import annotations

import json
import os
import re
import subprocess
import sys
Expand Down Expand Up @@ -54,6 +55,6 @@ def test_reported_version_is_the_running_one():
[sys.executable, "-c",
"from switchbay import updater; print(updater.local_switchbay_version())"],
capture_output=True, text=True, check=True, cwd=REPO,
env={"PYTHONPATH": str(REPO / "src"), "PATH": "/usr/bin:/bin"},
env={**os.environ, "PYTHONPATH": str(REPO / "src")},
)
assert out.stdout.strip() == _pyproject_version()
Loading