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 +140 -3
- package/README.md +11 -9
- package/dist-pkg/cli.js +231 -225
- package/package.json +1 -1
- package/skills/saffron/references/config.md +7 -5
- package/skills/saffron/references/syntax.md +1 -1
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
|
|
122
|
-
|
|
123
|
-
|
|
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
|
-
[
|
|
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
|
-
|
|
154
|
-
milestones, statuses
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
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
|
|