Skip to content
Back to skills

Click Path Audit Edho Ferdian

ASecurity

Trace every user-facing touchpoint (button, toggle, form submit) through its full state-change sequence to find defects that reading code line by line cannot see: handlers whose calls silently undo each other, async races, stale closures, and effects that reset the very state the button just set. Use when a control "does nothing" despite the handler existing and not crashing, after refactoring a shared state store (Zustand/Redux/context/ signals), or before release on critical flows. Trigger ...

  • 5 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 24, 2026
ai-agentsreacttestingdebuggingrefactoringapiperformance

Works with

  • cli
  • api

Security analysis

A100/100

Scanned September 24, 2026

npx -y skills add edhoferdian/EEF --skill click-path-audit-edho-ferdian --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Click Path Audit Edho Ferdian?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Click Path Audit Edho Ferdian
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/edhoferdian-click-path-audit-edho-ferdian/badge)](https://www.skillsdirectory.com/skills/edhoferdian-click-path-audit-edho-ferdian)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: click-path-audit-edho-ferdian
description: >-
  Trace every user-facing touchpoint (button, toggle, form submit) through its
  full state-change sequence to find defects that reading code line by line
  cannot see: handlers whose calls silently undo each other, async races,
  stale closures, and effects that reset the very state the button just set.
  Use when a control "does nothing" despite the handler existing and not
  crashing, after refactoring a shared state store (Zustand/Redux/context/
  signals), or before release on critical flows. Trigger phrases: "tombolnya
  gak jalan", "diklik tapi gak ada yang terjadi", "the button does nothing",
  "state-nya balik lagi", "sudah dicek semua tapi gak ketemu bug-nya".
---

# Click-Path Audit — Edho Ferdian Mode

Ordinary debugging asks: does the handler exist, does it crash, are the types
right. All three can be YES while the button is still broken. This skill asks
the question those three miss:

> **Does the final state match what the control's label promises?**

## The defect class

A "New Email" button called `setComposeMode(true)` and then
`selectThread(null)`. Both functions existed, neither threw, types were
correct — and `selectThread` reset `composeMode: false` as an undeclared side
effect. The button did nothing. A systematic debugging pass that found 54 other
defects missed this one, because nothing about it is visible from either
function in isolation. It only appears when you look at the *sequence*.

## Scope first

This audit is expensive; scope it before starting:

| Scope | When |
|-------|------|
| One control | A user reported one specific broken button |
| One screen | A new page was just built, or one screen misbehaves |
| One store | A shared store action was modified — audit every caller of the changed actions |
| Whole app | Pre-release, or after a refactor that touched shared state broadly |

For a whole-app audit, Step 1 must complete before any Step 2 work begins —
its output is the input for everything else. On a harness with sub-agent
delegation, build the map yourself, then fan out Step 2 to
`click-path-tracer-edho-ferdian` **in parallel** — one delegate per
screen/module, each given the complete map, never building its own
partial one. This is worth the delegation overhead at whole-app scale
(potentially dozens of touchpoints, each independent to trace once the
map exists) but not for the smaller scopes above — trace those inline.
On a harness with no delegation primitive, trace every touchpoint inline
regardless of scope, per Step 2 below.

## Step 1 — Build the side-effect map (mandatory, always first)

For every state store in scope (Zustand store, Redux slice, React context
reducer, signal container, view model), record for each action:

- which fields it **sets**
- which fields it **resets** as a side effect — fields it does not conceptually
  own

```
STORE: emailStore
  setComposeMode(bool)  → sets {composeMode}
  selectThread(t|null)  → sets {selectedThread, selectedThreadId, messages, drafts}
                          RESETS {composeMode: false, composeData: null, redraftOpen: false}
  setDraftGenerating(b) → sets {draftGenerating}

DANGEROUS RESETS (an action clearing state it does not own):
  selectThread → resets composeMode (owned by setComposeMode)
  reset        → resets everything
```

The DANGEROUS RESETS list is the whole point of this step. Every defect this
skill exists to catch lives there. Do not proceed to Step 2 with an incomplete
map — an audit against a partial map produces false confidence, which is worse
than no audit.

## Step 2 — Trace each touchpoint

For every interactive element in scope (`onClick`, `onSubmit`, `onChange`,
keyboard handler, gesture handler):

```
TOUCHPOINT: "New Email" — ThreadList.tsx:88
  HANDLER: onClick
    1. setComposeMode(true)   → sets {composeMode: true}
    2. selectThread(null)     → RESETS {composeMode: false}   ← CONFLICT
  EXPECTED (from the label): a blank compose form opens
  ACTUAL: composeMode is false; nothing renders
  VERDICT: BUG — Sequential Undo
```

Check every trace against these six patterns:

1. **Sequential undo** — a later call resets what an earlier call set. The
   canonical case above.
2. **Async race** — two async calls both write the same field; the final value
   depends on resolution order, not on intent.
3. **Stale closure** — a memoized handler captures an old value, so two
   increments apply the same stale base and the effect happens once, not twice.
4. **Missing transition** — the handler validates, logs, or sets a flag but
   never performs the action the label promises (no API call, no navigation,
   no persistence).
5. **Conditional dead path** — the real work sits behind a condition that is
   always false at that point in the lifecycle.
6. **Effect interference** — the handler sets a field and a watcher/effect
   observing that field immediately resets it.

For each call in a trace, answer four questions: what does it read, what does
it write, does it touch shared state, and does it reset anything as a side
effect.

## Step 3 — Report

```
CLICK-PATH-001 [HIGH]
  Touchpoint: "New Email" — src/components/ThreadList.tsx:88
  Pattern:    Sequential Undo
  Trace:
    1. setComposeMode(true) → sets {composeMode: true}
    2. selectThread(null)   → RESETS {composeMode: false}
  Expected: blank compose form opens
  Actual:   nothing renders; composeMode is false by the end of the handler
  Fix:      reorder (selectThread first, then setComposeMode), or remove the
            undeclared composeMode reset from selectThread and clear it at the
            call sites that actually mean to
```

Severity: **CRITICAL** — a money, auth, or destructive control that silently
does nothing (the user believes the action happened). **HIGH** — a primary
control that does nothing. **MEDIUM** — a control whose final state is partly
wrong. **LOW** — a redundant call with no user-visible effect (dead code, not a
defect).

## Boundaries — what this is not for

- API-level defects (wrong response shape, missing endpoint) — a click-path
  trace ends at the request; take those to normal debugging, and to
  `test-authoring-edho-ferdian/references/regression-testing.md` for the test.
- Styling and layout — visual inspection, or a QA sweep
  (`e2e-testing-edho-ferdian/references/qa-sweep.md`).
- Performance — `performance-audit-edho-ferdian`.

## Handoff — every finding earns a test

A click-path finding is a proven defect with a known reproduction, which makes
it the ideal RED gate. Hand each one to `dev-kickoff-edho-ferdian`'s normal
PLAN → TEST → IMPLEMENT loop: the failing test asserts the *final* state after
the handler runs, not that each individual function was called. A test that
asserts `setComposeMode` was called would have passed against the original bug.

## Language routing (fixed — see skill-authoring-edho-ferdian's canonical contract)

Communication to the user in Bahasa Indonesia; the trace report and call
sequence in English, since it gets pasted into an issue or handed to
`dev-kickoff-edho-ferdian`'s TEST/IMPLEMENT loop. Full contract:
`skill-authoring-edho-ferdian` §7.

## Global rules

1. **Store map before traces, always.** No exceptions; a partial map hides the
   exact defect this skill targets.
2. **Trace in execution order.** The order is the evidence.
3. **Judge against the label, not against the code.** The label is the
   contract with the user.
4. **A finding is a trace, not an opinion.** Every report shows the numbered
   call sequence with the conflicting write marked.
5. **Do not fix inside the audit.** Report, then hand off — an audit that
   starts editing loses its own coverage.

## Growth path

This skill is intentionally single-file. If the defect-pattern list (Step 2)
grows past six patterns, or this file passes ~250-300 lines, split framework-
specific tracing detail (e.g. a Zustand/Redux-specific vs. a signals-specific
lens) into `references/`, following the domain+lens pattern other skills in
this ecosystem use — do not let a single growing file replace that split.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.