Project kind detection

The scan detects language ecosystem (`node`, `python`, `go`) and framework (`Next.js`, `Express`), but has no concept of what a project fundamentally *is* — CLI tool, library, web app, API server, or full-stack app. A Node CLI, a Node web app, and a Node library all produce the same scan identity. Downstream consumers (skills, scaffolds, context generation) can't tailor advice because they don't know what kind of thing they're advising on. The deployment skill gives web-app guidance to a CLI tool. The project description says "TypeScript project" for anything without a recognized framework.

verdict PASSscore 16 / 16findings 7 (0 risk · 0 debt · 7 obs)duration 1h 30mrejection cycles 0shipped Apr 16, 2026

Pipeline timeline

Intent to proven code in 1h 30m across Think, Plan, Build, and Verify.

Think
12m
Plan
12m
Build
57m
Verify
21m

Assertion ledger

16 claims, each independently verified. Showing 8 — show all →

IDSaysMatcher
A001The scan result includes a project kind classificationverifiedok
A002Scanning a Node CLI project with a bin field detects it as a CLI toolverifiedok
A003Detection works without reading the filesystemverifiedok
A004New projects default to unknown kind until classifiedverifiedok
A005A project with a bin field in package.json is classified as a CLI toolverifiedok
A006A project with CLI dependencies like commander is classified as a CLI toolverifiedok
A007A project with a browser framework like React is classified as a web appverifiedok
A008A project with a server framework and no browser UI is classified as an API serververifiedok

Findings 7 total

obsprojectKind.tsclosed
Dead logic in full-stack browser-dep check: `projectKind.ts:105` — `BROWSER_FRAMEWORKS.has(d)` will never match because dep names are npm packages (lowercase: `'react'`, `'vue'`) while the set contains PascalCase display names (`'React'`, `'Vue'`). The adjacent inline array on lines 106-107 handles the actual matching with lowercase package names. Harmless now, but if someone removes the fallback array trusting the Set, full-stack detection silently breaks. Consider removing `BROWSER_FRAMEWORKS.has(d) ||` from the expression, or normalizing to one casing.
obsprojectKind.tsclosed
Framework display-name coupling creates latent misclassification: `projectKind.ts:43-64` sets contain PascalCase display names, but the input comes from `getFrameworkDisplayName()` which falls back to raw lowercase keys for unmapped frameworks. Two currently-detectable frameworks would misclassify: Koa (`'koa'` ≠ `'Koa'` → would be library/unknown instead of api-server) and React Router (`'React Router'` not in BROWSER_FRAMEWORKS → would be unknown instead of web-app). Fix: either lowercase-normalize the sets and input, or add missing entries to `FRAMEWORK_DISPLAY_NAMES` in displayNames.ts.
obsprojectKind.tsclosed
Unused export `ProjectKindResult`: Exported from projectKind.ts:22-24 but never imported outside the file. `detectProjectKind` returns it, but scan-engine.ts accesses `.kind` directly without typing the intermediate. Minor — not harmful, but if the intent was a typed contract for consumers, nobody is consuming the type.
obspackages/cli/src/engine/scan-engine.tsclosed
`hasMain` covers `main` AND `module`: scan-engine.ts:555 sets `hasMain = !!pkgRaw['main'] || !!pkgRaw['module']`. The variable name suggests only `main`. Consider `hasMainOrModule` for clarity, or split into separate booleans matching the spec's language ("main, module, or exports").
obsprojectKind.test.tsclosed
A003 purity test is comment-fragile: projectKind.test.ts:187-193 reads the source file and asserts `not.toContain('node:fs')`. A future comment mentioning `node:fs` would cause a false failure. A regex-based import check (`/import.*from\s+['"]node:fs/`) would be more precise. Not broken, not urgent.
+2more findings

Integrity seal

scopesha256:514909d4b78de...
contractsha256:e24cd4dbe8775...
plansha256:d3e0c7d9ecb56...
specsha256:fac256a54df88...
build-reportsha256:0e6bdff5da82b...
verify-reportsha256:063a80e9be00b...
audit cmd$ ana proof audit add-project-kind-detection   → all hashes match