Skip to main content
Version: 2.0.1-alpha.3

Choosing the Right Scat Categories

The --scat flag controls which CS-MAST structural categories are used to fingerprint code during library module detection. Choosing the right combination affects how many library modules are stripped — a better scat config means a cleaner refactor output with less noise.

What are scat categories?

CS-MAST partitions every AST node into one of nine structural categories before hashing:

CategoryWhat it captures
litLiteral values (strings, numbers, booleans, regex)
idIdentifier names (variable names, property names)
opOperators (+, -, ===, ??, etc.)
declVariable and function declarations
loopLoop statements (for, while, do)
condConditional statements and expressions (if, ? :, switch)
nameNamed constructs (function names, class names)
valValue-producing expressions (calls, member access, assignments)
op_nameOperator + name combinations

A scat combo like lit,decl,loop,cond tells CS-MAST to include those four categories when computing each sub-tree's hash. More categories generally add structural detail, producing more signatures and a larger intersection with the library baseline — but the effect on detection is dataset- and target-dependent, not a guaranteed improvement. The category impact summary below shows cond and val reducing average detection despite adding categories.

The default: lit,decl,loop,cond

The default combination was chosen as a conservative baseline that produces stable signatures across different builds of the same library. It detects 12 out of 16 library modules in a representative React-webpack bundle (rank #240 of 511 tested combinations).

Experiment results

An experiment tested all 511 non-empty subsets of the 9 scat categories against 18 reference React-webpack apps. Key findings:

  • 62 combinations (12%) achieve perfect 16/16 library module detection
  • The default lit,decl,loop,cond is suboptimal — 208 combinations outperform it
  • id is by far the most impactful category: combos that include id detect on average 5 more library modules than those that don't
  • val and cond slightly reduce detection on average (their patterns diverge more across minified bundles)

Category impact summary

CategoryAvg detection withAvg detection withoutDelta
id13.25/168.18/16+5.07
lit11.29/1610.14/16+1.15
name11.26/1610.18/16+1.08
loop11.03/1610.40/16+0.63
op10.76/1610.67/16+0.09
op_name10.60/1610.84/16-0.24
decl10.55/1610.89/16-0.34
cond9.94/1611.50/16-1.56
val9.39/1612.05/16-2.65

Top performing combinations

All of the following achieve 16/16 library module detection on the reference bundle:

Scat comboIntersection size
lit,id,loop,cond,name,val2840 signatures
lit,id,cond,name,val2803 signatures
lit,id,decl,loop,name,val2677 signatures
lit,id,decl,name,val2603 signatures
id,loop,cond,name,val2201 signatures
id,cond,name,val2164 signatures
id,cond,name1987 signatures

For most use cases, the following combination offers the best balance of detection accuracy and simplicity:

js-recon refactor -t react-webpack --scat lit,id,loop,cond,name,val

This detects all library modules in tested bundles and generates ~2840 signatures — enough to confidently distinguish library code from application code.

If you want the safest, most stable signatures (fewest false positives, widest compatibility across different React versions), the minimal combination that still achieves full detection is:

js-recon refactor -t react-webpack --scat id,cond,name

This uses only 1987 signatures but reliably detects all 16 library modules in the reference bundle.

If you suspect false positives (user code being incorrectly stripped), narrow the combo:

js-recon refactor -t react-webpack --scat lit,decl,loop,cond

This is the conservative default — fewer signatures, lower risk of over-matching.

Dataset availability

The CS-MAST signature dataset is hosted as a HuggingFace bucket:

https://huggingface.co/buckets/shriyanss/cs-mast-s-dataset

Bucket structure

The bucket is organized by technology and dataset size:

shriyanss/cs-mast-s-dataset/
├── react/
│ └── webpack/
│ ├── small/ ← 18 feature apps (React hooks baseline)
│ │ ├── sample_size
│ │ ├── technology
│ │ ├── 01-usestate-hook-webpack/
│ │ │ ├── lit-decl-loop-cond/
│ │ │ │ └── collisions.json
│ │ │ ├── lit-id-loop-cond-name-val/
│ │ │ │ └── collisions.json
│ │ │ └── … (all 511 scat combos)
│ │ ├── 02-useeffect-hook-webpack/
│ │ └── … (18 feature apps total)
│ └── large/ ← 18 larger apps (React 19 hooks baseline)
│ ├── sample_size
│ ├── technology
│ ├── 01-usestate/
│ └── …
└── main/

sample_size contains the number of apps in that prefix (for example, 18), used by the tool to compute signature quality. technology contains the tech identifier (for example, react-webpack), validated on startup.

All 511 combinations are available

Every non-empty subset of the 9 scat categories is already in the bucket. The dataset was generated by running cs-mast with all 511 permutations across all 18 feature apps, so whatever combination you pass to --scat will be found. When you run:

js-recon refactor -t react-webpack --scat lit,id,loop,cond,name,val

the tool resolves this to react/webpack/small/…/lit-id-loop-cond-name-val/collisions.json, downloads it for each of the 18 feature apps, and caches locally under ~/.js-recon/refactor/signature_cache/. Subsequent runs use the cache silently.

If a combination is genuinely absent (for example, for a technology not yet in the bucket), the tool falls back gracefully and runs without library stripping, printing a warning.

How the tool resolves the bucket directory

The category order in the directory name follows a fixed canonical order (lit → id → op → decl → loop → cond → name → val → op_name), regardless of the order you pass to --scat. So --scat cond,lit,id and --scat id,lit,cond both resolve to the lit-id-cond directory in the bucket.

React Vite recommendations

A separate benchmark (2026-06-30) tested all 511 scat combinations against 13 React Vite apps using a recovery quality score metric — how closely the refactored output's structural fingerprints match the original source. This metric differs from the webpack library-module count, so the two studies aren't directly comparable, but the category rankings are instructive.

Scat comboRecovery scoreNotes
id1.0000Perfect score — top recommendation
id,val1.0000Equivalent to id alone
id,op_name1.0000Equivalent to id alone
lit,id0.6599Good, but adding lit reduces score vs id alone
lit0.4918Acceptable if identifier-level matching is undesirable

The default lit,decl,loop,cond ranks 314/511 with a score of 0.0527 — significantly worse than id alone for Vite targets.

Recommended combinations for React Vite:

# Best recovery quality — use when false positives are not a concern
js-recon refactor -t react-vite --scat id

# Conservative — identifier-level matching disabled
js-recon refactor -t react-vite --scat lit

Key difference from webpack: name is beneficial for webpack (+1.08) but harmful for Vite (-0.048). Avoid name, decl, and cond in Vite scat configs.

See also