saffron-ai 0.9.4 → 0.9.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,143 @@ the VS Code extension (`ChathurangaJayasinghe.saffron-vscode`) and the
5
5
  JetBrains plugin (`ai.saffron.jetbrains`). Dates are publish dates. Each
6
6
  release heading names its main feature: `## <version>: <title>`.
7
7
 
8
+ ## 0.9.6: Dashboard figures you can trust
9
+
10
+ Released 2026-10-05.
11
+
12
+ Runner
13
+
14
+ - **Three dashboard figures no longer flatter the suite.** *Recorded*
15
+ counted a stale recording, one whose scenario was edited since and
16
+ needs the agent again, so the dashboard could say 100% while `saffron
17
+ status` said otherwise; it now counts current recordings only, and at
18
+ 100% says "every scenario has a current recording". *Passing* and the
19
+ last run's pass rate counted a heal whose zero-AI proof had failed;
20
+ such a heal is now "healed, unverified", out of the pass rate, with its
21
+ own stripe in the health bar, a count on the tiles and a mark in the
22
+ healed-again list. *Flaky* counted a scenario that was red on one base
23
+ URL and green on another as flipping; flips are now counted between
24
+ consecutive runs on the same base URL, and a first recording that
25
+ failed is left out. `status --json` gains `quality.suite.unverified`,
26
+ `quality.lastRun.unverified`, and `unverified` on tags and healing
27
+ entries. Both IDE dashboards show the runner's page, so they follow
28
+ without a plugin update.
29
+ - **An upload whose file does not exist says so.** Under a project path
30
+ reached through a link (a temp folder on macOS), the message was
31
+ "outside the project". The repository's own example now names its
32
+ upload file relative to the project, as replay has resolved it since
33
+ 0.9.4.
34
+ - **Uploads are single files.** A folder passed to a file input was let
35
+ through, and a folder upload sends everything inside it, dotfiles such
36
+ as `.env` included. The agent's upload and replay both refuse a folder
37
+ now.
38
+ - **`saffron report --merge` never hides another environment's result.**
39
+ A re-run attempt replaced the earlier attempt of the same shard number
40
+ before checking that both ran the same suite against the same base
41
+ URL, so a green production attempt could silently drop a red staging
42
+ one. An attempt now replaces only the same shard of the same suite,
43
+ split and base URL; anything else is refused, naming the base URLs.
44
+ - **`saffron export --branch` works with `"features": "."`.** With the
45
+ scenarios at the project root, the shared StepSets were left out of the
46
+ check against the commit the branch starts on, so a correctly bound
47
+ proposal was refused as using a StepSet "not defined anywhere".
48
+ - A replay that finds its recording stale no longer leaves a listener on
49
+ the browser context.
50
+
51
+ VS Code extension 0.5.1
52
+
53
+ - **The dashboard tab shows the Saffron mark in dark themes.** It used the
54
+ activity bar icon, one dark shape that VS Code tints there and a tab
55
+ draws as is, so it was dark on a dark tab.
56
+ - **Cancelling an import stops every process it started, on macOS and
57
+ Linux too.** The CLI runs in a process group of its own, so a `gh` or
58
+ `az` download that outlives it is stopped as well, with a forced stop
59
+ for one that ignores the first request. Output over 16 MB ends the
60
+ command with a clear message.
61
+
62
+ ## 0.9.5: CI heals you can trust
63
+
64
+ Released 2026-10-04.
65
+
66
+ Runner
67
+
68
+ - **A recording can only use the environment variables its scenario
69
+ names.** Replay fails any other `{env:...}` by name, so a recording
70
+ someone commits, or a CI bundle you import, cannot read the rest of
71
+ your environment. The run's preflight checks the same set, masking
72
+ covers exactly what can resolve, and a `{env:...}` or `{data:...}`
73
+ the agent typed as plain text is recorded escaped and never resolves.
74
+ An outline whose Examples rows hold different `{env:...}` values now
75
+ replays each row with its own variable.
76
+ - **Replay opens only http(s) pages and uploads only project files.**
77
+ Recorded navigation and new tabs refuse `data:` URLs, other `about:`
78
+ pages and other schemes, at replay and during recording. Upload paths
79
+ resolve against the project root, wherever saffron was started from.
80
+ - **Proposals that came from elsewhere are not run with your secrets.**
81
+ A run replays a pending proposal at zero AI only when this machine
82
+ filed it. One imported from a CI run, or checked out from a heal
83
+ branch, is never replayed, healed over or recorded over: the scenario
84
+ reports yellow, pending review, with how to review it and the CI run
85
+ it came from. `--strict` fails on it like on any yellow; `saffron run
86
+ --rerecord` records over it. A CI build of a heal branch therefore
87
+ reports yellow until the proposals are accepted, and does not heal
88
+ again. After upgrading, a proposal filed by an earlier version is
89
+ reported as pending review on its first run: accept or reject it.
90
+ - **Heal once.** When a committed recording fails and a heal filed on
91
+ this machine is still pending, the run replays that heal before
92
+ calling the agent. If it passes, the scenario is yellow, covered by
93
+ the pending proposal, so the next run and the outline's other Examples
94
+ rows do not pay for another heal. This works under `--no-agent` too.
95
+ - **`saffron import --run` asks the CI service who started the run.** A
96
+ run started by a fork's pull request is refused unless you pass
97
+ `--allow-fork`, and a downloaded bundle that names a different run
98
+ from the one you asked for is refused.
99
+ - **`saffron accept --all` takes only what you reviewed one by one.** It
100
+ skips proposals imported from a CI run unless you pass
101
+ `--include-imported`, and treats a proposal no proof replay checked as
102
+ unverified (`--include-unverified` to take it). Proposal files you name
103
+ are accepted as before. The Accept All buttons in both IDEs run this
104
+ command, so they are covered too.
105
+ - **Re-runs and shards.** Import takes the latest attempt of a whole run
106
+ exported more than once, reports a conflict when shards of one run
107
+ filed different proposals for the same scenario, and refuses two
108
+ bundles holding the same shard. `--shard-by scenario` keeps all rows
109
+ of a Scenario Outline on one shard. Shard reports record the CI
110
+ attempt, and `saffron report --merge` merges the latest attempt of a
111
+ re-run shard.
112
+ - **Feature edits are shown before they are applied.** `saffron diff`
113
+ (text and `--json`) and the draft pull request list the feature file
114
+ edits `saffron accept --with-feature-edit` would apply, and mark an
115
+ edit to a step set's step, which changes every scenario using it.
116
+ Feature edits can no longer hold line breaks or control characters,
117
+ accept skips one that would make the scenario name a new environment
118
+ variable, and every reader refuses a recording that names a feature
119
+ file outside the project.
120
+ - **Text from a proposal, report or trace is printed as text.** The HTML
121
+ report and the `saffron trace` replay page escape every value, the
122
+ replay page runs under a Content-Security-Policy with sandboxed
123
+ snapshot frames, and `saffron diff`, `saffron accept` and the pending
124
+ listing strip terminal control sequences. `saffron import` refuses a
125
+ bundle whose zip holds a file twice, or whose report has a step status
126
+ or counts no run writes.
127
+ - **Reports name proposal files relative to the project**, so a report
128
+ read on another checkout points at the right file. Older reports still
129
+ work.
130
+ - Messages use plain punctuation, the missing `{env:VAR}` error
131
+ included.
132
+ - **The dashboard's Failing count no longer forgets an old failure.** It
133
+ counted only failures from the last 10 runs, so a scenario that failed
134
+ and was then left out of ten runs read "all clear" while the health
135
+ bar still showed it red. It now counts each scenario's latest result,
136
+ as the health bar does.
137
+
138
+ JetBrains plugin 0.5.1
139
+
140
+ - **The Dashboard never shows another project's page.** A page still
141
+ loading when you switched projects (or when the tab was hidden) could
142
+ land afterwards and stay on screen; it is now dropped. Clicking a
143
+ scenario opens it in the project the page was made for.
144
+
8
145
  ## 0.9.4: The suite's quality at a glance
