Behavioral Fingerprinting Engine for Code Changes
Catch the regressions your tests don't cover — before they hit production 30-90 days later.
AI-assisted code changes are fast and pass existing tests. But tests only cover known behaviors. When an AI refactors processPayment(), it might subtly change how null currency codes are handled. Your tests pass. Three months later, 0.3% of payments start failing.
behaviorprint captures the complete behavioral signature of your functions — every edge case, every boundary value, every type coercion quirk — and detects when any of it changes.
Before Change After Change
│ │
▼ ▼
┌──────────────┐ ┌──────────────┐
│ Extract AST │ │ Extract AST │
│ functions │ │ functions │
└──────┬───────┘ └──────┬───────┘
▼ ▼
┌──────────────┐ ┌──────────────┐
│ Generate │ │ Generate │
│ input classes│ │ input classes│
│ (boundaries) │ │ (boundaries) │
└──────┬───────┘ └──────┬───────┘
▼ ▼
┌──────────────┐ ┌──────────────┐
│ Probe each │ │ Probe each │
│ function │ │ function │
│ (sandboxed) │ │ (sandboxed) │
└──────┬───────┘ └──────┬───────┘
│ │
└──────────┬──────────────────┘
▼
┌──────────────┐
│ Compare │
│ fingerprints │
└──────┬───────┘
▼
┌──────────────┐
│ Divergence │
│ Report │
└──────────────┘
- Function Extraction — AST-based (tree-sitter) identification of exported/public functions with arity detection
- Input Class Generation — Automatic boundary values:
0, -1, MAX_SAFE_INTEGER, null, undefined, NaN, Infinity, empty string, empty array, {}, and combinations - Behavioral Probing — Sandboxed execution capturing return values, thrown exceptions, and side effects (console output)
- Fingerprint Comparison — Hash-based comparison of
(input_class → output_signature)maps - Severity Classification —
return→throw= critical,null/undefinedboundary = high, type changes = medium - Coverage Gap Detection — Information-theoretic entropy metric identifying undertested behavioral surfaces
npm install @phoenixaihub/behaviorprint# Capture behavioral fingerprints of all exported functions
behaviorprint capture ./src --output before.json
# Make your changes...
# Capture again
behaviorprint capture ./src --output after.jsonbehaviorprint compare before.json after.json --output report.json{
"functions_analyzed": 12,
"identical": 9,
"divergent": 3,
"divergences": [
{
"function": "processPayment",
"file": "src/payments.js",
"input": [0, null],
"before": { "returns": { "success": false, "error": "invalid" } },
"after": { "throws": "TypeError: Cannot read property 'code' of null" },
"severity": "critical",
"production_frequency": "estimated 0.3% of calls"
}
]
}import { captureFunction, compareFingerprints } from '@phoenixaihub/behaviorprint';
// Capture a single function
const before = captureFunction(oldImplementation, 'processPayment');
const after = captureFunction(newImplementation, 'processPayment');
// Compare
const report = compareFingerprints([before], [after]);
console.log(`${report.divergent} behavioral divergences found`);
for (const d of report.divergences) {
console.log(`${d.severity}: ${d.function} — input: ${JSON.stringify(d.input)}`);
}import { capture, compareFingerprints } from '@phoenixaihub/behaviorprint';
const before = capture('./src-v1');
const after = capture('./src-v2');
const report = compareFingerprints(before.fingerprints, after.fingerprints);| Severity | Meaning | Example |
|---|---|---|
| critical | Function now throws where it previously returned | null input causes crash |
| high | Null/undefined boundary behavior changed | Silent null → error |
| medium | Return type changed | number → string |
| low | Value changed but type preserved | 42 → 43 |
# .github/workflows/behaviorprint.yml
- name: Capture baseline
run: behaviorprint capture ./src --output baseline.json
- name: Capture current
run: behaviorprint capture ./src --output current.json
- name: Compare
run: |
behaviorprint compare baseline.json current.json --output report.json
cat report.json | jq '.divergent' | grep -q '^0$' || exit 1MIT