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 +86 -3
- package/README.md +11 -9
- package/dist-pkg/cli.js +211 -205
- 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,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
|
|
122
|
-
|
|
123
|
-
|
|
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
|
-
[
|
|
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
|
|