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
60 changes: 60 additions & 0 deletions docs/BENCHMARKS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# NirmiqCodeSensei — Analysis Benchmarks (MS4)

The analysis pipeline is CPU-bound and local (no network, no server fan-out), so
the honest analog of "load handling" for this tool is **compute scaling**: how
the analysis time grows with project size, and how much the MS4 incremental path
saves when nothing changed.

## Method

A synthetic project generator (`scripts/_benchmark.mts`, a scratch harness — not
committed) writes N interlinked TS/TSX files across realistic layers
(`components`, `lib/services`, `lib/utils`, `app/*`, `hooks`). Each file imports
the previous one (so the import graph and cycle detection are exercised) and
contains branchy functions (so cyclomatic-complexity metrics are non-trivial).
Every timed function is pure/local and touches no database:

- **analyzeCode** — directory walk + AST parse (`@typescript-eslint/typescript-estree`) + DSA findings + import graph.
- **computeSeniorReview** — all eight lenses over the already-collected corpus (no re-walk, no re-parse).
- **computeSourceFingerprint** — the MS4 incremental-skip check (`sha256` of `path|size|mtime`, stat-only).

The AST parser and lens pass are warmed once per size so JIT compilation doesn't
skew the first measurement. Times are milliseconds.

## Results (dev machine, Windows 11)

| Files | analyzeCode | seniorReview | fingerprint | scanned |
|------:|------------:|-------------:|------------:|--------:|
| 50 | ~97 ms | ~3 ms | ~6 ms | 50 |
| 150 | ~130 ms | ~4 ms | ~13 ms | 150 |
| 300 | ~180 ms | ~4 ms | ~23 ms | 300 |

A full analysis of a 300-file project completes in **under ~200 ms** end to end
(analyzeCode + seniorReview), comfortably interactive.

## Interpretation

- **The lens pass is effectively free.** `computeSeniorReview` stays flat at
~3–4 ms regardless of project size, because it consumes the corpus that
`analyzeCode` already collected — it never re-walks the tree or re-parses ASTs.
- **`analyzeCode` dominates and stays bounded.** It grows sub-linearly (~97 ms →
~180 ms from 50 → 300 files) because AST parsing is capped at
`MAX_AST_FILES = 100`; beyond that only the cheaper regex/graph work grows.
Hard caps keep the worst case bounded on any repo:
- `MAX_FILES = 300` — files scanned per analysis.
- `MAX_AST_FILES = 100` — files given a full AST pass.
- `MAX_FILE_BYTES = 80 KB` — per-file size ceiling.
A project larger than these is analyzed on its most important files and marked
`truncated` (surfaced honestly in the learning-map summary), never hung.
- **Incremental re-analysis pays off (MS4).** On an unchanged tree,
`reanalyzeProject` computes only the fingerprint (~23 ms at 300 files,
stat-only — no AST parse, no lens pass, no DB writes) and short-circuits. That
is roughly **8× cheaper** than a full re-analysis (~180 ms + persistence) and
avoids all database churn.

## Reproducing

Recreate `scripts/_benchmark.mts` from this methodology (synthetic N-file project
→ time `analyzeCode`, `computeSeniorReview`, `computeSourceFingerprint`), run
`npx tsx scripts/_benchmark.mts`, then delete it. Numbers vary with hardware; the
shape (flat lens pass, bounded walk, cheap fingerprint) is what matters.
2 changes: 1 addition & 1 deletion docs/MEGASPRINT_ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ free + BYOK path (`ANTHROPIC_API_KEY` optional; offline analyzer is the default)
| **MS1** ✅ | Identity | Final distribution-ready name everywhere, incl. DB file / env / MCP internals, done once and safely | **DONE** — deep rename shipped; repo → `SheeshDarth/NirmiqCodeSensei`; DB boot-migration + `NCS_*` env fallback + `ncs_*` tools; gate green (16/16) |
| **MS2** ✅ | Security | The app ingests users' private source code — it must be provably safe | **DONE** — symlink-confined walk, shell-free git, realpath+credential-dir blocks, prod CSP no `unsafe-eval`, `npm audit` critical-gate; self-scan security lens **A/100** |
| **MS3** ✅ | Architecture & Data Integrity | Kill load-bearing hacks (description-as-path, no backup) | **DONE** — `sourcePath` column (migration 0008) retires the "Imported from:" hack; DB durability (`synchronous=NORMAL`, `busy_timeout`, boot integrity check, WAL checkpoint on exit) + downloadable backup; workspace error/loading boundaries; graph reconciliation already handled (`graphJson ?? buildKnowledgeGraph`). **#27/#28 module FKs deferred to MS4** (no analyzer-produced associations to populate them — REVIEW-012). Gate green (19/19) |
| **MS4** | Algorithms & Analysis Depth | The analysis *is* the product — make it rigorous and calibrated | Defensible self-scan grade; incremental re-analysis; documented large-repo benchmarks |
| **MS4** 🔄 | Algorithms & Analysis Depth | The analysis *is* the product — make it rigorous and calibrated | **In progress** — ✅ codeHealth scoring calibrated to code *density* not project size (self-scan F→**B(76)**, overall **A(95)**); size-relative `computeCodeHealthScore` + relativity test. ✅ incremental re-analysis — `computeSourceFingerprint` (path\|size\|mtime sha256) + `learning_maps.source_fingerprint` (0009); reanalyze short-circuits `{unchanged:true}` on an untouched tree. ✅ [benchmarks](BENCHMARKS.md) — 300-file full analysis <200ms, flat ~4ms lens pass, incremental skip ~8× cheaper; bounded by MAX_FILES/AST caps. Remaining: fold in #27/#28 module associations (REVIEW-012) |
| **MS5** | Quality & Reliability (QA) | 16 tests is a foundation, not production confidence | Critical path e2e-covered; CI green on Win/mac/Linux from a clean clone |
| **MS6** | Framework & Performance | Production Next.js build quality | Standalone build runs; perf/a11y budgets met; no UI-blocking analysis |
| **MS7** | Distribution & Release | Turn the repo into installable, versioned software — the actual "deploy" | `npx nirmiqcodesensei@latest` runs on a fresh machine; tagged v1.0.0 GitHub Release; CHANGELOG current; scaling-N/A ADR recorded |
Expand Down
1 change: 1 addition & 0 deletions lib/db/migrations/0009_mushy_sebastian_shaw.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE `learning_maps` ADD `source_fingerprint` text;
Loading
Loading