English · 简体中文
Check the code AI wrote for you — before it ships. Eleven dimensions, file:line evidence, plain language. You don't need to be a security expert.
- Security & privacy — exposed routes, injections, leaked keys, and what data the app actually collects versus what it claims.
- Supply chain & licenses — the download gate before you install, dependency versions, whether the license lets you ship it.
- Someone else can take it over — maintainability, readability, testability.
- It survives real use — robustness, runtime stability, performance, observability / operability, handover.
Security · Privacy · Supply chain & licenses · Maintainability · Readability · Testability · Robustness · Stability · Performance · Observability · Handover
Not "possible IDOR (CWE-639)" but "the
registerroute on line 12 has no auth guard — your user table is exposed to the internet", with the file and line. Dynamic reproduction is an opt-in second stage.
| Tier | One line | Enforcement |
|---|---|---|
| L1 Personal | Losing the data would not hurt; only you use it | Only leaked secrets (S3) hard-block; everything else advisory |
| L2 With users | Public and receiving other people's data | High severity blocks, medium must be fixed |
| L3 Company | Company project, paid work, compliance obligations | Nothing ships until the matrix passes; produces a presentable acceptance report |
| Piece | Form | What it does |
|---|---|---|
| Desktop app | Electron (Windows) | Chat + audit desk: tiered acceptance, agent workflows, live tool traces, artifact preview, usage stats |
| Engine | CLI (node bin/finalcheck.js audit <dir>) |
Static gates (secrets, dependencies, risky patterns, auth matrix, semantic checks) → scorecard + issue tickets |
| Agent runtime | Built into the desktop app | DAG workflows and a restricted-script DSL, adversarial verification of every claim, journal-based resume, blind spot checks |
| Gates & playbooks | Skill/hook integrations + playbooks/ |
Download gate (before installing/running third-party code) and delivery gate (before handing work over) |
| Rulebooks | Text, per tier | What the AI must follow while writing code, so problems are prevented up front |
The npm package finalcheck is currently a placeholder that prints usage; the real CLI runs from this repository (node bin/finalcheck.js audit ...). Use the desktop app for the full experience.
- Windows 10/11 (the desktop app is Windows-first; the CLI also runs on macOS/Linux)
- Node.js 22 or newer with npm 10 or newer
- Git (needed for source installs and for the S3 git-history check)
- Download the latest
fc-setup-<version>.exefrom Releases. - Run it and pick the install folder (a desktop shortcut is included).
- On first launch open Settings → Model settings and add an OpenAI-compatible gateway (Base URL / API key / model).
- Later versions update themselves from the same Releases page.
The build is not code-signed yet, so Windows SmartScreen may show "unrecognized app" — click More info → Run anyway.
git clone https://github.com/ccai40359-wq/finalcheck
cd finalcheck
npm ci
cd desktop && npm ci && npm run setup:sqlitenpm ci uses the committed lockfiles. npm run setup:sqlite rebuilds the better-sqlite3 binding for the Electron ABI; run it again after changing the Electron version.
node bin/finalcheck.js audit . --tier L2--tier accepts L1, L2 or L3. --json produces machine-readable output, and --include-fixtures pulls **/fixtures/** into the product verdict only when checking intentionally broken samples.
The audit is static by default: it does not run the audited project's test suite or quality commands, and Q1/Q2 are reported as coverage gaps instead of passes. Add --run-tests only for a project you trust and explicitly want executed; --no-tests wins over --run-tests when both are present. scan-download exits non-zero whenever it has a coverage gap, so "could not verify" never looks like a pass.
Implemented scope, limits and the manual-evidence contract are in docs/RELIABILITY.md.
cd desktop && npm run devFor a production Windows build use cd desktop && npm run dist; artifacts land in desktop/release/.
npm testTo smoke-test built artifacts locally, run npm run smoke:e2e from the repo root after desktop/out exists. It opens a real window against an isolated temp profile, so it never touches your real FinalCheck data.
Coverage notes: npm test runs the node:test suites. npm run lint checks the .mjs engine/tooling plus the .jsx renderer for shadowed t() and React hook rules; the renderer is not fully linted. npm run typecheck is a per-file opt-in check for three core main-process modules, not the whole codebase. CI also runs a FinalCheck self-audit and verifies that every .finalcheck/accept.json entry still matches current line content.
Set these in your shell or system environment (or before launching the app); there is no .env loader, so copying .env.example to .env has no effect. The CLI and desktop app run without any of them. Variables used by the project:
| Variable | Required | Purpose |
|---|---|---|
FINALCHECK_CONFIG_FILE |
No | Override the desktop config.json path |
FINALCHECK_PROJECTS_FILE |
No | Override the workspace list file |
FINALCHECK_SESSIONS_DIR |
No | Override the session storage directory |
FINALCHECK_MEMORY_DIR |
No | Override the agent memory directory |
FINALCHECK_SPILL_DIR |
No | Override the oversized-tool-output spill directory |
FINALCHECK_USAGE_FILE |
No | Override the usage ledger file |
FINALCHECK_HOOKS_FILE |
No | Override the hooks configuration file |
FINALCHECK_SESSION_STORE |
No | Select the session store backend |
FINALCHECK_DEFAULT_PROJECT |
No | Default workspace when none is supplied |
FINALCHECK_MAX_TURNS |
No | Cap agent turns per session |
FINALCHECK_STREAM_USAGE |
No | Enable streaming usage accounting |
FINALCHECK_SQLITE_BINARY_HOST |
No | better-sqlite3 prebuilt binary mirror |
FINALCHECK_SQLITE_ALLOW_UNVERIFIED |
No | Allow an unlisted SQLite prebuild instead of failing closed |
FINALCHECK_SANDBOX |
No | auto (default), required (refuse if the Windows ACL sandbox is unavailable), or off |
ELECTRON_RENDERER_URL |
No | Dev-server URL used by electron-vite |
APPDATA / USERPROFILE / LOCALAPPDATA |
Auto | Windows profile locations (set by the OS; LOCALAPPDATA holds the sandbox temp dir) |
CI / PYTHON / SMOKE_TARGET |
No | Test and smoke-test helpers |
The model API key is not read from an environment variable in the installed app: it is stored in the local %APPDATA%\FinalCheck\config.json (never committed, never written to reports) and edited through Settings → Model settings. .env.example contains names and placeholders only; never put a real key in it.
FinalCheck is a local desktop tool; "deploy" means building and distributing the Windows installer, not running a server.
cd desktop && npm run distThis runs electron-vite build and then electron-builder --win nsis --publish never. The installer is written to desktop/release/fc-setup-<version>.exe; the version comes from desktop/package.json. Upload the artifact to the GitHub Releases page the updater reads.
CI runs the test suite and the desktop build on every change; packaging is a manual release step.
Backups are explicit and local; nothing is uploaded.
node scripts/backup.mjs --out "D:\Backups\FinalCheck"The script copies the profile data (%APPDATA%\FinalCheck: config, sessions, memory) and the project database (.finalcheck/finalcheck.db) into a timestamped zip such as finalcheck-backup-20261111-194500.zip. Model API keys in config.json are replaced with [REDACTED] before they enter the archive; secret-looking files (.env, *.pem, *.key, credentials files) are skipped. The newest 7 archives are kept by default; change it with --keep <n> or choose another profile/project with --profile / --project.
Restore: close the app, unzip the archive, copy config.json, sessions/ and memory/ back to %APPDATA%\FinalCheck, and copy the database back to <project>\.finalcheck\finalcheck.db. Keep the previous backup until the restored app starts cleanly.
- Desktop app: reinstall the previous installer (for example
fc-setup-0.16.1.exe) from the Releases page. User data stays in%APPDATA%\FinalCheck; take a backup first. - Source tree: use
git revert <commit>for a single bad change, orgit checkout <previous-tag>to return to the previous release. Re-runcd desktop && npm run setup:sqliteafter switching Electron versions. - Data: restore the zip produced by
scripts/backup.mjsusing the steps above. Backups are the rollback path for sessions and memory because the app does not migrate data backwards.
- Export diagnostics: use Usage → Export diagnostics (also available in Settings → About & updates). The exported JSON contains the app version, OS, the last 200 log lines, rule hits, and config with API keys masked. Nothing is uploaded automatically.
- Reports look too noisy: run a baseline first (
--write-baseline), then use--fail-on newso only newly introduced blocking findings fail. - gitleaks/osv-scanner are missing: S3 keeps its built-in rules and the report says so; install the tools or set their paths to enable the wider rule set.
The UI ships in Chinese and English.
- Settings → Runtime → Language: Follow system / 中文 / English. Switching applies immediately.
- In English mode the agents, workflows and generated reports also produce English output; in Chinese mode everything stays Chinese.
- Chinese is the default: a Chinese system with Follow system stays Chinese, everything else starts in English.
- The API key lives only in the local
config.json(%APPDATA%\FinalCheckin the installed build). It is never written to sessions, logs or reports. - Path and command access is controlled by a policy:
workspace(writes inside the project only),readonly, oroff.workspaceis an application-level path policy, not an OS sandbox. Sensitive locations (.ssh,.aws,.gnupg, Git credentials, private keys) are blocked in every mode, and a command blacklist applies on top. readonlyrejects commands, quality-gate commands and project-memory writes. Path checks resolve junctions/symlinks to their real target before deciding whether a path is inside the workspace.- On Windows,
run_commandand quality-gate commands run inside a dsh ACL restricted-token sandbox when the package is available: creating and modifying files is limited to the workspace plus a private temp directory, and the sandbox fails closed at setup. It does not restrict reads, network, or process visibility; those remain application-level policy. If the sandbox is unavailable, the command runs on the host with a warning; setFINALCHECK_SANDBOX=requiredto refuse instead. - That token filters write access, not
DELETE, so a plaindelof a file outside the workspace is not stopped by the kernel (del /fand PowerShellRemove-Itemare). Delete/rename commands are therefore checked at the application layer: a literal absolute or..path outside the workspace rejects the whole command;%VAR%and wildcard forms are left to the command blacklist and the approval prompt. - Restricted tokens cannot write to Windows named pipes or cygwin shared memory, so Node toolchains (
npm test,node --test) fail withEPERMand Git Bash utilities (grep,cat,head) fail outright — Codex's Windows sandbox has the same limit. Those commands run on the host with asandboxSkipnote (the path policy, command blacklist and approvals still apply), while cmd/PowerShell/git/python commands stay sandboxed. The sandboxed child runs in an invisible console, so no console window pops up; on the rare system where the hidden console aborts the child (0xC0000142) the tool retries once with a visible console and says so. - Approvals are isolated per session, project and tool; "always allow this session" never leaks across sessions or projects. A compound command (
a && b, pipes,;or newlines) is approved as the whole command, so an allowed single command can never carry a second command with it. The quality gate binds its approval to the normalized command config fingerprint and runs the approved config snapshot, so changingfinalcheck.quality.jsonafter approval requires a new approval. - Dynamic targets (probes, stress tests) require an explicit, per-target confirmation and are capped at 60s / 50 connections; "allow once" covers that one run only, and the host is remembered only when you choose "always allow this session".
- Removing a workspace from the list never deletes anything on disk.
bin/ CLI entry points (finalcheck, finalcheck-mcp)
src/ audit engine (checks, probe/stress, MCP surface)
desktop/ Electron app (main / preload / renderer)
playbooks/ audit playbooks
integrations/ skill + hook wiring for coding agents
docs/ ACCEPTANCE.md — tier SSOT; RELIABILITY.md — implemented scope and evidence limits
tests/ node:test suites (1284 passing)
Early but real: the engine, the desktop app, tiered gates, agent workflows (DAG + script DSL), adversarial verification and in-app updates are in place, with 1284 tests passing on every change. Development follows the project's own L3 standard — a known violation of any L2 item in this repository counts as a bug.
Sean — github.com/ccai40359-wq · repository: finalcheck
Apache-2.0. See LICENSE.

