Skip to content
Closed
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
8 changes: 8 additions & 0 deletions .codex/bootstrap/tests-docs.v1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"contract": "tests-docs-bootstrap-v1",
"adapter": "node-ts",
"branch": "codex/bootstrap-tests-docs-v1",
"generated_at": "2026-02-17T05:42:34.624Z",
"generated_by": "/Users/d/.codex/scripts/bootstrap/global_tests_docs_bootstrap.mjs",
"changed_files": []
}
14 changes: 14 additions & 0 deletions .codex/prompts/test-critic.md
Original file line number Diff line number Diff line change
@@ -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.
21 changes: 21 additions & 0 deletions .codex/scripts/run_verify_commands.sh
Original file line number Diff line number Diff line change
@@ -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"
7 changes: 7 additions & 0 deletions .codex/verify.commands
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pnpm lint
pnpm typecheck
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Align verify command contract with defined npm scripts

The verify command list references scripts that are not defined in package.json (typecheck, test:coverage, test:integration, test:e2e:smoke, docs:generate, docs:check), so the run_verify_commands.sh step aborts immediately with ERR_PNPM_NO_SCRIPT (for example, Missing script: typecheck). As written, the quality workflow cannot pass even after dependencies install.

Useful? React with 👍 / 👎.

pnpm test:coverage
pnpm test:integration
pnpm test:e2e:smoke
pnpm docs:generate
pnpm docs:check
46 changes: 46 additions & 0 deletions .github/workflows/quality-gates.yml
Original file line number Diff line number Diff line change
@@ -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
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Replace frozen pnpm install with lockfile-compatible install

The new workflow will fail on every run at dependency installation because it executes pnpm install --frozen-lockfile in a repo that ships package-lock.json and no pnpm-lock.yaml; pnpm errors with ERR_PNPM_NO_LOCKFILE (Cannot install with "frozen-lockfile" because pnpm-lock.yaml is absent). This blocks all subsequent quality gates from running.

Useful? React with 👍 / 👎.


- 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/
13 changes: 13 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -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.
38 changes: 38 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
16 changes: 16 additions & 0 deletions docs/adr/0000-template.md
Original file line number Diff line number Diff line change
@@ -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.
9 changes: 9 additions & 0 deletions openapi/openapi.generated.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"openapi": "3.1.0",
"info": {
"title": "API Contract",
"version": "1.0.0"
},
"paths": {},
"components": {}
}
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
41 changes: 41 additions & 0 deletions scripts/ci/require-tests-and-docs.mjs
Original file line number Diff line number Diff line change
@@ -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' })
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

The script uses execSync with a template string that incorporates the baseRef variable, which is derived from the GITHUB_BASE_REF environment variable. GITHUB_BASE_REF is the name of the base branch in a pull request. If an attacker can influence the name of a branch in the repository (e.g., by creating a branch with a malicious name like main; touch /tmp/pwned), they could execute arbitrary commands on the CI runner when this script is executed. This could lead to the exfiltration of sensitive environment variables or secrets stored in the CI environment.

Suggested change
const diff = execSync(`git diff --name-only ${baseRef}...HEAD`, { encoding: 'utf8' })
const diff = execSync(`git diff --name-only ${baseRef.replace(/[^\w./-]/g, '')}...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);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Include Tauri backend paths in production-change policy checks

The production-code detector only matches src|app|server|api, so changes under src-tauri/ are never treated as production changes and can merge without any test updates despite the repository policy requiring tests for production changes. This creates a policy enforcement gap for backend Rust code in this project.

Useful? React with 👍 / 👎.

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.');
20 changes: 20 additions & 0 deletions scripts/cleanup-full.sh
Original file line number Diff line number Diff line change
@@ -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
19 changes: 19 additions & 0 deletions scripts/cleanup-heavy.sh
Original file line number Diff line number Diff line change
@@ -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
36 changes: 36 additions & 0 deletions scripts/lean-dev.sh
Original file line number Diff line number Diff line change
@@ -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"
2 changes: 1 addition & 1 deletion src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
11 changes: 9 additions & 2 deletions vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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()],
Expand All @@ -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: {
Expand Down
Loading