haltija 1.6.0 → 1.11.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,171 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.11.0
4
+
5
+ ### Errors now tell you what to do
6
+
7
+ Following the tjs lesson that an error's job is the next action, not the diagnosis:
8
+
9
+ - **"Element not found"** branches on what you passed. A stale **ref** explains that refs are only
10
+ valid while the element is in the DOM and to re-run `hj tree` (or target by text, which survives
11
+ re-renders); a **selector** gets the recovery order — `hj map`/`hj tree` to see what's there, the
12
+ hidden-elements rule, prefer `:text()`/`[data-testid]` over structural selectors, and `hj wait` if
13
+ the page is still loading.
14
+ - **Unknown-action errors list the valid actions** instead of only rejecting yours.
15
+ - **"No active recording" / "No selection available" / "url is required"** now say how to reach a
16
+ valid state.
17
+ - **Schema-validation failures** carry a `hint` with the CLI form and a runnable example body — and
18
+ `hj` now prints `hint` on errors, which it previously discarded, so the teachable half reached
19
+ nobody.
20
+
21
+ ### Fixed: six endpoints were missing from every generated doc
22
+
23
+ All three doc generators iterated a hardcoded category list and silently dropped anything not in it,
24
+ so every `/network/*` and `/dialog/*` endpoint appeared in **no** generated documentation. They now
25
+ append unlisted categories, so a new category can't vanish.
26
+
27
+ ### New: a docs-coverage gate
28
+
29
+ `docs-drift` catches generated files going stale against the schema; it can't catch a feature
30
+ shipping that the prose never mentions — which is how `hj map`, `--canvas` and `hj shutdown` all
31
+ shipped undiscoverable. A test now asserts every public endpoint reaches the reference and
32
+ `llms.txt`, every agent-facing command is named in `SKILL.md`, and headline capabilities are
33
+ explained rather than merely listed — failing with exactly what to add.
34
+
35
+ ## 1.10.0
36
+
37
+ ### New: a screenshot you can't take now degrades to a labelled schematic
38
+
39
+ In a plain browser with no desktop app and no screen-share grant, `hj screenshot` used to just fail.
40
+ It now returns a **schematic** of the page instead — and because canvases need **no permission**, any
41
+ `<canvas>` is embedded as **real pixels** inside it. For a 3D app or a chart that's the actual visual
42
+ content, so the substitute is genuinely useful rather than a consolation prize.
43
+
44
+ Labelled three ways, because a schematic quietly standing in for a screenshot would be exactly the
45
+ plausible-but-wrong result this tool exists to prevent: `source: "schematic"`, a `warning` naming
46
+ both routes to real pixels, and a red banner burned across the image. `--no-fallback` restores the
47
+ hard error, and `--strict` turns the warning into a non-zero exit.
48
+
49
+ ### New: the schematic surfaces contrast problems
50
+
51
+ The schematic is drawn in the **page's own colours** — element background as fill, border as stroke,
52
+ text colour for the caption — so a control the user can barely read is a box you can barely read.
53
+ Poor contrast shows itself instead of hiding in a JSON blob. It's machine-checkable too: DOM-tier
54
+ nodes carry `colors: {fg, bg, contrast, passes}` and a `contrastFail` string when they miss WCAG AA.
55
+ (The verdict is drawn in legible red on purpose — a warning about unreadable text mustn't itself be
56
+ unreadable.)
57
+
58
+ ### Fixed: the widget was served without a charset
59
+
60
+ `Content-Type: application/javascript` carried no `; charset=utf-8`, so browsers parsed
61
+ `component.js` as Latin-1 and **every non-ASCII string literal in the widget was corrupted at parse
62
+ time** — em-dashes, `×`, `·`, and the `⟷`/`⟵` binding-arrow legend. The bytes on disk were always
63
+ valid UTF-8; the browser was mis-decoding them. Fixed on all five JS responses.
64
+
65
+ ## 1.9.0
66
+
67
+ ### New: `hj map --image` — the map as a rasterized schematic
68
+
69
+ Renders the affordance map as a PNG: one labeled box per control, nested by structure, each showing
70
+ its handle (`@ref` or `#index`) so the picture doubles as an **index** — glance at it, pick a
71
+ target, act on that one record.
72
+
73
+ It has to be a **bitmap** to be worth anything: an image of text costs a vision encoder far fewer
74
+ tokens than the same text tokenized, but that applies to rendered pixels, not to SVG markup (which
75
+ is just text tokens, and worse than the JSON it would replace). Rasterized in the browser, so there
76
+ is no new dependency.
77
+
78
+ **The win is density-dependent, and the response says so rather than assuming.** An image costs
79
+ ~1000–1600 vision tokens regardless of content, so a small page is cheaper as JSON; the image pays
80
+ off once the map is large. `cost.approxJsonTokens` reports the JSON size for that page so the choice
81
+ is measurable. The schematic is also deterministic, which makes a diff between two runs a regression
82
+ a human can see.
83
+
84
+ ## 1.8.0
85
+
86
+ ### New: `hj map` — what can I interact with, and what is it wired to?
87
+
88
+ An affordance map of the page. Usually a better first move than `hj tree` or a screenshot when
89
+ you're deciding what to *do*: structural, deterministic (no fonts/theme/viewport/animation timing),
90
+ and dense — a small page is a few hundred bytes (~100 tokens) against ~1–1.5k vision tokens for a
91
+ screenshot.
92
+
93
+ Two tiers, and the response always says which one produced it:
94
+
95
+ - **`source: "tosi-agent"`** — when the page exposes an agent surface (`globalThis.tosiAgent`, a
96
+ tosijs app calling `enableAgentInterface()`), the map is the app's **own wiring records**, passed
97
+ through unchanged. Those carry what the DOM cannot: which state path each control is bound to and
98
+ in which **direction** (`⟷` two-way/user-writable, `⟵` display-only, absent = static), the handler
99
+ path each event calls, and the callable actions. Act through the paths rather than synthesizing
100
+ input — `hj eval "tosiAgent.write('app.filter','milk')"` — and note that writing a `⟵`
101
+ display-only path via the DOM won't stick, which is exactly the "I typed into it and nothing
102
+ happened" trap.
103
+ - **`source: "dom"`** — any other page: structural, visible-only, each node carrying a `ref` for
104
+ `hj click <ref>`. Labelled an approximation with **no** binding provenance, so it can't be
105
+ mistaken for real wiring.
106
+
107
+ Credit to the tosijs agent for the idea (#12).
108
+
109
+ ## 1.7.0
110
+
111
+ ### New: capture a `<canvas>` directly — `hj screenshot --canvas <selector>`
112
+
113
+ Reads the canvas's own pixels (`toDataURL`) instead of capturing the screen. For a WebGL scene
114
+ (Babylon/three.js) or a UI rendered into a texture that means **exact pixels at native resolution,
115
+ no screen-share grant, no desktop app required** — and it works even when the canvas is scrolled
116
+ out of view or the tab isn't frontmost. Takes the same `--scale`/`--format`/`--max-width`/file
117
+ options as any screenshot.
118
+
119
+ It also handles the trap that makes naive canvas capture untrustworthy: a WebGL context clears its
120
+ drawing buffer after compositing unless created with `{ preserveDrawingBuffer: true }`, so
121
+ `toDataURL` can hand back a **blank image with no error**. Haltija samples the result and returns a
122
+ `warning` explaining the likely cause instead of a silent empty picture — and deliberately doesn't
123
+ cry wolf: a canvas with real content warns not at all, and a uniform *opaque* colour (which may be a
124
+ perfectly legitimate solid background) gets a softer note than a fully transparent one. A canvas
125
+ tainted by cross-origin textures returns a clear CORS error rather than crashing.
126
+
127
+ ### New: adopter-context test lane
128
+
129
+ The suite now includes tests that reproduce the *dirty machine* adopters actually have — a server
130
+ already running with zero windows, two projects in different directories each expecting their own,
131
+ and ambiguous targeting from an unrelated directory. Every field bug this project has shipped lived
132
+ in that gap, invisible to a suite that starts from nothing.
133
+
134
+ ## 1.6.1
135
+
136
+ Makes haltija's detection reachable by automation ([#8](https://github.com/tonioloewald/haltija/issues/8),
137
+ [#11](https://github.com/tonioloewald/haltija/issues/11)).
138
+
139
+ haltija already *detects* the situations that wreck a test lane — the wrong project's browser, a
140
+ hidden tab returning stale results, a server with nothing to drive. It only ever **warned on
141
+ stderr**, so scripts consumed plausible-but-wrong results and failed much later, pointing at the
142
+ caller's own code.
143
+
144
+ ### New: `ready` — "server is up" is not "server is drivable"
145
+
146
+ `/status` and `/windows` now return **`ready`**: true when at least one top-level tab is connected.
147
+ A server running with *zero* windows answers `/status` 200, so an adopter's reuse probe skipped
148
+ starting its own browser and then had nothing to navigate. Gate a lane on `ready`, not on the 200.
149
+
150
+ ### New: `hj doctor`
151
+
152
+ One-command preflight that **exits non-zero**: server reachable → a tab is connected → the target
153
+ isn't ambiguous → tabs aren't all hidden → versions aligned. `--json` for machine-readable output.
154
+ Use it as the wait-loop condition in CI.
155
+
156
+ ### New: `hj --strict` / `HALTIJA_STRICT=1`
157
+
158
+ Turns the advisory warnings into **non-zero exits**, and refuses to print a suspect result to
159
+ stdout at all — a script must not consume a value that may be wrong. A warning is the right default
160
+ for a human at a prompt and the wrong one for a lane.
161
+
162
+ ### Fixed
163
+
164
+ - **Warning de-duplication silently defeated strict mode.** The server withheld a repeated warning
165
+ entirely, so the first command in a lane failed and every later one within the cooldown passed.
166
+ The server now always reports the condition and marks repeats (`warningRepeated`); de-dup is a
167
+ presentation concern, so `hj` stays quiet on a repeat while `--strict` fails on any warning.
168
+
3
169
  ## 1.6.0
4
170
 
5
171
  Consolidating release: rolls up everything from 1.5.2–1.5.7 (the last npm-published version was
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "haltija-desktop",
3
- "version": "1.6.0",
3
+ "version": "1.11.0",
4
4
  "private": true,
5
5
  "description": "Haltija Desktop - God Mode Browser for AI Agents",
6
6
  "homepage": "https://github.com/tonioloewald/haltija",