saffron-ai 0.9.3 → 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,133 @@ 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
+
91
+ ## 0.9.4: The suite's quality at a glance
92
+
93
+ Released 2026-10-04.
94
+
95
+ Runner
96
+
97
+ - **The agent skill knows the new features.** It shows tag expressions
98
+ in `--filter`, `saffron trace`, and a CI job that exports its heals as
99
+ a bundle (or a draft pull request) for `saffron runs` and `saffron
100
+ import --run`. The AGENTS.md / CLAUDE.md block `saffron init` writes
101
+ says how a CI heal arrives, and the `project_status` MCP tool says
102
+ which run an imported proposal came from. Run `npx saffron init` again
103
+ to update a project's copy.
104
+ - **`saffron dashboard`: the suite's quality at a glance.** A page in
105
+ the run report's design, read from `.saffron/history.jsonl`: tests,
106
+ the share passing (each scenario's latest result), failing scenarios
107
+ and for how many runs in a row, flaky ones (passed and failed by turns
108
+ over the last 20 runs), ones the agent healed again and again, never
109
+ run and left out of the last run, the slowest, pass rate and execution
110
+ time per run, and results per tag. It writes
111
+ `.saffron/reports/dashboard.html` and opens it; `--stdout` prints the
112
+ page for the IDE panels. The same numbers are in `saffron status
113
+ --json` as `quality`.
114
+
115
+ VS Code extension 0.5.0
116
+
117
+ - **The dashboard is the suite's quality page**, the one `saffron
118
+ dashboard` renders, instead of the run report. Click a scenario's
119
+ name to open it. Needs saffron-ai 0.9.4 or later.
120
+ - **Last run: Open Replay and Open Report in the title bar.** Open
121
+ Replay opens every scenario the run traced, so it works when
122
+ everything passed and no row is listed; Open Report opens the HTML
123
+ report in the browser.
124
+
125
+ JetBrains plugin 0.5.0
126
+
127
+ - **The Dashboard is the suite's quality page**, the same one as in VS
128
+ Code, instead of the embedded run report. Click a scenario's name to
129
+ open it. Needs saffron-ai 0.9.4 or later.
130
+ - **Last Run: Open Report** opens the run's HTML report in the browser.
131
+ - **Last Run: Open Replay works when everything passed.** With no row to
132
+ select it did nothing; it now opens every scenario the run traced, or
133
+ says how to keep traces when the run kept none.
134
+
8
135
  ## 0.9.3: Review CI heals on your machine
9
136
 
10
137
  Released 2026-10-04.
@@ -74,9 +201,9 @@ Runner
74
201
  `az` is missing, signed out or failing answers `{provider, branch,
75
202
  runs: [], problem: {kind, message}, error}`, `error` holding the same
76
203
  message, so a client reading either field works; any other failure is
77
- `{"error": ...}` alone; both exit 2. On Azure Pipelines the pull
78
- request builds are asked for once (`--top 500`), so a listing usually takes
79
- 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.
80
207
  `export --branch` opens the draft pull request on Azure DevOps too,
81
208
  through `az repos pr create`.
82
209
  - **Export streams the bundle to disk.** Screenshots and traces are
package/README.md CHANGED
@@ -74,16 +74,17 @@ 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
- | `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. |
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). |
81
81
  | `saffron steps [search] [--json] [--snippets]` | List/search the step vocabulary (files + caches) with recorded/divergent/unrecorded badges and usage; `--snippets` writes `.vscode/saffron.code-snippets` for native VS Code completion. |
82
82
  | `saffron mcp` | Serve the vocabulary and the project overview to AI assistants over stdio MCP (`search_steps`, `list_step_sets`, `project_status`), e.g. `claude mcp add saffron -- npx saffron mcp`. |
83
83
  | `saffron author <prose-file> [-o out]` | Draft a `.saffron` feature file from plain-paragraph requirements, reusing the project's step vocabulary (AI; reports how many lines are seedable). |
84
84
  | `saffron lsp` | Run the Saffron language server over stdio for JetBrains (LSP4IJ/Ultimate), Neovim, any LSP editor: badge completion, StepSet go-to-definition, hover, diagnostics. Highlighting for JetBrains comes from the bundled TextMate grammar (`textmate/saffron` in the package); run `npx saffron lsp` in a terminal for setup steps. |
85
85
  | `saffron init [--agents list] [--examples]` | Make the project agent-ready (`--examples` installs the Saucedemo example suite): installs the bundled **Saffron agent skill** into `.claude/skills` and `.agents/skills` (Copilot/Cursor via `--agents`), registers the `saffron mcp` server in `.mcp.json` / `.cursor/mcp.json` / `.vscode/mcp.json`, adds a managed block to `AGENTS.md`/`CLAUDE.md`, scaffolds config. |
86
86
  | `saffron report` | Open the latest HTML report. |
87
+ | `saffron dashboard` | Open the suite's quality dashboard: failing, flaky and never-run scenarios, repeated heals, slowest, trends, per tag. |
87
88
  | `saffron trace [scenario] [--port n] [--no-open] [--json]` | Open the execution replay of the last run (every traced scenario, or the one you name): its Given / When / Then, the page inspectable at every action, the network alongside, and what the agent changed. Needs `"trace": "retain-on-failure"` (or `"on"`). |
88
89
 
89
90
  Configuration lives in `saffron.config.json` at your project root:
@@ -119,7 +120,7 @@ experimental; `npx saffron login antigravity` once) or `cursor`
119
120
  (`npm i -D @cursor/sdk`, then `npx saffron login cursor`). `model` takes
120
121
  that provider's model names. `npx saffron login` says what a provider
121
122
  still needs on this machine. Every sign-in flow is in
122
- [docs/PROVIDERS.md](docs/PROVIDERS.md).
123
+ [AI providers and sign-in](https://saffron-ai.io/docs/ai-providers).
123
124
 
124
125
  `storageState` (also `--storage-state`) points to a Playwright storage-state
125
126
  JSON (cookies + localStorage) applied to every scenario's browser context, so
@@ -149,13 +150,15 @@ features/ your .saffron and .feature files
149
150
 
150
151
  ## Roadmap
151
152
 
152
- See the roadmap on **[the site](https://saffron-ai.io/#roadmap)**, the single source of truth for
153
- milestones, statuses, and decision gates. Headlines:
154
- action-vocabulary additions as real-world failures surface them, the
155
- Level-2 shared step library (gated on Level-1 divergence data), LLM-less
156
- MCP replay, multi-provider agents, parallel workers, public npm/GitHub
157
- release, and the long-term open-core SaaS layer. Everything shipped so
158
- 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.
159
162
 
160
163
  ## Documentation
161
164