9
146
 
10
147
  Released 2026-10-04.
@@ -118,9 +255,9 @@ Runner
118
255
  `az` is missing, signed out or failing answers `{provider, branch,
119
256
  runs: [], problem: {kind, message}, error}`, `error` holding the same
120
257
  message, so a client reading either field works; any other failure is
121
- `{"error": ...}` alone; both exit 2. On Azure Pipelines the pull
122
- request builds are asked for once (`--top 500`), so a listing usually takes
123
- three `az` calls, not seven.
258
+ `{"error": ...}` alone; both exit 2. On Azure Pipelines each listing
259
+ asks for 50 builds first, and for more, up to 500, only while too few
260
+ are the branch's.
124
261
  `export --branch` opens the draft pull request on Azure DevOps too,
125
262
  through `az repos pr create`.
126
263
  - **Export streams the bundle to disk.** Screenshots and traces are
package/README.md CHANGED
@@ -74,7 +74,7 @@ node dist/cli/index.js -p examples accept --all
74
74
  | Command | What it does |
75
75
  |---|---|
76
76
  | `saffron run [paths] [--headed] [--filter expr] [--rerecord] [--no-agent] [--strict] [--browser b] [--no-hooks] [--workers n] [--heal-model m] [--no-verify] [--no-reuse] [--model m] [--storage-state f] [--trace mode]` | Run features. Cached replays are deterministic; misses/failures escalate to the agent (unless `--no-agent`). Replay cross-browser with `--browser firefox\|webkit`, parallelize with `--workers N`, heal on a cheaper model with `--heal-model`, keep an execution trace with `--trace retain-on-failure`. Exit 1 on red (and on yellow with `--strict`). |
