@unotest/viewer 0.30.0 → 0.32.0

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
@@ -1,5 +1,136 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.32.0] - 2026-09-05
4
+
5
+ ### Minor Changes
6
+
7
+ - 442fadf: `npx @unotest/web box …` reads a box's results from a terminal: `box envs` lists the environments a read token may look at, `box runs` their history (`--latest` collapses it to one line per scenario with its failing streak), `box run <id>` explains one run — the failure, the soft steps, the judge's verdicts — `box queue` shows who is waiting, and `box screenshot` saves a frame the run captured.
8
+
9
+ `box run --download` fetches the run's `*.unotest.zip` into `.unotest/box/` and unpacks its failure bundle into `.unotest/failures/`, where `list_failures`, `get_failure_*` and `agent_fix` already look — so a run that failed on a box is debugged with the commands a local failure is. `--no-screenshots` asks the box itself to leave the step frames out (`GET /api/runs/:id/export?screenshots=0`), which is what makes the download smaller rather than only the disk.
10
+
11
+ Reading needs a personal read token in `UNOTEST_BOX_READ_TOKEN`; the project's `UNOTEST_BOX_TOKEN` still pushes bundles and values and cannot read runs.
12
+
13
+ The viewer publishes its archive reader as `@unotest/viewer/snapshot`, so the three places that open a `*.unotest.zip` — its server, its browser bundle and now the CLI — share one implementation and one message for a file that is not an archive.
14
+
15
+ - 442fadf: `BoxReadClient` reads a box's runs — environments, run history, one run's whole journal, a collection's children, the queue, a run's export zip and its individual artifacts — over the same HTTP routes a browser uses, authenticated with the personal read token in `UNOTEST_BOX_READ_TOKEN`. Every refusal arrives as a typed `BoxReadError` whose `kind` says what to do next, so throttling is never mistaken for a rejected token and a live run's export says "wait" rather than looking like a broken box. Configuration mistakes surface when a read is attempted rather than at startup, so a stale token in a project's `.env` cannot stop a local run that never touches a box.
16
+
17
+ The viewer gains a `@unotest/viewer/wire` entry point exporting its HTTP contract types (the runs page, a run's full snapshot, the queue payload and the snapshot manifest), so a client can name the shapes it parses instead of keeping a second copy of them.
18
+
19
+ ### Patch Changes
20
+
21
+ - 8aa0f30: Protocol contract for reading a box's run results with a personal read token: `UNOTEST_BOX_READ_TOKEN` (distinct from the project's `UNOTEST_BOX_TOKEN`, which stays a write credential for bundles and environment values), the `X-Unotest-Environment: <project>/<environment>` header every bearer request names its own environment with, the `/_guard/api/envs` listing and its `BoxReadEnvironment` entry, and typed refusals (`unauthorized`, `forbidden`, `unknown-environment`, `not-found`, `rate-limited`, `run-in-progress`, `unavailable`, `malformed`) with parsers that reject anything that is not a box answering. Throttling gets a code of its own rather than an `unauthorized` carrying `Retry-After`: a rejected token means mint a new one, a throttled one means wait and resend the same one. The viewer's `ViewerEnvOption` is now that same protocol type rather than a second copy of it. An environment whose viewer is still starting — the common state right after a bundle push — answers `unavailable` rather than looking like an unreachable box, so the advice is to wait rather than to check the address.
22
+ - 8aa0f30: A run exported as `*.unotest.zip` now carries everything needed to diagnose it away from the machine that produced it: `stdout.log` and `stderr.log` (previously dropped, which left the one artifact that explains a runner crash outside the bundle), the failing page's `page.html` reachable through the manifest, and the run's step screenshots — declared in a new `manifest.screenshots` list, because an importer keeps only what the manifest names and a frame absent from it did not survive the round trip.
23
+ - Updated dependencies [8aa0f30]
24
+ - Updated dependencies [047ca68]
25
+ - Updated dependencies [047ca68]
26
+ - Updated dependencies [047ca68]
27
+ - @unotest/protocol@0.32.0
28
+ - @unotest/dsl@0.32.0
29
+ - @unotest/core@0.32.0
30
+
31
+ ## [0.31.0] - 2026-09-04
32
+
33
+ ### Minor Changes
34
+
35
+ - b8e105b: Steps tree shows what a step attached to itself: a row that called
36
+ `note(...)`, `log(...)` or `assertJudge(...)` gets an `ⓘ N` chip, and the
37
+ list under it renders notes as `label → value`, log lines, and the
38
+ verdict as `judge ✓/✗ · rubric · text` — open by default under a failed
39
+ step and under a verdict that said no, with open/closed choices
40
+ remembered per scenario and step. A note from inside a helper lands
41
+ under the entry step that called it (the runner records the entry
42
+ position; older journals fall back to the step in flight). The error
43
+ card of a failed judge step carries the whole verdict. After the run the
44
+ System pane lists the scenario's `log(...)` lines with their time. The
45
+ server keeps `note` / `log` lines when it reads a finished run's journal.
46
+ - 100ab9d: Steps view reads the `step-block:*` envelopes of a run: a block's duration
47
+ is now the whole block (a step wrapping a loop of three navigations shows
48
+ the loop's 4.8s, not the last statement's 66ms), a `{tag}` step shows its
49
+ evaluated tag as a chip (the source expression before the run), a
50
+ `step.soft` block is marked `soft`, and a group with soft descendants
51
+ rolls them up as "1 of 10 soft failed" and reads as failed. A run with
52
+ soft failures gets a card above the tree listing every one with its tag,
53
+ line and error. Journals recorded before 0.31.0 render as before. The
54
+ server keeps `step-block:*` and `judge:verdict` lines when it reads a
55
+ finished run's journal from disk (it used to drop every kind it did not
56
+ list, so a verdict never reached the page); the error card under a
57
+ failed step shows that step's own error, not the run's last one; the
58
+ status bar counts soft steps ("2 of 3 soft failed").
59
+ - ad7c918: Trace view — the execution tree of a run, next to Steps and Code. Built
60
+ from the journal alone: a helper call opens into the helper's statements
61
+ and `step(...)` blocks (file named on the row), a loop into one group per
62
+ iteration (an iteration that ran nothing included), a block into its
63
+ envelope with tag and duration. Helper calls and passed iterations start
64
+ folded with a summary ("10 iterations · 1 failed"); the failed branch is
65
+ open down to the failing statement, which carries the error card.
66
+ Double-click opens the row's file — a helper too — at that line in Code.
67
+ Notes, log lines and verdicts sit under their statement; screenshots
68
+ open from the row, helper-frame captures included. The chosen view is
69
+ remembered across reloads (a debug session always opens in Code). The
70
+ inspector's flat event list is now the **Events** tab, so Trace names
71
+ one thing. The server keeps `loop:iteration` lines when it reads a
72
+ finished run's journal.
73
+
74
+ ### Patch Changes
75
+
76
+ - e048334: The viewer's editor flags an undeclared external variable
77
+ (`lint:external-variable-undeclared`), the way `unotest-web lint` and the
78
+ pre-run lint already do: a bare `UPPER_SNAKE` identifier that no
79
+ `unotest/.env` / `.secrets` file of the active environment declares is an
80
+ error in the editor, naming the files searched. Protocol:
81
+ `DslValidateContext` gains `externalNames` / `externalSources`; the
82
+ viewer supplies them from the active target + environment's layer files
83
+ (the same files the variables panel shows) and `@unotest/web`'s language
84
+ service turns them into the linter's lookup.
85
+ - dcf4c9e: Viewer editor: lint markers appear as soon as a file opens (or the page
86
+ reloads), not only after the first keystroke — the editor validates the
87
+ source it mounted with instead of waiting for a change event that a
88
+ reopened tab never fires.
89
+ - 9ae6d59: A scenario that finished in the same instant the viewer looked at it is no
90
+ longer recorded as `interrupted` with a finish an hour before its start.
91
+ The runner ends a run by appending `run:finished` and then backdating the
92
+ heartbeat; the viewer read those two files in the opposite order, so a
93
+ steps snapshot taken a few milliseconds early could meet the backdated
94
+ heartbeat, and the provisional verdict stuck in the run index while the
95
+ collection reported the scenario passed. The heartbeat is read first now.
96
+ A viewer restart (which rebuilds the index from disk) already corrected
97
+ such records; runs indexed live are right the first time.
98
+ - 13a2d51: Viewer, Home tab: the tile of a scenario that is running now breathes
99
+ through colour and shadow only — the scale pulse is gone. It moved the
100
+ tile's box every frame, so an automation driver never saw the tile as
101
+ stable and a click on it waited out its timeout. A tile that never ran
102
+ no longer carries `data-age="fresh"`: it has no age, so the attribute is
103
+ absent.
104
+ - 91fb562: Viewer, Home tab: clicking a scenario tile opens the scenario's LAST RUN —
105
+ the run whose verdict the tile's colour is showing — instead of the test
106
+ file. A tile that has never run still opens the test (there is no run to
107
+ open), and so does every tile in schedule mode, where the schedule is
108
+ edited from the test. The legend now reads "hover for history · click to
109
+ open the last run".
110
+ - dcf4c9e: Viewer, Home tab: the tile field no longer refits itself in a loop. The
111
+ header and legend take the grid's width; when the legend wrapped at one
112
+ width and not at the next, the field's height changed, the fit followed,
113
+ the width changed back — at 60 fps every tile's box moved every frame,
114
+ and an automation click on ANY tile ("element is not stable") waited out
115
+ its timeout unless forced. Header and legend now never wrap (they grow
116
+ past the grid instead), so the fit converges and tiles stay put. A run
117
+ opened from a tile is titled by its scenario, like one opened from the
118
+ Runs tree, instead of by its run id.
119
+ - Updated dependencies [b8e105b]
120
+ - Updated dependencies [b8e105b]
121
+ - Updated dependencies [9ae6d59]
122
+ - Updated dependencies [56784b3]
123
+ - Updated dependencies [e048334]
124
+ - Updated dependencies [100ab9d]
125
+ - Updated dependencies [100ab9d]
126
+ - Updated dependencies [100ab9d]
127
+ - Updated dependencies [ad7c918]
128
+ - Updated dependencies [ad7c918]
129
+ - Updated dependencies [dcf4c9e]
130
+ - @unotest/core@0.31.0
131
+ - @unotest/protocol@0.31.0
132
+ - @unotest/dsl@0.31.0
133
+
3
134
  ## [0.30.0] - 2026-09-03
4
135
 
5
136
  ### Minor Changes