# Quality bar and anti-patterns

> Readable and deep-tier completion criteria, naming anti-patterns (program-scope-only rename, mechanical fallback names, checkpoint promotion), Stage 3 acceptance categories E1–E4, and quality-gate failure modes.

- Repository: JimLiu/decode-codex
- GitHub: https://github.com/JimLiu/decode-codex
- Human docs: https://grok-wiki.com/public/docs/jimliu-decode-codex-1a3a0c425b33
- Complete Markdown: https://grok-wiki.com/public/docs/jimliu-decode-codex-1a3a0c425b33/llms-full.txt

## Source Files

- `.agents/skills/deobfuscate-javascript/SKILL.md`
- `.agents/skills/deobfuscate-javascript/scripts/acceptance-checklist.md`
- `.agents/skills/deobfuscate-javascript/stages/stage-3-finalize.md`
- `.agents/skills/deobfuscate-javascript/scripts/quality-gate.ts`
- `.agents/skills/deobfuscate-javascript/reference/naming-heuristics.md`

---

---
title: "Quality bar and anti-patterns"
description: "Readable and deep-tier completion criteria, naming anti-patterns (program-scope-only rename, mechanical fallback names, checkpoint promotion), Stage 3 acceptance categories E1–E4, and quality-gate failure modes."
---

`scripts/quality-gate.ts` enforces threshold-based checks on every promoted file under `restored/`, and `scripts/acceptance-checklist.md` defines the four-category semantic bar (E1–E4) that Stage 3 acceptance review applies after the script gate passes. Together they define when a deobfuscation restore is actually done — not merely formatted or syntactically valid.

## Two completion tiers

Restoration depth is independent of scope (single file vs whole import tree). Both tiers require the **staging → organize → promote** discipline: batch/script output never lands directly in `restored/`.

| Tier | Trigger | Hard bar | Optional / deep-only |
|------|---------|----------|----------------------|
| **Readable** (default for lone snippets; opt-out for whole trees) | User asks "quick" / "readable" / "快速", or a pasted snippet with no `index.html` tree | Meaningful identifiers throughout; no mechanical fallback names; semantic kebab filenames; provenance header; prettier-clean structure | TypeScript types, `forwardRef`, npm-import resolution tail, Stage 3 acceptance LOOP |
| **Deep** (default for whole-tree restores) | User asks "deep" / "full" / "typed" / "restore the code", or any `index.html` + asset tree without an explicit quick pass | Everything in readable tier **plus** typed `.tsx` surfaces, import-graph drain to `stages.promoted`, Stage 3 semantic rewrite, E1–E4 acceptance review, target-level `quality-gate.ts` over the whole `restored/` tree | — |

<Note>
Deep is a completion bar, not an upsell. A whole-tree restore is **done** only when every reachable project-local chunk reaches `stages.promoted` (deep: also `stages.finalized`) and `quality-gate.ts <target-dir>` exits 0.
</Note>

### Readable-tier deliverable shape

A valid readable deliverable:

- Lives in `restored/<semantic-domain>/` with kebab-case filenames (`button.tsx` exports `Button`)
- Starts with `// Restored from ref/webview/assets/<chunk>.js`
- Uses meaningful names — no `buttonValue3`, `contextParam14`, or other generated fallbacks
- May ship untyped (`function Button(props)` with no `Props` interface is acceptable)
- Passes `quality-gate.ts` with `--allow-untyped` when typing checks are intentionally relaxed

### Deep-tier deliverable shape

A valid deep deliverable adds:

- `Props` interfaces (or type aliases) on exported React components
- `forwardRef` + `displayName` on DOM-wrapping components
- `as const` lookup tables with `keyof typeof` unions
- Bare-specifier npm imports (`import clsx from "clsx"`)
- Semantic local imports between finalized siblings
- Stage 3 acceptance review pass on every public file (E1–E4)
- `manifest.stages.finalized = true` on accepted app-feature chunks

