From 8ed0d89b6325f1a75a3afd01690d859270fcb7ad Mon Sep 17 00:00:00 2001 From: saagar210 Date: Mon, 16 Feb 2026 01:49:31 -0800 Subject: [PATCH 1/4] feat(dev): add lean development and cleanup workflows - Add a lean dev entrypoint that uses temporary cache paths and cleans up on exit - Add targeted and full cleanup scripts for reproducible local artifacts - Make Vite/Tauri dev port and Vite cache path configurable for safe local overrides - Document normal vs lean dev flow and cleanup tradeoffs in README Tests: npm run lint && npm run build --- README.md | 38 ++++++++++++++++++++++++++++++++++++++ package.json | 5 ++++- scripts/cleanup-full.sh | 20 ++++++++++++++++++++ scripts/cleanup-heavy.sh | 19 +++++++++++++++++++ scripts/lean-dev.sh | 36 ++++++++++++++++++++++++++++++++++++ src-tauri/tauri.conf.json | 2 +- vite.config.ts | 11 +++++++++-- 7 files changed, 127 insertions(+), 4 deletions(-) create mode 100755 scripts/cleanup-full.sh create mode 100755 scripts/cleanup-heavy.sh create mode 100755 scripts/lean-dev.sh diff --git a/README.md b/README.md index a437270..6935867 100644 --- a/README.md +++ b/README.md @@ -39,10 +39,48 @@ npm install # Run in development mode npm run tauri dev +# Run in low-disk lean development mode +npm run dev:lean + # Build for production npm run tauri build ``` +### Normal Dev vs Lean Dev + +- **Normal dev (`npm run tauri dev`)** + - Fastest repeated startup once Rust and frontend caches are warm. + - Uses persistent local build artifacts (for example `src-tauri/target`, Vite cache in `node_modules/.vite`). +- **Lean dev (`npm run dev:lean`)** + - Runs the same Tauri dev flow, but moves heavy build caches to temporary locations. + - Automatically removes heavy build artifacts when you exit. + - Uses less persistent disk space, but startup/rebuild can be slower. + +### Cleanup Commands + +- **Targeted heavy cleanup** (keeps dependencies for speed): + +```bash +npm run clean:heavy +``` + +Removes only heavy build artifacts: +- `dist` +- `src-tauri/target` +- `node_modules/.vite` + +- **Full local reproducible cleanup** (maximum space recovery): + +```bash +npm run clean:full +``` + +Removes: +- `dist` +- `src-tauri/target` +- `node_modules/.vite` +- `node_modules` (recreated by `npm install`) + ### First Connection 1. Click "Add" in the sidebar to create a connection diff --git a/package.json b/package.json index 86ea2fd..c25efa9 100644 --- a/package.json +++ b/package.json @@ -5,12 +5,15 @@ "type": "module", "scripts": { "dev": "vite", + "dev:lean": "./scripts/lean-dev.sh", "build": "tsc && vite build", "preview": "vite preview", "lint": "tsc --noEmit", "lint:fix": "eslint . --fix && prettier --write .", "format": "prettier --write .", - "tauri": "tauri" + "tauri": "tauri", + "clean:heavy": "./scripts/cleanup-heavy.sh", + "clean:full": "./scripts/cleanup-full.sh" }, "dependencies": { "@dagrejs/dagre": "^2.0.3", diff --git a/scripts/cleanup-full.sh b/scripts/cleanup-full.sh new file mode 100755 index 0000000..6c71c25 --- /dev/null +++ b/scripts/cleanup-full.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd -- "${SCRIPT_DIR}/.." && pwd)" +cd "$REPO_ROOT" + +paths=( + "dist" + "src-tauri/target" + "node_modules/.vite" + "node_modules" +) + +for path in "${paths[@]}"; do + if [ -e "$path" ]; then + rm -rf "$path" + echo "removed $path" + fi +done diff --git a/scripts/cleanup-heavy.sh b/scripts/cleanup-heavy.sh new file mode 100755 index 0000000..82aeeec --- /dev/null +++ b/scripts/cleanup-heavy.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd -- "${SCRIPT_DIR}/.." && pwd)" +cd "$REPO_ROOT" + +paths=( + "dist" + "src-tauri/target" + "node_modules/.vite" +) + +for path in "${paths[@]}"; do + if [ -e "$path" ]; then + rm -rf "$path" + echo "removed $path" + fi +done diff --git a/scripts/lean-dev.sh b/scripts/lean-dev.sh new file mode 100755 index 0000000..9d84140 --- /dev/null +++ b/scripts/lean-dev.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd -- "${SCRIPT_DIR}/.." && pwd)" +cd "$REPO_ROOT" + +LEAN_TMP_ROOT="$(mktemp -d -t dbviz-lean-dev-XXXXXX)" +LEAN_CARGO_TARGET_DIR="$LEAN_TMP_ROOT/cargo-target" +LEAN_VITE_CACHE_DIR="$LEAN_TMP_ROOT/vite-cache" +LEAN_DEV_PORT="${LEAN_DEV_PORT:-1420}" + +mkdir -p "$LEAN_CARGO_TARGET_DIR" "$LEAN_VITE_CACHE_DIR" + +cleanup() { + local exit_code=$? + + if [ -d "$LEAN_TMP_ROOT" ]; then + rm -rf "$LEAN_TMP_ROOT" + fi + + npm run clean:heavy >/dev/null 2>&1 || true + + exit "$exit_code" +} +trap cleanup EXIT INT TERM + +export CARGO_TARGET_DIR="$LEAN_CARGO_TARGET_DIR" +export VITE_CACHE_DIR="$LEAN_VITE_CACHE_DIR" +export TAURI_DEV_PORT="$LEAN_DEV_PORT" + +echo "[lean-dev] temporary cargo target: $CARGO_TARGET_DIR" +echo "[lean-dev] temporary vite cache: $VITE_CACHE_DIR" +echo "[lean-dev] tauri dev port: $TAURI_DEV_PORT" + +npm run tauri dev -- --port "$TAURI_DEV_PORT" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 4c378b3..a8616df 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -4,7 +4,7 @@ "version": "0.1.0", "identifier": "com.dbviz.app", "build": { - "beforeDevCommand": "npm run dev", + "beforeDevCommand": "npm run dev -- --port ${TAURI_DEV_PORT:-1420}", "devUrl": "http://localhost:1420", "beforeBuildCommand": "npm run build", "frontendDist": "../dist" diff --git a/vite.config.ts b/vite.config.ts index 2f56295..eeae9fe 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -5,6 +5,12 @@ import { resolve } from "path"; // @ts-expect-error process is a nodejs global const host = process.env.TAURI_DEV_HOST; +// @ts-expect-error process is a nodejs global +const envPort = Number(process.env.TAURI_DEV_PORT || process.env.PORT || "1420"); +const port = Number.isFinite(envPort) ? envPort : 1420; +const hmrPort = port + 1; +// @ts-expect-error process is a nodejs global +const cacheDir = process.env.VITE_CACHE_DIR || "node_modules/.vite"; export default defineConfig(async () => ({ plugins: [react(), tailwindcss()], @@ -14,15 +20,16 @@ export default defineConfig(async () => ({ }, }, clearScreen: false, + cacheDir, server: { - port: 1420, + port, strictPort: true, host: host || false, hmr: host ? { protocol: "ws", host, - port: 1421, + port: hmrPort, } : undefined, watch: { From b1034d4b56f5b51668eca2f4b3e0e44633a553c0 Mon Sep 17 00:00:00 2001 From: saagar210 Date: Mon, 16 Feb 2026 21:35:47 -0800 Subject: [PATCH 2/4] chore(codex): bootstrap tests and docs defaults --- .codex/bootstrap/tests-docs.v1.json | 17 ++++++++++ .codex/prompts/test-critic.md | 14 ++++++++ .codex/scripts/run_verify_commands.sh | 21 ++++++++++++ .codex/verify.commands | 7 ++++ .github/workflows/quality-gates.yml | 46 +++++++++++++++++++++++++++ AGENTS.md | 13 ++++++++ docs/adr/0000-template.md | 16 ++++++++++ openapi/openapi.generated.json | 9 ++++++ scripts/ci/require-tests-and-docs.mjs | 41 ++++++++++++++++++++++++ 9 files changed, 184 insertions(+) create mode 100644 .codex/bootstrap/tests-docs.v1.json create mode 100644 .codex/prompts/test-critic.md create mode 100755 .codex/scripts/run_verify_commands.sh create mode 100644 .codex/verify.commands create mode 100644 .github/workflows/quality-gates.yml create mode 100644 AGENTS.md create mode 100644 docs/adr/0000-template.md create mode 100644 openapi/openapi.generated.json create mode 100644 scripts/ci/require-tests-and-docs.mjs diff --git a/.codex/bootstrap/tests-docs.v1.json b/.codex/bootstrap/tests-docs.v1.json new file mode 100644 index 0000000..3a6d464 --- /dev/null +++ b/.codex/bootstrap/tests-docs.v1.json @@ -0,0 +1,17 @@ +{ + "contract": "tests-docs-bootstrap-v1", + "adapter": "node-ts", + "branch": "codex/bootstrap-tests-docs-v1", + "generated_at": "2026-02-17T05:35:47.710Z", + "generated_by": "/Users/d/.codex/scripts/bootstrap/global_tests_docs_bootstrap.mjs", + "changed_files": [ + ".codex/prompts/test-critic.md", + ".codex/scripts/run_verify_commands.sh", + ".codex/verify.commands", + ".github/workflows/quality-gates.yml", + "docs/adr/0000-template.md", + "openapi/openapi.generated.json", + "scripts/ci/require-tests-and-docs.mjs", + "AGENTS.md" + ] +} diff --git a/.codex/prompts/test-critic.md b/.codex/prompts/test-critic.md new file mode 100644 index 0000000..6c29c8c --- /dev/null +++ b/.codex/prompts/test-critic.md @@ -0,0 +1,14 @@ +You are a QA Test Critic reviewing only changed files and related tests. + +Review criteria: +1. Tests assert behavior outcomes, not implementation details. +2. Each changed behavior includes edge/error/boundary coverage. +3. Mocks are used only at external boundaries. +4. UI tests cover loading/empty/error/success and disabled/focus-visible states. +5. Assertions would fail under realistic regressions. +6. Flag brittle selectors, snapshot spam, and tautological assertions. +7. Flag missing docs updates for API/command or architecture changes. + +Output: +- Emit ReviewFindingV1 findings only. +- Priority order: critical, high, medium, low. diff --git a/.codex/scripts/run_verify_commands.sh b/.codex/scripts/run_verify_commands.sh new file mode 100755 index 0000000..aef497b --- /dev/null +++ b/.codex/scripts/run_verify_commands.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +set -euo pipefail + +VERIFY_FILE="${1:-.codex/verify.commands}" +if [[ ! -f "$VERIFY_FILE" ]]; then + echo "missing verify commands file: $VERIFY_FILE" >&2 + exit 1 +fi + +failed=0 +while IFS= read -r cmd || [[ -n "$cmd" ]]; do + [[ -z "$cmd" ]] && continue + [[ "$cmd" =~ ^# ]] && continue + echo ">>> $cmd" + if ! bash -lc "$cmd"; then + failed=1 + break + fi +done < "$VERIFY_FILE" + +exit "$failed" diff --git a/.codex/verify.commands b/.codex/verify.commands new file mode 100644 index 0000000..4d72142 --- /dev/null +++ b/.codex/verify.commands @@ -0,0 +1,7 @@ +pnpm lint +pnpm typecheck +pnpm test:coverage +pnpm test:integration +pnpm test:e2e:smoke +pnpm docs:generate +pnpm docs:check diff --git a/.github/workflows/quality-gates.yml b/.github/workflows/quality-gates.yml new file mode 100644 index 0000000..0dd204e --- /dev/null +++ b/.github/workflows/quality-gates.yml @@ -0,0 +1,46 @@ +name: quality-gates + +on: + pull_request: + push: + branches: [main, master] + +jobs: + quality: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - uses: actions/setup-node@v5 + with: + node-version: 22 + + - uses: pnpm/action-setup@v4 + with: + version: 9 + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Policy checks + run: node scripts/ci/require-tests-and-docs.mjs + + - name: Verify commands + run: bash .codex/scripts/run_verify_commands.sh + + - name: Diff coverage + run: | + python -m pip install --upgrade pip diff-cover + diff-cover coverage/lcov.info --compare-branch=origin/main --fail-under=90 + + - name: Upload test artifacts on failure + if: failure() + uses: actions/upload-artifact@v4 + with: + name: test-artifacts + path: | + playwright-report/ + test-results/ + coverage/ diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..4bdead5 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,13 @@ +## Definition of Done: Tests + Docs (Blocking) + +- Any production code change must include meaningful test updates in the same PR. +- Meaningful tests must include at least: + - one primary behavior assertion + - two non-happy-path assertions (edge, boundary, invalid input, or failure mode) +- Trivial assertions are forbidden (`expect(true).toBe(true)`, snapshot-only without semantic assertions, render-only smoke tests without behavior checks). +- Mock only external boundaries (network, clock, randomness, third-party SDKs). Do not mock the unit under test. +- UI changes must cover state matrix: loading, empty, error, success, disabled, focus-visible. +- API/command surface changes must update generated contract artifacts and request/response examples. +- Architecture-impacting changes must include an ADR in `/docs/adr/`. +- Required checks are blocking when `fail` or `not-run`: lint, typecheck, tests, coverage, diff coverage, docs check. +- Reviewer -> fixer -> reviewer loop is required before merge. diff --git a/docs/adr/0000-template.md b/docs/adr/0000-template.md new file mode 100644 index 0000000..f48132d --- /dev/null +++ b/docs/adr/0000-template.md @@ -0,0 +1,16 @@ +# 0000. Title + +## Status +Proposed | Accepted | Superseded + +## Context +What problem or constraint forced this decision? + +## Decision +What was chosen? + +## Consequences +What improves, what tradeoffs are accepted, what risks remain? + +## Alternatives Considered +Option A, Option B, and why they were rejected. diff --git a/openapi/openapi.generated.json b/openapi/openapi.generated.json new file mode 100644 index 0000000..3e752f6 --- /dev/null +++ b/openapi/openapi.generated.json @@ -0,0 +1,9 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "API Contract", + "version": "1.0.0" + }, + "paths": {}, + "components": {} +} diff --git a/scripts/ci/require-tests-and-docs.mjs b/scripts/ci/require-tests-and-docs.mjs new file mode 100644 index 0000000..6509f6a --- /dev/null +++ b/scripts/ci/require-tests-and-docs.mjs @@ -0,0 +1,41 @@ +import { execSync } from 'node:child_process'; + +const defaultBaseRef = (() => { + try { + return execSync('git symbolic-ref refs/remotes/origin/HEAD', { encoding: 'utf8' }).trim().replace('refs/remotes/', ''); + } catch { + return 'origin/main'; + } +})(); + +const baseRef = process.env.GITHUB_BASE_REF ? `origin/${process.env.GITHUB_BASE_REF}` : defaultBaseRef; +const diff = execSync(`git diff --name-only ${baseRef}...HEAD`, { encoding: 'utf8' }) + .split('\n') + .map((line) => line.trim()) + .filter(Boolean); + +const isProdCode = (file) => /^(src|app|server|api)\//.test(file) && !/\.(test|spec)\.[cm]?[jt]sx?$/.test(file); +const isTest = (file) => /^tests\//.test(file) || /\.(test|spec)\.[cm]?[jt]sx?$/.test(file); +const isDoc = (file) => /^docs\//.test(file) || /^openapi\//.test(file) || file === 'README.md'; +const isApiSurface = (file) => /^(src|app|server|api)\/.*(route|controller|handler|webhook|api|command)/.test(file); +const isArchChange = (file) => /^src\/(auth|db|infra|queue|events|architecture)\//.test(file) || /^infra\//.test(file); +const isAdr = (file) => /^docs\/adr\/\d{4}-.*\.md$/.test(file); + +const prodChanged = diff.some(isProdCode); +const testsChanged = diff.some(isTest); +const apiChanged = diff.some(isApiSurface); +const docsChanged = diff.some(isDoc); +const archChanged = diff.some(isArchChange); +const adrChanged = diff.some(isAdr); + +const failures = []; +if (prodChanged && !testsChanged) failures.push('Policy failure: production code changed without test updates.'); +if (apiChanged && !docsChanged) failures.push('Policy failure: API/command changes without docs/OpenAPI updates.'); +if (archChanged && !adrChanged) failures.push('Policy failure: architecture-impacting change without ADR.'); + +if (failures.length > 0) { + for (const failure of failures) console.error(failure); + process.exit(1); +} + +console.log('Policy checks passed.'); From 2cfefa46183df2837f7724eccebd0ccd2d94d7dc Mon Sep 17 00:00:00 2001 From: saagar210 Date: Mon, 16 Feb 2026 21:38:27 -0800 Subject: [PATCH 3/4] chore(codex): bootstrap tests and docs defaults --- .codex/bootstrap/tests-docs.v1.json | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/.codex/bootstrap/tests-docs.v1.json b/.codex/bootstrap/tests-docs.v1.json index 3a6d464..666fdaf 100644 --- a/.codex/bootstrap/tests-docs.v1.json +++ b/.codex/bootstrap/tests-docs.v1.json @@ -2,16 +2,7 @@ "contract": "tests-docs-bootstrap-v1", "adapter": "node-ts", "branch": "codex/bootstrap-tests-docs-v1", - "generated_at": "2026-02-17T05:35:47.710Z", + "generated_at": "2026-02-17T05:38:27.096Z", "generated_by": "/Users/d/.codex/scripts/bootstrap/global_tests_docs_bootstrap.mjs", - "changed_files": [ - ".codex/prompts/test-critic.md", - ".codex/scripts/run_verify_commands.sh", - ".codex/verify.commands", - ".github/workflows/quality-gates.yml", - "docs/adr/0000-template.md", - "openapi/openapi.generated.json", - "scripts/ci/require-tests-and-docs.mjs", - "AGENTS.md" - ] + "changed_files": [] } From 9eb32cb3e7981704ba34bb4df43cd26030fc4d23 Mon Sep 17 00:00:00 2001 From: saagar210 Date: Mon, 16 Feb 2026 21:42:34 -0800 Subject: [PATCH 4/4] chore(codex): bootstrap tests and docs defaults --- .codex/bootstrap/tests-docs.v1.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.codex/bootstrap/tests-docs.v1.json b/.codex/bootstrap/tests-docs.v1.json index 666fdaf..e8ebf8c 100644 --- a/.codex/bootstrap/tests-docs.v1.json +++ b/.codex/bootstrap/tests-docs.v1.json @@ -2,7 +2,7 @@ "contract": "tests-docs-bootstrap-v1", "adapter": "node-ts", "branch": "codex/bootstrap-tests-docs-v1", - "generated_at": "2026-02-17T05:38:27.096Z", + "generated_at": "2026-02-17T05:42:34.624Z", "generated_by": "/Users/d/.codex/scripts/bootstrap/global_tests_docs_bootstrap.mjs", "changed_files": [] }