Skip to content

Releases: dtduc-git/jevnav

v0.2.0: make the MCP authority boundary explicit and honest

Choose a tag to compare

@dtduc-git dtduc-git released this 25 Sep 08:53

0.2.0: make the MCP authority boundary explicit and honest

An external review of the MCP surface (and the doc claims around it) found
that the gate only covered browse/goal while the README implied the whole
tool set, direct primitives left no trace, upload_files could read any host
path, goto accepted file://, and lighthouse ran an unpinned npx with a
caller-controlled argv.

  • every acting MCP tool writes a kind:"action" record to the same trace as
    decisions (typed values, JS expressions and single-character keys masked);
    read_trace skips action records, read_actions exposes them, SPEC documents
    the record
  • fill_form/upload_files intent resolution goes through the same gate as
    browse (upload's target choice matches the element only, since "upload"
    itself is on the risky list)
  • --file-root (default cwd) bounds upload reads and artifact writes, and
    refuses a default root that is / or the home directory; --allow-file-urls
    opts file:// back in for goto/new_page
  • lighthouse: http(s) only, pinned 13.5.0, URL validated before npx
  • annotations: screenshot/heap_snapshot/trace_stop/dialog_policy destructive
  • cli: --no-eval/--max-candidates now actually reach serve() (dropped before)
  • README/SECURITY/SPEC: gate scope, traced vs replayed, readers not traced,
    --no-trace, masking limits
  • tests: 239 (action records, intent gate + decision steps, file-root and
    symlink escapes, scheme guards, replay --execute on an intent step,
    single-char key masking)

Reviewed by oc-review over three passes (last pass only doc/test nits).

v0.1.15: fix network over MCP, stable request ids, sharper tool docs

Choose a tag to compare

@dtduc-git dtduc-git released this 25 Sep 04:11

0.1.15: fix network over MCP, stable request ids, sharper tool docs

Glama scored the v0.1.14 tool set B 3.4/5; outline was the only C (2.9)
and the server score weights the minimum tool at 40%, so this release
rewrites the terse descriptions and fixes the two real bugs they exposed.

  • network_detail ran response.text() from the MCP handler thread: every
    call over MCP raised a greenlet error. It now goes through on_page like
    every other browser operation.
  • network entries carried live Playwright request/response objects, so the
    MCP layer's json.dumps crashed. network_tail projects serializable
    fields and adds an id; network_detail looks the request up by that id
    (a ring-buffer position shifts once 200 entries are recorded).
  • the id counter is shared across tabs, a tab's recorder is reused when it
    is selected again (no double listeners, history kept), and closed tabs
    are pruned.
  • fill_form check accepts the true-like strings a model sends; outline,
    console, goto, network, network_detail, fill_form and press_key now
    document what they actually return and change.
  • tests: 220 (id round-trip over MCP, ring overflow, tab recorder reuse,
    check values, network json path).

Reviewed by oc-review over three passes (final pass only style nits).

v0.1.14: MCP tool annotations and honest side-effect disclosures

Choose a tag to compare

@dtduc-git dtduc-git released this 23 Sep 12:19

0.1.14: MCP tool annotations and honest side-effect disclosures

Glama's TDQS reads the schema, not just the prose: every tool now carries
MCP annotations, and the nine tools it scored C got descriptions that say
what they do to the page, the disk and later calls.

  • annotations on all 33 tools: readOnlyHint for observation, and
    destructiveHint=true where a call can overwrite or remove state
    (browse, goal, close_page, fill_form, press_key, drag, upload_files,
    read_js); idempotentHint=false where a repeat is not a no-op
    (screenshot/heap_snapshot write timestamped files, scroll is relative,
    trace_start/stop change session state)
  • read_js is documented as arbitrary JavaScript, not observation: its
    annotation set is no longer read-only
  • lighthouse: readOnly=false (npx fetches and runs a second Chrome), and
    it resolves the current URL through on_page instead of crashing when no
    browser has started yet
  • dialog_policy, upload_files, route, emulate, select_page, resize, drag,
    heap_snapshot: descriptions now state persistence, replacement and
    error conditions
  • tests pin the full 33-tool annotation table over the real stdio protocol

jevnav v0.1.13

Choose a tag to compare

@dtduc-git dtduc-git released this 22 Sep 06:57

jevnav 0.1.13 — dependency security patch.

MCP Marketplace flagged five High CVEs in the mcp Python SDK, all of them in
versions the old mcp>=1.2 floor allowed. The floor is now mcp>=1.28.1, the
highest patched version among the advisories:

Advisory CVE Affected Patched
GHSA-3qhf-m339-9g5v CVE-2025-53366 < 1.9.4 1.9.4
GHSA-j975-95f5-7wqh CVE-2025-53365 < 1.10.0 1.10.0
GHSA-9h52-p55h-vw2f CVE-2025-66416 < 1.23.0 1.23.0
GHSA-jpw9-pfvf-9f58 CVE-2026-52869 <= 1.27.1 1.27.2
GHSA-vj7q-gjh5-988w CVE-2026-59950 < 1.28.1 1.28.1

No API changes. The lock stays on mcp 2.2.0 (full suite green); the new floor
was checked by hand at mcp==1.28.1 (MCP test files pass). server.json is
bumped alongside the package and a test now keeps the two versions in sync.

jevnav v0.1.12

Choose a tag to compare

@dtduc-git dtduc-git released this 22 Sep 01:13

jevnav 0.1.12 — the pytest plugin becomes the front door.

  • jev.expect(...) is now recorded on the trace as a verify block, so
    replay --execute checks the outcome instead of only re-running the actions;
    an expectation step reports no drift.
  • A test against a local file records file:<relative>, so its trace can be
    committed and replayed on another machine. examples/pytest-interop/ ships
    one, and this repository's own CI replays it with the same Action users get.
  • The German risky pattern gained kündigen|widerrufen — the recall gap the new
    gate study found ("das abo kündigen" ran through). abmelden stays out: it
    also means "log out".

New docs: the README leads with page truth for agents (outline, styles,
diff) and keeps replay as the evidence layer; docs/why.md is the longer
argument; research/gate-study.md measures the gate — risky patterns at recall
1.00 / precision 0.65, and no wrong decision auto in 24 hard decisions, at the
cost of 61% of the correct ones going to review.

215 tests (214 pass, 1 skip).

jevnav v0.1.11

Choose a tag to compare

@dtduc-git dtduc-git released this 21 Sep 16:08

jevnav 0.1.11 — the secret pattern catches concatenated names.

APIKEY, SECRETKEY, AUTHTOKEN, GITHUB_APIKEY and STRIPE_SECRETKEY all
slipped past the token-boundary pattern and would have landed verbatim in a
committed trace. A suffix branch catches them, while PASS and AUTH stay out
of it so BYPASS_CACHE and OAUTH_REDIRECT_URI do not match. The asymmetry is
deliberate: a missed secret is silent and worse than a false positive, which at
least warns.

ORDER_SPEC moved from page.py to trace.py next to SPEC — it is written
into the run header, and the lazy import it required is gone; page.py keeps a
pointer comment.

213 tests (212 pass, 1 skip).

jevnav v0.1.10

Choose a tag to compare

@dtduc-git dtduc-git released this 21 Sep 15:36

jevnav 0.1.10 — the reorder signal gets the right ground truth.

moved compared the package version, so a trace recorded by 0.1.8 and replayed
by 0.1.9 — identical ordering code — was excused as "re-ranked" while the page
had really reordered. With a release a day, that excused almost every real
reorder. The signal is now page.ORDER_SPEC, bumped only when the shortlist
ordering (ROLE_RANK, global_order, the cap) changes, recorded in every trace as
run.order_spec. Older traces map their tool version onto it (0.1.0 → 0,
0.1.1–0.1.4 → 1, 0.1.5+ → 2); an unknown ordering never excuses movement.

The pytest plugin's secret pattern is anchored on token boundaries:
COMPASS_DIR, MONKEY_PATCH_DIR, KEYCHAIN_PATH, PASSENGER_ROOT,
AUTHOR_NAME and BYPASS_CACHE no longer look like secrets (their values were
being rewritten to value_from_env and replayed as another machine's value),
while PASSWORD123 still does.

213 tests (212 pass, 1 skip).

jevnav v0.1.9

Choose a tag to compare

@dtduc-git dtduc-git released this 21 Sep 14:40

jevnav 0.1.9 — two heuristics become facts.

moved is now excused only when the trace's run.tool differs from the running
version. The page-identical rule had swallowed real DOM reorders — same version
and the same fingerprint set means the order can only have changed on the page.
The reason names both versions, and TraceWriter records tool by default, so
every trace carries the ground truth (the pytest plugin's traces were missing
it).

The pytest plugin rewrites a literal value to value_from_env only when the
variable name looks like a secret (TOKEN, KEY, SECRET, PASSWORD, PASS,
CREDENTIAL, AUTH). A path that happens to equal $PWD or $HOME stays a
literal and says why — rewriting it used to replay as another machine's value.

210 tests (209 pass, 1 skip).

jevnav v0.1.8

Choose a tag to compare

@dtduc-git dtduc-git released this 21 Sep 13:44

jevnav 0.1.8 — replay stays honest across versions, and the plugin stops leaking.

moved compared absolute positions in the shortlist, so any change to the
extractor's ordering turned every step of an old trace into moved forever —
the two committed example traces (written by 0.1.0) had shipped that way since
0.1.1. moved now requires the candidate set to have drifted; an identical set
with a different position is ok, with the re-rank stated in the reason. Both
examples replay all-ok without being regenerated.

The pytest plugin:

  • resolves ${VAR} before extraction and the decision, so a missing variable
    fails the test instead of costing a Jev call first;
  • masks the os.environ["TOKEN"] reflex: a value that already is an environment
    value is recorded by name (value_from_env) with a warning, instead of the
    literal landing in a committed trace.

SPEC.md's candidate table now documents value and rank.

208 tests (207 pass, 1 skip).

jevnav v0.1.7

Choose a tag to compare

@dtduc-git dtduc-git released this 21 Sep 13:05

jevnav 0.1.7 — the release gate, and the pytest plugin.

This release can no longer ship from a red commit: publish.yml and
mcp-registry.yml call ci.yml as a reusable workflow and wait on it. 0.1.5
reached PyPI while CI was red on the same commit; that is now structurally
impossible, not just a rule.

The pytest plugin stops putting secrets in traces and stops losing actions:

  • jev.fill("the password field", "${DEMO_PASSWORD}") reads the value from the
    environment and the trace records only the variable name (value_from_env).
    The docstring used to teach the literal-password flow.
  • fill("") is recorded as the clear it is, and press records its key; both
    used to replay into a KeyError.
  • The fixture uses the shared browser_session, so the browser closes even when
    the test fails.

dom_index is renamed rank — it was the element's position in its frame's
shortlist, never a DOM index. Same order, honest name.

204 tests (203 pass, 1 skip).