From 1a6256f3d892f4ebbe73c0f0552a0cd5ebe45a1c Mon Sep 17 00:00:00 2001 From: jean-baptiste Date: Fri, 22 May 2026 13:32:03 +0200 Subject: [PATCH 1/4] chore: add Taskfile.yaml as standard task entrypoint Wraps npm scripts under task(1) with named tasks (install, dev, build, test, lint, check, ci, clean, db:reset, install:lint). Updates README with a Tooling section documenting the preferred workflow. --- README.md | 37 ++++++++++++++++++---- Taskfile.yaml | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+), 7 deletions(-) create mode 100644 Taskfile.yaml diff --git a/README.md b/README.md index 3d23a6da..f07b5047 100644 --- a/README.md +++ b/README.md @@ -78,14 +78,38 @@ Grab the latest release for your platform: - **Linux**: `build-essential`, `python3` (`sudo apt install build-essential python3`) - **Windows**: Visual Studio Build Tools or `npm install -g windows-build-tools` +## Tooling + +[task](https://taskfile.dev) is the preferred entrypoint for all dev operations. Install it once (`brew install go-task` / `snap install task --classic` / see taskfile.dev for other platforms), then: + +```bash +task install # npm install +task dev # launch Electron (--no-sandbox, required on Linux) +task test # node --test (24 tests) +task lint # eslint . +task check # test + lint — pre-commit / pre-push gate +task ci # same as check but sequential, verbose +task build # npm run build:linux +task clean # wipe dist/, codemirror bundle, local DB (asks for confirmation) +task db:reset # wipe ~/.switchboard/switchboard.db only +``` + +Run `task` (no args) to list all tasks with descriptions. + +The npm scripts are still present and work as before; `task` just wraps them as a consistent entrypoint. + ## Development Setup ```bash -# Install dependencies (runs postinstall automatically) -npm install +task install # install dependencies (runs postinstall automatically) +task dev # launch Electron +``` -# Start the app -npm start +Or with npm directly: + +```bash +npm install +npm start # bundles CodeMirror then launches Electron ``` `npm start` bundles CodeMirror and launches Electron. For faster iteration after the first run: @@ -99,10 +123,9 @@ npm run electron All build commands bundle CodeMirror first, then invoke electron-builder. ```bash -# Current platform -npm run build +task build # AppImage + deb (Linux) -# Platform-specific +# npm equivalents: npm run build:mac # DMG + zip (arm64 + x64) npm run build:win # NSIS installer (x64 + arm64) npm run build:linux # AppImage + deb (x64 + arm64) diff --git a/Taskfile.yaml b/Taskfile.yaml new file mode 100644 index 00000000..7d0b7236 --- /dev/null +++ b/Taskfile.yaml @@ -0,0 +1,88 @@ +# https://taskfile.dev + +version: "3" + +set: [pipefail] + +vars: + SWITCHBOARD_DB: "{{.HOME}}/.switchboard/switchboard.db" + +tasks: + default: + desc: List all available tasks + silent: true + cmds: + - task --list + + install: + desc: Install npm dependencies + cmds: + - npm install + + dev: + desc: Launch Switchboard in development mode (Electron, no-sandbox) + silent: true + cmds: + - npx electron . --no-sandbox + + build: + desc: Build Linux distribution packages (AppImage + deb) + silent: true + cmds: + - npm run build:linux + + test: + desc: Run the node:test suite (24 tests) + cmds: + - npm test + + lint: + desc: Run ESLint across the codebase + cmds: + - | + if [ ! -f eslint.config.js ] && [ ! -f .eslintrc.js ] && [ ! -f .eslintrc.json ] && [ ! -f .eslintrc.yaml ] && [ ! -f .eslintrc.yml ]; then + echo "ESLint not yet configured; run \`task install:lint\` first" + exit 1 + fi + npx eslint . + + "install:lint": + desc: Install ESLint + jsdom dev deps (idempotent) + cmds: + - | + MISSING="" + node -e "require('eslint')" 2>/dev/null || MISSING="$MISSING eslint" + node -e "require('jsdom')" 2>/dev/null || MISSING="$MISSING jsdom" + if [ -n "$MISSING" ]; then + npm install --save-dev $MISSING + else + echo "ESLint and jsdom already installed — nothing to do." + fi + + check: + desc: Run tests + lint (pre-commit / pre-push gate) + deps: [test, lint] + + ci: + desc: CI gate — runs test then lint, verbose, exits on first failure + cmds: + - npm test + - npx eslint . + + clean: + desc: Remove dist/, codemirror bundle, and local DB (asks for confirmation) + interactive: true + cmds: + - | + read -p "This will delete dist/, public/codemirror-bundle.js, and {{.SWITCHBOARD_DB}}. Type YES to confirm: " ans + [ "$ans" = "YES" ] + - rm -rf dist/ + - rm -f public/codemirror-bundle.js + - rm -f "{{.SWITCHBOARD_DB}}" + - echo "Clean complete." + + "db:reset": + desc: Wipe the local Switchboard SQLite database (no confirmation) + cmds: + - rm -f "{{.SWITCHBOARD_DB}}" + - echo "Removed {{.SWITCHBOARD_DB}}" From 8314f6925a44a64108e2dd175eb7d6ed06be4168 Mon Sep 17 00:00:00 2001 From: jean-baptiste Date: Fri, 22 May 2026 13:30:03 +0200 Subject: [PATCH 2/4] test(lint): add ESLint flat config + jsdom renderer tests for sidebar MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Layer 1 — ESLint 9 flat config (eslint.config.js) with no-undef enforced on renderer (public/*.js) and main-process files. Verified statically catches the two recent sidebar.js regressions: - undeclared subagentIndex in renderProjects destructure - out-of-scope projectPath in buildSessionsList orphan branch Wired via "lint" + "pretest" scripts; npm test now lints first. Layer 2 — jsdom-backed renderer tests (test/dom-setup.js, test/dom-sidebar.test.js): - bootstraps a JSDOM window, evaluates utils.js / icons.js / sidebar.js in its VM context, stubs cross-file globals (window.api, sessionMap, activePtyIds, etc.) - sample fixture: 2 top-level sessions, 3 subagents (1 orphan), 1 starred, 1 archived - 7 tests covering: structural completeness, starred/archived classes, subagent carets, orphan group, projectPath localStorage key, empty project, idempotent re-render Both bug-class regressions are now caught at lint time AND runtime. Existing 24+ tests still green (npm test → 32 pass). Notes: - Pre-existing no-unused-vars / no-redeclare warnings (204) left as warnings, not errors; not in scope. - One stray no-undef (_shellProfiles in main.js) annotated with eslint-disable + TODO; appears to be dead code from a refactor. --- eslint.config.js | 305 +++++++ main.js | 4 + package-lock.json | 1748 ++++++++++++++++++++++++++++---------- package.json | 5 + test/dom-setup.js | 195 +++++ test/dom-sidebar.test.js | 146 ++++ 6 files changed, 1963 insertions(+), 440 deletions(-) create mode 100644 eslint.config.js create mode 100644 test/dom-setup.js create mode 100644 test/dom-sidebar.test.js diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 00000000..81ede521 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,305 @@ +// ESLint flat config for Switchboard (ESLint 9.x). +// +// Goals: +// 1. Catch dumb "undefined variable" mistakes in renderer code +// (no-undef). Two recent regressions in public/sidebar.js +// (subagentIndex undefined; project.projectPath out of scope) +// would have been caught instantly by this rule. +// 2. Warn about unused vars without blocking the build. +// 3. Keep the existing 24+ node:test suite green. +// +// The renderer (public/*.js) loads as a set of classic