saffron-ai 0.9.4 → 0.9.5

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,89 @@ 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.5: CI heals you can trust
9
+
10
+ Released 2026-10-04.
11
+
12
+ Runner
13
+
14
+ - **A recording can only use the environment variables its scenario
15
+ names.** Replay fails any other `{env:...}` by name, so a recording
16
+ someone commits, or a CI bundle you import, cannot read the rest of
17
+ your environment. The run's preflight checks the same set, masking
18
+ covers exactly what can resolve, and a `{env:...}` or `{data:...}`
19
+ the agent typed as plain text is recorded escaped and never resolves.
20
+ An outline whose Examples rows hold different `{env:...}` values now
21
+ replays each row with its own variable.
22
+ - **Replay opens only http(s) pages and uploads only project files.**
23
+ Recorded navigation and new tabs refuse `data:` URLs, other `about:`
24
+ pages and other schemes, at replay and during recording. Upload paths
25
+ resolve against the project root, wherever saffron was started from.
26
+ - **Proposals that came from elsewhere are not run with your secrets.**
27
+ A run replays a pending proposal at zero AI only when this machine
28
+ filed it. One imported from a CI run, or checked out from a heal
29
+ branch, is never replayed, healed over or recorded over: the scenario
30
+ reports yellow, pending review, with how to review it and the CI run
31
+ it came from. `--strict` fails on it like on any yellow; `saffron run
32
+ --rerecord` records over it. A CI build of a heal branch therefore
33
+ reports yellow until the proposals are accepted, and does not heal
34
+ again. After upgrading, a proposal filed by an earlier version is
35
+ reported as pending review on its first run: accept or reject it.
36
+ - **Heal once.** When a committed recording fails and a heal filed on
37
+ this machine is still pending, the run replays that heal before
38
+ calling the agent. If it passes, the scenario is yellow, covered by
39
+ the pending proposal, so the next run and the outline's other Examples
40
+ rows do not pay for another heal. This works under `--no-agent` too.
41
+ - **`saffron import --run` asks the CI service who started the run.** A
42
+ run started by a fork's pull request is refused unless you pass
43
+ `--allow-fork`, and a downloaded bundle that names a different run
44
+ from the one you asked for is refused.
45
+ - **`saffron accept --all` takes only what you reviewed one by one.** It
46
+ skips proposals imported from a CI run unless you pass
47
+ `--include-imported`, and treats a proposal no proof replay checked as
48
+ unverified (`--include-unverified` to take it). Proposal files you name
49
+ are accepted as before. The Accept All buttons in both IDEs run this
50
+ command, so they are covered too.
51
+ - **Re-runs and shards.** Import takes the latest attempt of a whole run
52
+ exported more than once, reports a conflict when shards of one run
53
+ filed different proposals for the same scenario, and refuses two
54
+ bundles holding the same shard. `--shard-by scenario` keeps all rows
55
+ of a Scenario Outline on one shard. Shard reports record the CI
56
+ attempt, and `saffron report --merge` merges the latest attempt of a
57
+ re-run shard.
58
+ - **Feature edits are shown before they are applied.** `saffron diff`
59
+ (text and `--json`) and the draft pull request list the feature file
60
+ edits `saffron accept --with-feature-edit` would apply, and mark an
61
+ edit to a step set's step, which changes every scenario using it.
62
+ Feature edits can no longer hold line breaks or control characters,
63
+ accept skips one that would make the scenario name a new environment
64
+ variable, and every reader refuses a recording that names a feature
65
+ file outside the project.
66
+ - **Text from a proposal, report or trace is printed as text.** The HTML
67
+ report and the `saffron trace` replay page escape every value, the
68
+ replay page runs under a Content-Security-Policy with sandboxed
69
+ snapshot frames, and `saffron diff`, `saffron accept` and the pending
70
+ listing strip terminal control sequences. `saffron import` refuses a
71
+ bundle whose zip holds a file twice, or whose report has a step status
72
+ or counts no run writes.
73
+ - **Reports name proposal files relative to the project**, so a report
74
+ read on another checkout points at the right file. Older reports still
75
+ work.
76
+ - Messages use plain punctuation, the missing `{env:VAR}` error
77
+ included.
78
+ - **The dashboard's Failing count no longer forgets an old failure.** It
79
+ counted only failures from the last 10 runs, so a scenario that failed
80
+ and was then left out of ten runs read "all clear" while the health
81
+ bar still showed it red. It now counts each scenario's latest result,
82
+ as the health bar does.
83
+
84
+ JetBrains plugin 0.5.1
85
+
86
+ - **The Dashboard never shows another project's page.** A page still
87
+ loading when you switched projects (or when the tab was hidden) could
88
+ land afterwards and stay on screen; it is now dropped. Clicking a
89
+ scenario opens it in the project the page was made for.
90
+
8
91
  ## 0.9.4: The suite's quality at a glance
9
92
 
10
93
  Released 2026-10-04.
@@ -118,9 +201,9 @@ Runner
118
201
  `az` is missing, signed out or failing answers `{provider, branch,
119
202
  runs: [], problem: {kind, message}, error}`, `error` holding the same
120
203
  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.
204
+ `{"error": ...}` alone; both exit 2. On Azure Pipelines each listing
205
+ asks for 50 builds first, and for more, up to 500, only while too few
206
+ are the branch's.
124
207
  `export --branch` opens the draft pull request on Azure DevOps too,
125
208
  through `az repos pr create`.
126
209
  - **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