Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 

README.md

practify-scanner (TypeScript)

Defensive code pattern detection for TypeScript/JavaScript — Practify Protocol Level 1

Maturity: IN DEVELOPMENT — cross-language port of the verified Python scanner. Pattern detection accuracy validated on test files; not yet tested on large production codebases.

What it does

Scans TypeScript/JavaScript source code for defensive patterns — code constructs that signal the author was uncertain but chose to hide it rather than declare it.

Pattern Severity What it catches
swallowed-exception ERROR catch {} — exception silently discarded, or catch (e) { console.log(e) }
bare-except ERROR catch (e: any) / bare catch — catching unknown errors
missing-anchor WARNING Exported function without @pract.test or @pract.i_dont_know JSDoc annotation
defensive-null-chain WARNING 3+ chained if (x === null) return null patterns
trivial-test WARNING Tautological assertions like expect(result).toBe(result)
vague-todo INFO // TODO without issue tracker reference

Install

npm install practify-scanner

Usage

# Scan a file
npx practify-scanner check src/app.ts

# Scan a directory
npx practify-scanner check src/

# Generate a health report
npx practify-scanner report .

Programmatic API

import { scanFile, scanDirectory, summarize } from "practify-scanner";

// Scan a single file
const patterns = scanFile("src/index.ts");
for (const p of patterns) {
  console.log(`[${p.patternType}] ${p.filePath}:${p.lineNumber}`);
  console.log(`  ${p.suggestion}`);
}

// Scan a directory
const results = scanDirectory("src/");
console.log(`Scanned ${results.size} files`);

// Summarize
const summary = summarize(patterns);
console.log(summary); // { total, byType, bySeverity }

The Principle

practify-scanner is based on a simple insight:

Defensive code patterns expose the author's cognitive state — "I'm not sure about this, but I don't want to say I don't know."

The scanner doesn't judge. It surfaces the patterns so you can decide:

  • "Yes, I know this is safe" → document why
  • "No, I'm not sure" → add a @pract.i_dont_know JSDoc annotation
  • "Actually, this is a real problem" → fix it

Using JSDoc Annotations

The scanner checks for practify annotations in JSDoc comments:

/**
 * Process a list of items, keeping only positive values.
 *
 * @pract.test "empty list returns empty" — process([]) === []
 * @pract.test "keep positives" — process([-1, 0, 3, -5]) === [3]
 * @pract.i_dont_know "behavior with massive lists (>1M) not verified"
 */
export function process(data: number[]): number[] {
  return data.filter((x) => x > 0);
}

Without these annotations, process would trigger a missing-anchor warning — not because it's buggy, but because it has no verifiable evidence of correctness.

Differences from the Python Scanner

Aspect Python TypeScript
AST parser ast (stdlib) TypeScript Compiler API
Anchor detection Decorators (@pract.test) JSDoc annotations (@pract.test)
File types .py .ts, .tsx, .js, .jsx, .mjs
Maturity Verified In Development

The TypeScript port uses JSDoc annotations instead of decorators because:

  1. TypeScript decorators are still experimental (Stage 3)
  2. JSDoc annotations work in both .ts and .js files
  3. No runtime dependency required — annotations are pure documentation until the anchor system is ported

Part of the Practify Protocol

This is Level 1 of the Practify Protocol — a code verification protocol for vibe coding.

  • Level 1 (this package): Scanner — detect defensive patterns
  • Level 2+: Anchors + Noise Cards — full verification protocol

For the Python full protocol including @pract.test decorators, noise card tracking, and AI context injection, see the Python practify package.

Contributing

This port needs practice data:

  1. Run it on your TypeScript codebase — report false positives
  2. Compare with the Python scanner — same patterns on equivalent code should produce the same results
  3. Test on large codebases — we need to validate performance and accuracy at scale

License

MIT