complexity is the single dial that decides how much protection the engine applies. A preset is a named point on it: light is 5, hard is 12. light renames identifiers, rewrites syntax and encodes strings, with no structural layers; from medium up, and for any value you set directly, every token is driven toward the target. Set complexity directly for a value in between or beyond — it is an unbounded non-negative number.
What rises with the number
Complexity is a budget, not a schedule. There is no fixed list of "this feature at this number". Above 0, the engine spends a larger budget as the value climbs and negotiates which transformations to apply, per build — so two builds at the same complexity are different shapes, and no single transformation is guaranteed at a given level. That per-build variation is the point: see how AfterPack works for why a fixed structure would be a fingerprint.
Three things are fixed:
complexity | What is guaranteed |
|---|---|
0 (minify) | No obfuscation. Identifiers are renamed and the code is compressed; nothing below runs. Engine 0.2.2 also rewrote syntax at 0. |
> 0 | Every string literal the engine can rewrite goes through a runtime decoder — the string floor. |
≥ 7 (medium and up) | Encoded strings and integers are keyed to a shared runtime value, and object literals are rebuilt in varied shapes. |
Everything else — control-flow reshaping, opaque predicates, integer-expression interpretation, and the rest — is drawn from the budget as it grows, not switched on at a line. inflation.max does not change which of them apply: left unset, the target alone decides, and a build that would grow past a value you set fails.
Turning a transformation off, or on
You can turn any transformation kind off. You cannot force one on.
- Off is reliable.
transforms.<kind>.enabled = falseremoves that kind at any complexity. From engine 0.2.3, turning offscopeDeepenat7and up can leave part of a file short of its target, and the build then fails withDIAG_TARGET_NOT_REACHED, naming the lines. - On is a permission.
truelets the engine use a kind; it still decides per build whether the complexity and budget call for it. Outside a region you raise, the only kinds alightbuild applies are string encoding and, on Pro,comparisonHardening.objectConstructionappears only at7(medium) and up, and the two Pro kinds need a Pro build. - At
0, none of it applies.minifyruns no transformations, so everytransformsflag is moot.
To make a transformation more likely, raise complexity rather than toggling a flag.
Next
- Presets: the named levels and the size budget each one sets.
- Configuration: every key, including the
transforms.<kind>.enabledflags. - How AfterPack works: why the set of transformations changes every build.
- Directives: a different complexity for one region (Pro).