Skip to content

Explore: experimental effects planner (--planner effects) - #157

Open
devnacho wants to merge 4 commits into
mainfrom
explore-effects-planner
Open

devnacho wants to merge 4 commits into
mainfrom
explore-effects-planner

Conversation

@devnacho

Copy link
Copy Markdown
Contributor

Adds an experimental effects planner to explore mode, behind sedum explore --planner effects (guided mode only). The weighted walk is still the default.

How it works

  • Jev labels, code plans. Jev answers only closed questions:

    • what each control does, one of 19 effects;
    • what each field asks for, one of 23 roles;
    • for a forward step that stalls, what blocks it.

    Labels are cached per control, so a page structure costs one call. Code plans over an abstract map of states (route template + form fields + step-scoped forward controls) using:

    • class decay, with site-wide controls counted once;
    • forward value that grows with depth;
    • gate boosts and seeded tie-breaking.
  • Scope and route templates. Scoped to the start origin. UUID, ULID and dashed-id path segments fold into one template.

  • Travel learns which URLs restore a state. A state reached at the same URL as the state before it, or whose loaded URL showed a different state, is marked not restorable. It is reached by loading the nearest restorable ancestor and replaying the clean path from there, checking each step.

  • Hysteresis. While the current state still offers an untried forward step, the planner finishes it before moving to another state.

  • Controls that cannot act are skipped. These are left out:

    • disabled, aria-disabled and pointer-events: none targets;
    • targets covered by an unrelated element at every probe point.

    A control whose clicks changed nothing twice is dead in that state. Disabled submits are filled for, then given up if they stay disabled.

  • The whole budget is used. When the plan runs out: reload, then sweep what is left, then start a fresh session (the cookies and storage the run started with) and replay to the deepest states. After that the walk planner spends the remaining steps (effects.walkFrom in result.json).

  • Accounts. Credentials typed into a sign-up form that moved on are reused for sign-in forms, and steps a sign-in gate blocked are re-opened once signed in. Emails and usernames carry a per-run token.

  • Forms.

    • Only the target's own form is filled, and never before a link to another page.
    • A link to the current page never counts as a forward step.
    • A dialog is one state wherever it opens.

Explore mode's detectors, safety questions, --safe and trace/result format are unchanged. result.json additionally carries planner and effects (states, maxDepth, walkFrom).

Measured: walk vs effects, 150 steps, seeds 1–3

Deepest flow = furthest stage of each site's purchase funnel. Values are seed 1/2/3, with the step at which that stage was reached. The effects runs' Jev cost includes the walk planner's calls after the handover.

site planner steps (effects/walk) route templates route depth map depth deepest flow (step) Jev $ (mean) findings
toolshop walk 150/150/150 6/6/7 4/2/3 – 1/7 (10), 3/7 (72), 1/7 (1) 0.0286 2/2/1
toolshop effects 150/150/150, no handover 18/14/19 5/3/5 7/11/10 1/7 (24), 4/7 (19), 7/7 (143) 0.0052 4/3/6
demoblaze walk 150/150/150 4/4/4 2/2/2 – 4/6 (122), 6/6 (86), 1/6 (1) 0.0077 1/1/1
demoblaze effects 101+49 / 91+59 / 107+43 4/4/4 2/2/1 3/3/2 6/6 on all (37, 38, 45) 0.0052 1/1/1
saucedemo walk 150/150/150 6/6/7 2/2/4 – 6/6 (57, 122, 110) 0.0072 0/0/0
saucedemo effects 68+82 / 58+92 / 63+87 7/6/6 4/3/4 4/4/4 6/6 (19, 16, 16) 0.0060 0/0/0

Funnels:

  • toolshop: product → add → /checkout → proceed → address → payment → confirm
  • demoblaze: product → add → cart → place order → form filled → purchase
  • saucedemo: add → cart → checkout info → info filled → overview → complete

SauceDemo was not used for tuning. It starts signed in as standard_user via --cookies.

Verification

  • pnpm typecheck, eslint and prettier are clean.
  • pnpm test: 1391 passed, 254 skipped.
  • With SEDUM_BROWSER_INTEGRATION=1, the effects fixture-shop integration test and the explore suites pass.
  • CodeScene: every changed file scores 10.0, and pre_commit_code_health_safeguard passes.

Known gaps

  • On toolshop, seed 1 spent its budget on the signed-in account area and never reached checkout. Seed 2 stopped at the sign-in step.
  • Back-links in a wizard's step indicator that Jev labels proceed still cost a step or two.
  • Gate retries on large forms (profile, change password) can take around 10 steps.
  • On demoblaze, "Purchase" is not recognised as progress: the confirmation overlay is outside the dialog the planner is scoped to.

https://ampcode.com/threads/T-1e692c7c-8490-4324-ab0f-e524e1999732

ampagent and others added 2 commits October 17, 2026 13:53
Jev labels each control class once with a closed list of 19 effects,
each field with a role, and answers a gate question when a forward step
stalls. Code plans over an abstract state map (route template + form
fields + step-scoped forward controls) with class decay, site-wide
chrome, reveal-by-toggle, travel by replayed clean path or URL, forward
value that grows with depth, gate boosts and seeded tie-breaking.