77
- | `saffron accept [files... \| --all] [--include-unverified] [--with-feature-edit] [--propagate]` | Promote cache proposals to committed caches (`--all` skips UNVERIFIED ones unless `--include-unverified`); `--with-feature-edit` also rewrites the adapted steps in the `.feature` file (and keeps the cache in sync); `--propagate` applies the heal's locator fixes to every other cache using the same locator. One heal repairs N scenarios before they ever fail. No args: list pending proposals. |
77
+ | `saffron accept [files... \| --all] [--include-unverified] [--include-imported] [--with-feature-edit] [--propagate]` | Promote cache proposals to committed caches (`--all` skips UNVERIFIED ones unless `--include-unverified`, and ones imported from a CI run unless `--include-imported`); `--with-feature-edit` also rewrites the adapted steps in the `.feature` file (and keeps the cache in sync); `--propagate` applies the heal's locator fixes to every other cache using the same locator. One heal repairs N scenarios before they ever fail. No args: list pending proposals. |
78
78
  | `saffron reject [files... \| --all]` | Discard proposals; the agent will try again next run. |
79
79
  | `saffron export [-o file] [--branch name]` / `saffron runs` / `saffron import <bundles...> \| --run <id>` | Carry a CI heal to your machine: export packs the run's proposals, report, screenshots and traces into one bundle for CI to upload; `runs` lists the branch's CI runs (GitHub Actions or Azure Pipelines); import (of a file, or of a run with `--run`) checks the bundle against your checkout (repository, each proposal's binding) and files it there, ready for `saffron diff` and `saffron accept`. `--branch` also has CI commit the proposals to a new branch and open a draft pull request with their diffs. |
80
80
  | `saffron status [--json]` | Project overview for people, IDE panels and dashboards: feature files and scenarios with cache state, tags, pending proposals, last run, history, vocabulary health (divergent steps, duplicate wordings proven by identical recordings), effective config, and suite quality from the run history (failing, flaky, never run, slowest, trends, per tag). |
@@ -120,7 +120,7 @@ experimental; `npx saffron login antigravity` once) or `cursor`
120
120
  (`npm i -D @cursor/sdk`, then `npx saffron login cursor`). `model` takes
121
121
  that provider's model names. `npx saffron login` says what a provider
122
122
  still needs on this machine. Every sign-in flow is in
123
- [docs/PROVIDERS.md](docs/PROVIDERS.md).
123
+ [AI providers and sign-in](https://saffron-ai.io/docs/ai-providers).
124
124
 
125
125
  `storageState` (also `--storage-state`) points to a Playwright storage-state
126
126
  JSON (cookies + localStorage) applied to every scenario's browser context, so
@@ -150,13 +150,15 @@ features/ your .saffron and .feature files
150
150
 
151
151
  ## Roadmap
152
152
 
153
- See the roadmap on **[the site](https://saffron-ai.io/#roadmap)**, the single source of truth for
154
- milestones, statuses, and decision gates. Headlines:
155
- action-vocabulary additions as real-world failures surface them, the
156
- Level-2 shared step library (gated on Level-1 divergence data), LLM-less
157
- MCP replay, multi-provider agents, parallel workers, public npm/GitHub
158
- release, and the long-term open-core SaaS layer. Everything shipped so
159
- far is in the roadmap's "Where we are" table.
153
+ The roadmap is at **[saffron-ai.io/docs/roadmap](https://saffron-ai.io/docs/roadmap)**:
154
+ milestones, statuses and decision gates, and everything shipped so far in
155
+ its "Where we are" table.
156
+ Headlines ahead: API testing (reusable REST operations, fixtures and schema
157
+ validation), scenarios with two users in two browsers, a configurable
158
+ features folder, running one scenario (`file:line`, with run icons in both
159
+ IDEs), parallel recording and a browser matrix in one run, failure video,
160
+ agent-blind secrets, LLM-less MCP replay, the Level-2 shared step library
161
+ (gated on Level-1 divergence data), and the long-term open-core SaaS layer.
160
162
 
161
163
  ## Documentation
162
164