saffron-ai 0.8.3 → 0.8.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
@@ -4,6 +4,158 @@ All notable changes to Saffron, in one place: the `saffron-ai` runner (npm),
4
4
  the VS Code extension (`ChathurangaJayasinghe.saffron-vscode`) and the
5
5
  JetBrains plugin (`ai.saffron.jetbrains`). Dates are publish dates.
6
6
 
7
+ ## 0.8.5
8
+
9
+ Released 2026-09-24.
10
+
11
+ Runner
12
+
13
+ - **A proposal is bound to what you reviewed.** Every proposal now carries
14
+ digests of the scenario's steps, of the committed recording it was
15
+ diffed against and of its own recording, taken when it was filed.
16
+ `saffron accept` recomputes them and refuses a proposal, by reason, when
17
+ any moved since: a step edited, a colleague's heal accepted, a locator
18
+ fix propagated, a pull, a hand edit ("step 3 now reads ... and was
19
+ ..."). There is no override; run the scenario again for a proposal
20
+ bound to what is there now, or reject it. `saffron accept`, `saffron
21
+ diff`, `saffron status --json` (`stale`) and both IDE panels show STALE
22
+ with the reason first. A run that finds a stale pending proposal records
23
+ afresh instead of proving it again. Fingerprints are advisory and are
24
+ not bound; data tables, doc strings and the feature edits that
25
+ `--with-feature-edit` would apply are. Proposals filed before this
26
+ release carry no digests and are accepted with a note.
27
+ - **Recordings and proposals are validated on read.** The schema version,
28
+ every step, every action type and field are checked, along with the
29
+ operands each action needs (a click without a usable target, an
30
+ `expectUrl` without a URL, which used to compare "" and pass), and the
31
+ first problem is named by path. An unreadable recording makes its scenario red
32
+ with the reason instead of replaying as garbage or being recorded over;
33
+ `saffron status` marks it `invalid` with the reason (`cacheProblem`);
34
+ an unreadable proposal is reported and left out of listings
35
+ (`unreadableProposals`) instead of blanking them. A file from a newer
36
+ runner, a schema version or an action type this one does not know, says
37
+ to update `saffron-ai`. Fields added within the schema version stay
38
+ optional, so newer caches read on older runners. Hand-written caches may
39
+ omit `recordedAt` and `recordedBy`.
40
+
41
+ Editors (VS Code extension 0.2.10, JetBrains plugin 0.2.5)
42
+
43
+ - Both Proposals panels mark a stale proposal STALE, with the reason and
44
+ what to do, and note a proposal filed by an older runner.
45
+
46
+ ## 0.8.4
47
+
48
+ Released 2026-09-24.
49
+
50
+ Runner
51
+
52
+ - **A check could point at the wrong element.** In a live heal the agent
53
+ recorded "the Morning Ritual package is applied" against `role=definition`
54
+ with no name. The booking summary has one definition per row, so replay
55
+ read the first one (the room) and the proof replay failed. `saffron_assert`
56
+ and `saffron_capture` now refuse a bare role unless it is one that occurs
57
+ once per page (`status`, `alert`, `dialog`, `main` and similar), and ask
58
+ the agent for a name, text, label or selector instead.
59
+ - **A baseURL's query string and path were lost on replay.** With
60
+ `baseURL` set to `http://localhost:5173/?flow=checkout-guest`, a recorded
61
+ visit to the start page replayed as `http://localhost:5173/`, silently
62
+ dropping the flag that picks the variant under test. A baseURL with a
63
+ path fared no better: under `http://host/app`, a cached `/rooms`
64
+ replayed as `http://host/rooms`, and a recorded `http://host/apple` was
65
+ cached as `/le`. Under `http://h/#/home`, a recorded visit to `/` with
66
+ no hash replayed back to `#/home`, a different page for a hash router;
67
+ it is now kept as `/#`, the way a missing query is kept as `?`.
68
+ The baseURL is now a prefix in both directions: cached
69
+ navigations keep its path and inherit its query, so a cache recorded
70
+ against `?flow=standard` replays against `--base-url
71
+ "...?flow=checkout-guest"`. A cached URL with a query of its own keeps
72
+ it, other origins stay untouched, and existing caches replay as before.
73
+ - **Heal summaries could describe a changed flow as a locator tweak.**
74
+ When an A/B variant folded the guest information page into checkout,
75
+ the heal was right (fields re-targeted, the "Continue to payment" click
76
+ dropped) but its note only said the selects were now found by label.
77
+ The heal prompt now asks the agent to name the kind of change (a locator
78
+ or label change, a page removed or merged, a page added or reordered)
79
+ and the page it happened on. Saffron also compares the healed recording
80
+ with the committed one and adds its own `flow change:` notes for any
81
+ click, key press, goto or tab move that was dropped or added, together
82
+ with the page replay stopped on. A renamed button still reads as a
83
+ locator change and adds no note.
84
+ - **Two data references holding the same value could bind a field to the
85
+ wrong one.** With `users.owner` and `users.recipient` both "Alice", the
86
+ recorder tokenized every typed "Alice" as the first reference, so a
87
+ recipient field read the owner. Change the recipient to "Bob" and the
88
+ scenario correctly went stale, but step reuse seeded the mis-bound
89
+ actions straight back and the proof replay agreed: verified, zero AI
90
+ calls, wrong field. The recorder now resolves an equal value by the
91
+ reference the step itself names, leaves the literal when the step names
92
+ both or neither (so the stale check catches it), and step reuse refuses
93
+ a step that names a reference its recording does not read.
94
+ - **The report could list `{unique:...}` values that were never typed.**
95
+ A recording seeded from earlier steps, and the proof replay of a pending
96
+ proposal, each drew their own seed while the report showed the values of
97
+ a third. One seed per scenario run now reaches every replay, recording
98
+ and proof, so the report's values are the ones in your application.
99
+ - **A second Ctrl-C during teardown exited before the cleanup finished.**
100
+ The first Ctrl-C started teardown; the next one fell through to Node's
101
+ default and killed the run on top of it. Saffron now answers it with a
102
+ note and keeps waiting.
103
+ - **Re-merging shards after a shard was re-run left the old result in
104
+ history.** The merge treated the run as already recorded and skipped it.
105
+ It now replaces that run's history line, and still never counts a run
106
+ twice. In CI the run is identified by the CI run id, the suite and the
107
+ base URL rather than by the earliest start time, so this holds whichever
108
+ shard was re-run; outside CI, `SAFFRON_RUN_ID` gives the same stability.
109
+ - **The proof replay of a recording reused the recording's `{unique:...}`
110
+ values.** Fixed alongside the report fix above: the proof is a second
111
+ execution, so creating the same record again failed, filed the proposal
112
+ unverified and paid for a refinement pass. Each proof now draws its own
113
+ values, and the report lists them separately from the recording's.
114
+ - **A heal or a refinement could redo earlier steps on the wrong tab and
115
+ file them under step 1.** When the agent takes over, it attaches to the
116
+ browser over CDP and sees every Saffron page as one tab list, starting
117
+ on the first. During a refinement the scenario's own page was still open
118
+ beside the proof replay's, so the agent started on the wrong page,
119
+ selected a tab, and in one run went back to the start page and redid the
120
+ search. Every action performed before its first `saffron_step` was filed
121
+ under step 1, and the merge adopted it over the recording replay had
122
+ already passed: proposals whose step 1 held only "switch to tab 1", or a
123
+ second copy of the search, and a proof replay that failed on them.
124
+ Saffron now closes the pages of other browser contexts before an agent
125
+ session, so the agent sees only the live tabs, and tells it which tab
126
+ replay left off on: the page replay was really acting on, not the newest
127
+ tab with a matching URL, which is a different page when two tabs share
128
+ one. A heal or refinement records nothing until the agent
129
+ announces the failed step: anything it clicks or navigates before that is
130
+ diagnosis and is discarded, and the prompt tells it to look with
131
+ snapshots instead. A seeded recording segment files early actions under
132
+ the first step it may record, never a step that already ran, and drops
133
+ an early tab selection. Actions the agent files under an already
134
+ completed step are discarded, and the merge keeps completed steps'
135
+ recordings whatever the session holds for them.
136
+ Each of these leaves a `recording:` note in the proposal's adaptations.
137
+ Fresh recordings from step 1 behave as before.
138
+ The live tab also follows the agent through a seeded recording: a tab
139
+ it selects, opens or closes in one segment is where the next seeded
140
+ island replays and the next segment starts, read from the browser
141
+ tool's own tab list rather than guessed from a URL.
142
+ - **A role with a text no longer matched any element showing that text.**
143
+ Role and text together now mean the element of that role that shows the
144
+ text, and nothing else.
145
+ - **Shards from different environments merged silently.** A staging shard
146
+ and a production shard combined into one report labelled with whichever
147
+ came first. The merge now refuses shards with different base URLs, by
148
+ name.
149
+
150
+ Editors (VS Code extension 0.2.9)
151
+
152
+ - **`{data:...}` diagnostics stayed stale after editing a data file.** The
153
+ extension watched feature files and caches but not the data folder or
154
+ `saffron.config.json`, so fixing a missing key in `users.json` left the
155
+ error on the feature until the feature itself was touched. Edits to data
156
+ files and to the config now refresh every open feature file, including a
157
+ custom data folder and environment overlays.
158
+
7
159
  ## 0.8.3
8
160
 
9
161
  Released 2026-09-22.