Scope is the start origin; UUID/ULID-like and dashed id segments fold
into one route template. Explore mode's detectors, safety questions,
--safe and trace/result format are unchanged; walk stays the default.

Amp-Thread-ID: https://ampcode.com/threads/T-1e692c7c-8490-4324-ab0f-e524e1999732
Co-authored-by: Ignacio Gutierrez <nachojgutierrez@gmail.com>
…n-in

- Travel: a URL is not trusted to restore a state. A state reached at the
  same URL as the one before it, or whose loaded URL showed another state,
  is not restorable; it is reached by loading the nearest restorable state
  and replaying the clean path from there. Each replayed step is checked.
- Hysteresis: while the current state offers an untried forward step, the
  plan stays on it.
- Dead controls: disabled, aria-disabled, pointer-events: none and covered
  targets are left out; a control whose clicks changed nothing twice is dead
  in that state. Disabled submits are filled for, and given up if they stay
  disabled.
- Budget: when the plan is used up, reload, sweep what is left, replay to
  the deepest states in a fresh session (back to the run's starting cookies
  and storage), then hand the rest to the walk planner (effects.walkFrom).
- Accounts: credentials typed into a sign-up form that moved on are used
  for sign-in forms; sign-in-gated steps re-open once signed in. Email and
  username carry a per-run token.
- Forms: fill only the target's own form, never before a link to another
  page; a link to the current page is never a forward step.
- Dialogs are one state wherever they open; typed values name their source
  as format.field.<role>, format.account.<role> or format.newPassword.

Amp-Thread-ID: https://ampcode.com/threads/T-1e692c7c-8490-4324-ab0f-e524e1999732
Co-authored-by: Ignacio Gutierrez <nachojgutierrez@gmail.com>
@coldtea-pr-lens

coldtea-pr-lens Bot commented Oct 17, 2026 •

Copy link
Copy Markdown
  • Redraw · drawn at acfc210, the branch has moved on

Architecture

Architecture diagram for sedum-dev/sedum at acfc210

Play the walkthrough

Inside the changed components — 1 view

Component view — Effects planner subsystem

Internal modules of the effects planner:⁠ labeling, state mapping, form filling, and session handling.

Architecture view of Component view — Effects planner subsystem in sedum-dev/sedum

Data flow

Data flow diagram for sedum-dev/sedum at acfc210

Follow each request


Review

✨ Nothing flagged · reviewed acfc210


Tip

Open a diagram on the canvas, then press W or click play to walk through the change one step at a time

🪧 More tips
  • Run npx skills add coldteadotai/pr-lens, then tell your coding agent: "Diagram the change you just made with PR Lens and attach it to the pull request."
  • Run npx @coldtea/pr-lens-cli analyze --base origin/main on a branch, then npx @coldtea/pr-lens-cli render .pr-lens/graph.json. Same lenses, your own model key, before the pull request exists
  • Click the link under each diagram to open it on a canvas you can zoom, pan and step through
  • The diagrams are links. Click one to open it on the canvas, then press W or click play to walk through the change
  • The CLI's render reads .github/pr-lens.yml and applies your renames, exclusions and lane pins at draw time
  • Set github.comment.collapsed: true in .github/pr-lens.yml to fold the comment behind one View architecture and data flow row. Drawing still runs as before
  • Set github.draw: on-demand in .github/pr-lens.yml and PR Lens stops drawing pull requests on its own. Comment @pr-lens draw on a pull request when you want that one drawn
  • Add .github/workflows/pr-lens.yml with coldteadotai/pr-lens/packages/action@v0 and your model provider's key as its api-key to run PR Lens from your own CI. Any /chat/completions endpoint works
  • After a push, tick Redraw to draw the latest commit
  • Switch GitHub to dark mode and the diagrams follow. The moving dots are this pull request's data in motion

Thanks for using PR Lens! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out on X, Bluesky, Mastodon, Reddit or LinkedIn

codescene-access[bot]

This comment was marked as outdated.

…eep their class

- Form scoping looked the target up by its data-sedum-ref, but click refs
  are gone once the fields are scanned, so every fill on the page was
  typed. The target is now found by the scanner's element path, shared
  with the liveness check (element-path.ts).
- A submit its form did not enable was recorded as a click failure, so two
  such steps closed the control's class site-wide and the same control,
  enabled elsewhere, was never tried. It now gives up that record only.

Both are covered by browser tests on small served pages.

Amp-Thread-ID: https://ampcode.com/threads/T-1e692c7c-8490-4324-ab0f-e524e1999732
Co-authored-by: Ignacio Gutierrez <nachojgutierrez@gmail.com>
codescene-access[bot]

This comment was marked as outdated.

…etry

- A disabled button no longer joins the record or class of the same
  enabled control, so a record's second try never targets a disabled
  member (which resolved to a different, enabled one).
- A travel load that failed (timeout, dropped connection) counts as a
  failed trip; it no longer marks the URL as not restoring its state.
- Credentials are kept per state until a submit there moves on: a refill
  after a rejected sign-up adds to what the form was given, so the
  account is still recorded when the retry succeeds.

Amp-Thread-ID: https://ampcode.com/threads/T-1e692c7c-8490-4324-ab0f-e524e1999732
Co-authored-by: Ignacio Gutierrez <nachojgutierrez@gmail.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants