Skip to content

v1.0.0

Choose a tag to compare

@divshekhar divshekhar released this 22 Jun 07:09

[1.0.0] — 2026-06-22

The 1.0 release. Iris is stable, documented, and benchmarked end to end: every package is versioned
1.0.0 under the open-core license split, and the same verify loop that wins on a toy app stays the
cheapest way to observe a real production dashboard.

The headline is the "lean responses" pass — same observations, fewer tokens. On the cross-tool
detection benchmark Iris's average observation cost drops 959 → 815 tokens with detection unchanged at
1.0 and zero false positives, lifting Verification Efficiency past the best external tool (12.27 vs
10.55) while remaining the only tool that catches every regression. Re-verifying a saved suite costs
47 tokens with no model and 0% flake, up to 2,574× cheaper than re-driving it with an LLM.

Added

  • Honest, reproducible benchmarks with a small-app vs real-app story. A committed benchmark image
    set (re-run efficiency, the two-apps small-vs-real comparison, the per-tool cost on the real Syrin
    dashboard, and a capability matrix) rendered from a public source pipeline (assets/benchmarks +
    a shared design system), with the methodology written up in docs/benchmarks.md.
    On a real production dashboard Iris observes a page for 1,023 tokens vs Chrome DevTools MCP's 1,357
    and Playwright MCP's 2,193, and is the only tool that asserts success from the app's own signal.
  • Documentation set — an architecture overview, the benchmarks explainer,
    an expanded getting-started, and a Mintlify configuration so the docs
    publish as a site.
  • Open-source project hygieneCONTRIBUTING.md, CODE_OF_CONDUCT.md, issue and pull-request
    templates, plus contributor / stargazer / forker recognition in the README.

Changed

  • iris_act collapses a clean action to its consequence — the effect block now omits fields at
    their uninformative default (an absent dispatched/targetMatched/visible/enabled means true;
    an absent focusMoved/occludedBy means null; an absent occluded/scrolledIntoView/
    valueChanged/defaultPrevented means false), so a successful click returns just domMutatedWithin
    and any real signal still surfaces. No information is lost — absence always means the boring value.
  • MCP tool results serialize as compact JSON by default — the agent-facing text content drops the
    two-space indentation (the typed structuredContent is unchanged), ~40% cheaper on the structured
    payloads that dominate. Set IRIS_ENCODING=pretty for the previous indented form; IRIS_ENCODING=toon
    remains the densest tabular encoding.
  • iris_act_and_wait returns a reaction digest, not the full timelinetrace is now
    { window_ms, summary } (the counts that answer "what did the app do?") plus a since cursor; the full
    per-event timeline is one iris_observe { since } away when the counts aren't enough. On a large DOM the
    dropped events array was the bulk of the loop cost — a verify loop on a 5,000-row grid falls from ~531 to
    ~279 tokens with the consequence still asserted from the row:approved signal.

Fixed

  • Multiple apps on one machine no longer collide or orphan the daemon. Several Next.js / React apps
    (or browser tabs) can run at once: the @syrin/iris-next integration now defaults to a unique per-tab
    session id (SESSION_AUTO) instead of a shared constant, so two Next apps never silently evict each
    other. A bridge/daemon port collision now fails fast with a clear error instead of hanging forever
    and leaving an orphaned process — the listen() calls finally handle EADDRINUSE.
  • License files now carry a real copyright. Filled the Apache-2.0 appendix in every SDK package
    license so no [yyyy] / [name of copyright owner] placeholders remain.

Security

  • Daemon mode now enforces the documented auth contract. iris serve / the MCP daemon previously
    built its bridge without forwarding the pairing token, bind host, or origin allow-list, so
    IRIS_TOKEN / IRIS_HOST / IRIS_ALLOWED_ORIGINS were silently ignored in daemon mode. They are now
    honored identically to the in-process path. (Residual risk was bounded — the daemon is loopback-pinned —
    but the advertised control is now actually enforced.)
  • Every security-critical environment variable is a single named constant (IrisEnv in
    @syrin/iris-protocol). A typo in an inline 'IRIS_TOKEN' string could previously have disabled auth
    silently; the names now live in exactly one place.