## Anti-patterns to refuse

These produce output that looks acceptable on a skim but fails on a real read. Refuse them before declaring done.

### Both tiers — naming and staging

<Warning>
The anti-patterns below are hard failures in **every** tier. They concern readability and staging discipline, not TypeScript compilation.
</Warning>

#### Program-scope-only rename

**Symptom:** Top-level exports have meaningful names (`AppShellTabContent`, `RightPanelTabs`) but function bodies remain `let k = useIntl(), [A, M] = useState(false), N = !h`.

**Cause:** Renaming stopped at Pass 1 (`--scope-kind Program`). Function-body bindings live in `FunctionDeclaration` / `ArrowFunctionExpression` scopes that the Program filter drops.

**Cure:** Continue through Pass 2 (function-body `let`/`const`/`var`) and Pass 3 (params). Run `smart-rename.ts` first for mechanical cases, then hand-name domain nouns, lookup tables, and JSX intermediates. See [Stage 2 scripts](/stage-2-scripts) (Step 2.5 — don't stop at program scope).

```text
Pass 1 (Program)     → exports, registries, top-level helpers
Pass 2 (bodies)      → hook returns, JSX intermediates, destructured props
Pass 3 (params)      → props, event, item/index — mostly smart-rename.ts
```

#### Mechanical fallback names

**Symptom:** Identifiers like `ImportedBinding1`, `callbackValue1`, `localValue1`, `buttonValue3`, `buttonParam1`, `contextParam14`, `DistO`, `restoredHelper1`, or `elementNode1`.

**Cause:** `auto-restore-full.ts` or the renamer exhausted evidence and emitted placeholder names that look grammatical but carry no domain meaning.

**Cure:** Replace with semantic names from producer/consumer usage, JSX shape, call graph, and export context. Never ship new placeholders. `quality-gate.ts` matches these via `MECHANICAL_NAME_RE` and fails with `mechanical-names`.

`smart-rename.ts` handles the ~80% of cases that are mechanically derivable (React `props`, event handlers, `.map` iteratees, hook returns). What remains is judgment work — see the heuristics spec in `reference/naming-heuristics.md`.

#### Checkpoint promotion

Two related failure modes violate the staging contract:

**Mechanical checkpoint in `restored/`**

- **Symptom:** `auto-restore-full.ts` output, hash-basename files (`button-bq66r8jD.tsx`), or `--write-target-checkpoints` files sitting directly in `restored/`
- **Cause:** Skipping organize → promote; copying raw script output into the deliverable root
- **Cure:** Keep all batch output in `restored/.deobfuscate-javascript/_full/checkpoints/`. Promote only after the promotion bar is met

**Checkpoints built, `restored/` empty**

- **Symptom:** `_full/checkpoints/` is full but `restored/` has no promoted semantic tree
- **Cause:** Batch executor ran; organize → promote loop was skipped
- **Cure:** `plan-organize.ts` → review/`--apply` → `promote-organized.ts` until `ledger.ts frontier --stage promote` is empty

```mermaid
stateDiagram-v2
    [*] --> Checkpoint: auto-restore-full / polish
    Checkpoint --> Organized: plan-organize.ts
    Organized --> Promoted: promote-organized.ts + quality-gate
    Promoted --> Finalized: Stage 3 rewrite + E1–E4 review
    Finalized --> [*]: quality-gate target-dir exit 0
    Checkpoint --> AntiPattern: copy to restored/ directly
    AntiPattern --> [*]: FAIL
```

### Deep tier only

These are typing, structure, and coverage requirements. A well-named untyped file is a valid readable deliverable; they apply only when deep/typed/production output was requested.

| Anti-pattern | Symptom | Cure |
|--------------|---------|------|
| Checkpoint shipped as deep completion | `$WS/polished.tsx` or `_full/checkpoints/<basename>.tsx` copied to public target without semantic rewrite | Host-agent rewrite → D0 gate → E1–E4 review |
| Multi-export bundle left flat | >1000 lines, registry-object export, single `<bundle>.tsx` | Split into a semantic directory (deep only; see `/restoration-pipeline`) |
| Deep request downgraded | `build-import-graph.ts --max-lines N` skips reachable chunks | Default `--max-lines 0`; report partial restore explicitly |
| App chunk faced instead of restored | Feature chunk left as `boundaries/*.ts` facade | Recurse import graph; drain `ledger.ts frontier` |
| Completion inferred from narrow audit | `IMPORT_MAP.status === "done"` while app chunks remain mechanical | Run `quality-gate.ts <target-dir>` over whole tree |
| Script gate passed, no acceptance review | `promote-final.ts` exit 0 but no end-to-end read | Host-agent E1–E4 self-review (always runnable) |

## Stage 3 acceptance categories (E1–E4)

After `quality-gate.ts` passes, deep mode requires an end-to-end read of every delivered file. The host agent applies `scripts/acceptance-checklist.md` directly — no sub-agent authorization required.

<Info>
**E1 (Naming)** is the shared bar in both tiers. **E2–E4** are deep-mode criteria. The checklist file uses B1–B4 labels internally; they map 1:1 to E1–E4 in `stages/stage-3-finalize.md`.
</Info>

### E1 — Naming

Failures report as `NEEDS_FIX:naming`.

- No identifiers matching `*Param\d+`, `*Value\d+`, `paramN`, `valueN`, `callbackValueN`, `localValueN`, `ImportedBindingN`, `restoredHelperN`, `elementNodeN`, `hookValueN`, `RestoredComponentN`, or `DistA` / `DistO` / `DistT`
- Lookup tables named for their role (`buttonColorClassNames`, not `buttonValue3` or `colorMap`)
- Parameters with call-site-appropriate names (`props`, `event`, `disabled`, `className`)
- React components in `PascalCase` ending in a noun phrase; hooks start with `use`
- Sibling imports use semantic names from the producer (not `import { t as ot }`)
- Public filenames and directories are semantic kebab-case without hash suffixes

### E2 — Readability (idiomatic TSX)

Failures report as `NEEDS_FIX:readability`.

- Every exported React component has a `Props` interface or `type Props =`
- DOM-wrapping components use `forwardRef<…>(…)` with `displayName`
- Pure SVG icons use `SVGProps<SVGSVGElement>` / `IconProps`, named `*Icon`, default-exported when single
- Lookup tables use `as const`; key unions exposed via `keyof typeof`
- No bundler residue: no `jsxRuntime.jsx(…)`, `(0, fn)(…)`, React Compiler `cache[N]`, `__toESM` / `loadJsxRuntime`, trailing `//# sourceMappingURL=`
- Provenance header present

### E3 — Formatting

Failures report as `NEEDS_FIX:formatting`.

- `bunx prettier --check <file>` exits 0
- User-defined JSX component tags are capitalized
- Long ternaries and nested call pyramids collapsed or extracted

### E4 — Other (structure, imports, exports)

Failures report as `NEEDS_FIX:other`.

- Vendored npm deps use bare specifiers
- Finalized local sibling imports use semantic public paths
- `default export` where the file has a single primary component
- Re-export aliases collapsed (`export const Foo = expr` preferred)
- Dead helpers and unused imports removed

### Acceptance LOOP

<Steps>
<Step title="Pre-filter">

Run `bun scripts/quality-gate.ts <target-dir>`. Exit 0 means review-ready. Non-zero → fix script-detectable failures via the D0 remediation list before spending the semantic read.

</Step>
<Step title="Review">

Read each file end-to-end against E1–E4. For large trees, `prepare-stage-e-review.ts` writes batch packets under the hidden workspace.

</Step>
<Step title="Repair">

Apply the cheapest fix per finding shape: `semantic-finalize.ts --recipe icon|button` for recipe gaps; hand-edit for missing types; `ledger.ts mark-done` + `apply.ts` for mechanical fallback names; `prettier --write` for formatting.

</Step>
<Step title="Re-read changed files only">

Do not re-review files that already passed. Repeat until every file returns `VERDICT: PASS`.

</Step>
</Steps>

There is no "ship with TODO" success path in deep mode. A TODO header may live in a checkpoint, but public completion requires every file to pass E1–E4.

## Quality-gate failure modes

`quality-gate.ts` runs per-file analysis plus full-restoration coverage checks when `_full/manifest.json` exists. Default thresholds:

<ParamField body="maxCrypticParams" type="number" default="20">
Cryptic parameter count before `cryptic-params` failure.
</ParamField>

<ParamField body="maxCrypticBindings" type="number" default="80">
Total cryptic binding count before `cryptic-bindings` failure.
</ParamField>

<ParamField body="maxShortRefCount" type="number" default="50">
Per-identifier short-name reference density before `short-identifier-density` failure.
</ParamField>

<ParamField body="maxFlatLines" type="number" default="1000">
Line count triggering `split-required` on multi-export bundles.
</ParamField>

### Per-file issue codes

| Code | Meaning | Typical fix |
|------|---------|-------------|
| `cryptic-params` | >20 cryptic params | Pass 3 rename + `smart-rename.ts` |
| `cryptic-bindings` | >80 cryptic bindings | Pass 2/3 rename |
| `short-identifier-density` | One-letter refs exceed threshold | Continue function-body rename |
| `mechanical-names` | Generated fallback names remain | Semantic rename from usage context |
| `mechanical-import-bindings` | Facade import aliases like `DistO` | Import semantic facade aliases |
| `bundle-residue` | `jsx-runtime`, `toESModule`, `sourceMappingURL`, React Compiler cache | Re-run `polish.ts` or hand-strip |
| `invalid-jsx-tags` | Lowercase tags that are not HTML intrinsics | Recover PascalCase component name |
| `unbound-jsx-tags` | JSX component referenced without local binding | Fix import or declare component |
| `unbound-identifiers` | Identifier referenced without binding | Fix import or scope |
| `untyped-component-props` | Exported component lacks `Props` type (deep only) | Add interface or run button recipe |
| `untyped-public-function-params` | Exported function params lack types (deep only) | Add parameter annotations |
| `public-cryptic-names` | Exported symbol still cryptic | Rename public exports |
| `non-kebab-filename` | Public file not kebab-case | Rename to `button.tsx` etc. |
| `split-required` | Flat file should be a directory | Split into semantic directory (`/restoration-pipeline`) |
| `unfinalized-checkpoint-imports` | Public file imports `.deobfuscate-javascript/` checkpoint | Promote dependency first |
| `missing-provenance-header` | No `// Restored from ref/...` line | Add D1 provenance |
| `unformatted` | Prettier check failed | `scripts/format.ts` |
| `parse-error` | File does not parse | Fix syntax upstream |

### Full-restoration coverage codes

These fire from `analyzeFullRestorationCoverage()` even when individual files pass — including when `IMPORT_MAP.json` is absent (the stall state).

| Code | Meaning |
|------|---------|
| `full-restoration-checkpoints-not-drained` | `_full/checkpoints/` has files not yet promoted to `restored/` |
| `full-restoration-organize-incomplete` | Chunks reached `stages.finalized` but never `stages.promoted` |
| `full-restoration-public-file-in-hash-dir` | Promoted file lives under `button-bq66r8jD/` instead of semantic domain folder |
| `missing-import-map` | Manifest exists but `IMPORT_MAP.json` is missing |
| `full-restoration-missing-public-output` | Reachable local chunk has no import-map entry |
| `full-restoration-oversized-local` | Deep restore left a chunk as `oversized-local` |
| `full-restoration-app-feature-boundary` | App/feature chunk marked boundary/facade instead of restored |
| `full-restoration-mechanical-app-feature` | App chunk status is `mechanical-readable-restored` |
| `full-restoration-app-feature-not-accepted` | App chunk lacks `stages.finalized` or Stage 3 acceptance record |
| `full-restoration-app-feature-ts-nocheck` | App chunk finished with `@ts-nocheck` |
| `full-restoration-app-feature-facade` | App chunk finished as typed `export declare const` facade |
| `full-restoration-app-feature-empty-placeholder` | App chunk is `export {}` placeholder |
| `full-restoration-npm-boundary-not-resolved` | Known npm boundary still an `any`-facade |

<RequestExample>

```bash
# Deep pre-filter (D0 gate) — naming signal only on a Stage 2 checkpoint
bun scripts/quality-gate.ts "$WS/polished.tsx" --allow-flat --allow-mechanical-names

# Final deliverable gate — provenance required, typing enforced
bun scripts/quality-gate.ts restored/ --check-format

# In-progress whole-tree run — suppress stall checks
bun scripts/quality-gate.ts restored/ --allow-organize-incomplete
```

</RequestExample>

<ResponseExample>

```text
quality-gate: FAIL restored/composer/thread-panel.tsx
  [mechanical-names] Generated fallback names remain: contextParam14, DistO
  [untyped-component-props] Exported component props need explicit TS types: ThreadPanel

quality-gate: FAIL restored/IMPORT_MAP.json
  [full-restoration-checkpoints-not-drained] Mechanical checkpoints exist under _full/checkpoints/ but were not promoted into the public tree
```

</ResponseExample>

### Relaxation flags

Use these only for intermediate checkpoints, never public deliverables:

- `--allow-flat` — suppress `split-required` (intentional single-file artifact)
- `--allow-mechanical-names` — suppress `mechanical-names` (intermediate checkpoint only)
- `--allow-missing-provenance` — suppress provenance header check (pre-D1 candidate)
- `--allow-untyped` — suppress TypeScript typing checks (readable tier)
- `--vendored` — relax semantic naming on faithful vendored modules and boundary facades
- `--allow-organize-incomplete` — suppress checkpoint-drain stall checks during in-progress runs

## Verification checklist

Before reporting completion:

1. **Readable tier:** `quality-gate.ts` passes on promoted files; optional E1 naming self-review
2. **Deep tier:** D0 gate → semantic rewrite → D7 gate → E1–E4 LOOP → target-level `quality-gate.ts <target-dir>` exit 0
3. **Whole tree:** `ledger.ts frontier --stage promote` is empty; every reachable local chunk is `stages.promoted` (deep: + `stages.finalized`)

<Check>
The canonical exemplar for deep-mode Button output is embedded in `scripts/acceptance-checklist.md` — compare candidate files against its shape: typed `Props`, `as const` lookup tables, `forwardRef` + `displayName`, provenance header, bare npm imports.
</Check>

## Related pages

<CardGroup>
<Card title="Restoration pipeline" href="/restoration-pipeline">
Stage 1–3 flow, readable vs deep depth, and the restoration contract that defines done.
</Card>
<Card title="Workspace and output" href="/workspace-and-output">
Staging under `.deobfuscate-javascript/`, promote bar, kebab-case filenames, and `IMPORT_MAP.json`.
</Card>
<Card title="Full tree restoration" href="/full-tree-restoration">
Organize → promote loop, checkpoint drain, and target-level quality-gate coverage.
</Card>
<Card title="Pipeline caveats" href="/pipeline-caveats">
Ordering rules, sourcemap precedence, polish tier differences, and recovery steps.
</Card>
<Card title="Orchestration scripts" href="/orchestration-scripts">
`quality-gate.ts`, `promote-organized.ts`, and `plan-organize.ts` CLI reference.
</Card>
</CardGroup>
