haltija 1.6.1 → 1.11.2

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,219 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.11.2
4
+
5
+ Patch. Four field reports from tosijs-3d and tosijs-ui, all confirmed.
6
+
7
+ ### Fixed: `--canvas` couldn't reach a canvas in a shadow root ([#15](https://github.com/tonioloewald/haltija/issues/15))
8
+
9
+ Which is where every component-based renderer puts it — so the exact-pixels escape hatch failed on
10
+ exactly the pages where pixels are the only thing worth looking at. Canvas resolution now pierces
11
+ shadow DOM and accepts every shape someone would reasonably write:
12
+
13
+ ```bash
14
+ hj screenshot --canvas "tosi-b3d canvas" # descendant, crossing the boundary
15
+ hj screenshot --canvas "tosi-b3d >>> canvas" # explicit piercing form
16
+ hj screenshot --canvas "canvas" # found inside shadow roots too
17
+ hj screenshot --canvas # no selector: the largest canvas on the page
18
+ ```
19
+
20
+ A genuine miss now lists the canvases that *do* exist, with working selectors. The **schematic**
21
+ embeds shadow-root canvases as well — previously it silently showed none on these pages.
22
+
23
+ ### Fixed: advisory hints were printed to stdout ([#14](https://github.com/tonioloewald/haltija/issues/14))
24
+
25
+ A dim hint line was appended to **stdout** after JSON output, so `JSON.parse(await $\`hj windows\`)`
26
+ threw — and an adopter's readiness probe fell into an open catch and silently did nothing. All
27
+ advisory text is on stderr now; stdout is the data channel.
28
+
29
+ Two related fixes from the same report:
30
+
31
+ - **`hj <cmd> --help` now describes that command** instead of falling through to global help, which
32
+ read exactly like "unknown command" (a reporter concluded `doctor` and `map` didn't exist in their
33
+ build). haltija's own error messages recommend this form, so the remedy we printed was broken.
34
+ - **The standalone `hj` bundle now carries its hints.** They were read from a sibling `hints.json`,
35
+ which doesn't exist next to `~/.local/bin/hj` — so two distributions reporting the same version
36
+ produced different output. Hints are compiled in, like the version and semver helpers.
37
+
38
+ ### Fixed: contrast false positives on text-less ancestors ([#13](https://github.com/tonioloewald/haltija/issues/13))
39
+
40
+ A container propagates `color`/`background` but has no font size, so `large` is *unknowable* —
41
+ defaulting it to false held it to 4.5:1 and manufactured failures for text that passes as large on
42
+ the child that actually renders it. About half the findings on a typical page. Only elements with
43
+ their own direct text are graded now.
44
+
45
+ ## 1.11.1
46
+
47
+ Patch, per the rule that a minor bump waits for a cleared backlog and a nine-lens review.
48
+
49
+ ### Fixed: contrast audit noise
50
+
51
+ Two sources of false findings, fixed before anyone acts on a long list of them:
52
+
53
+ - **Containers with no text of their own were flagged.** A `<div>`/`<form>` inherits a colour but
54
+ displays nothing, so a "failure" there is noise. Only elements that actually render text, a label
55
+ or a value get a verdict now.
56
+ - **Text over a `background-image`** (gradient, photo) was judged against whatever background-*color*
57
+ sat beneath it — which can be wrong in either direction. Those are now reported as
58
+ `colors.uncertain` rather than asserted as pass or fail.
59
+
60
+ An audit people learn to skim is worth nothing, so the bar is: only claim what can be justified.
61
+
62
+ ### Per-tab routing, by declaration ([#1](https://github.com/tonioloewald/haltija/issues/1), [#2](https://github.com/tonioloewald/haltija/issues/2))
63
+
64
+ cwd routing gets a command to the right *server*; which **tab** answers then fell back to focus, so
65
+ two projects on a shared server could drive each other's pages. Ranking tabs by "this origin looks
66
+ like your project" was rejected twice — there's no reliable origin→directory map, and a
67
+ usually-right guess reintroduces the silent misroute cwd routing exists to prevent.
68
+
69
+ So the project declares it. A `.haltija.json` at the project root:
70
+
71
+ ```json
72
+ { "origins": ["https://localhost:8030", "http://localhost:3000"] }
73
+ ```
74
+
75
+ …and `hj`, run anywhere inside that project, pins commands to a connected tab on one of those
76
+ origins regardless of focus. **Entirely opt-in** (no file = unchanged behaviour) and it never
77
+ guesses: if you declared origins and no connected tab matches, `hj` says so loudly instead of
78
+ quietly driving another project's page — and refuses outright under `--strict`. `HALTIJA_ORIGINS`
79
+ overrides for one-off shells and CI.
80
+
81
+ ### `hj screenshot --schematic`
82
+
83
+ Ask for the schematic even when real capture *is* available — it's cheaper, deterministic, and
84
+ carries the contrast audit. Canvases are still embedded as real pixels.
85
+
86
+ ## 1.11.0
87
+
88
+ ### Errors now tell you what to do
89
+
90
+ Following the tjs lesson that an error's job is the next action, not the diagnosis:
91
+
92
+ - **"Element not found"** branches on what you passed. A stale **ref** explains that refs are only
93
+ valid while the element is in the DOM and to re-run `hj tree` (or target by text, which survives
94
+ re-renders); a **selector** gets the recovery order — `hj map`/`hj tree` to see what's there, the
95
+ hidden-elements rule, prefer `:text()`/`[data-testid]` over structural selectors, and `hj wait` if
96
+ the page is still loading.
97
+ - **Unknown-action errors list the valid actions** instead of only rejecting yours.
98
+ - **"No active recording" / "No selection available" / "url is required"** now say how to reach a
99
+ valid state.
100
+ - **Schema-validation failures** carry a `hint` with the CLI form and a runnable example body — and
101
+ `hj` now prints `hint` on errors, which it previously discarded, so the teachable half reached
102
+ nobody.
103
+
104
+ ### Fixed: six endpoints were missing from every generated doc
105
+
106
+ All three doc generators iterated a hardcoded category list and silently dropped anything not in it,
107
+ so every `/network/*` and `/dialog/*` endpoint appeared in **no** generated documentation. They now
108
+ append unlisted categories, so a new category can't vanish.
109
+
110
+ ### New: a docs-coverage gate
111
+
112
+ `docs-drift` catches generated files going stale against the schema; it can't catch a feature
113
+ shipping that the prose never mentions — which is how `hj map`, `--canvas` and `hj shutdown` all
114
+ shipped undiscoverable. A test now asserts every public endpoint reaches the reference and
115
+ `llms.txt`, every agent-facing command is named in `SKILL.md`, and headline capabilities are
116
+ explained rather than merely listed — failing with exactly what to add.
117
+
118
+ ## 1.10.0
119
+
120
+ ### New: a screenshot you can't take now degrades to a labelled schematic
121
+
122
+ In a plain browser with no desktop app and no screen-share grant, `hj screenshot` used to just fail.
123
+ It now returns a **schematic** of the page instead — and because canvases need **no permission**, any
124
+ `<canvas>` is embedded as **real pixels** inside it. For a 3D app or a chart that's the actual visual
125
+ content, so the substitute is genuinely useful rather than a consolation prize.
126
+
127
+ Labelled three ways, because a schematic quietly standing in for a screenshot would be exactly the
128
+ plausible-but-wrong result this tool exists to prevent: `source: "schematic"`, a `warning` naming
129
+ both routes to real pixels, and a red banner burned across the image. `--no-fallback` restores the
130
+ hard error, and `--strict` turns the warning into a non-zero exit.
131
+
132
+ ### New: the schematic surfaces contrast problems
133
+
134
+ The schematic is drawn in the **page's own colours** — element background as fill, border as stroke,
135
+ text colour for the caption — so a control the user can barely read is a box you can barely read.
136
+ Poor contrast shows itself instead of hiding in a JSON blob. It's machine-checkable too: DOM-tier
137
+ nodes carry `colors: {fg, bg, contrast, passes}` and a `contrastFail` string when they miss WCAG AA.
138
+ (The verdict is drawn in legible red on purpose — a warning about unreadable text mustn't itself be
139
+ unreadable.)
140
+
141
+ ### Fixed: the widget was served without a charset
142
+
143
+ `Content-Type: application/javascript` carried no `; charset=utf-8`, so browsers parsed
144
+ `component.js` as Latin-1 and **every non-ASCII string literal in the widget was corrupted at parse
145
+ time** — em-dashes, `×`, `·`, and the `⟷`/`⟵` binding-arrow legend. The bytes on disk were always
146
+ valid UTF-8; the browser was mis-decoding them. Fixed on all five JS responses.
147
+
148
+ ## 1.9.0
149
+
150
+ ### New: `hj map --image` — the map as a rasterized schematic
151
+
152
+ Renders the affordance map as a PNG: one labeled box per control, nested by structure, each showing
153
+ its handle (`@ref` or `#index`) so the picture doubles as an **index** — glance at it, pick a
154
+ target, act on that one record.
155
+
156
+ It has to be a **bitmap** to be worth anything: an image of text costs a vision encoder far fewer
157
+ tokens than the same text tokenized, but that applies to rendered pixels, not to SVG markup (which
158
+ is just text tokens, and worse than the JSON it would replace). Rasterized in the browser, so there
159
+ is no new dependency.
160
+
161
+ **The win is density-dependent, and the response says so rather than assuming.** An image costs
162
+ ~1000–1600 vision tokens regardless of content, so a small page is cheaper as JSON; the image pays
163
+ off once the map is large. `cost.approxJsonTokens` reports the JSON size for that page so the choice
164
+ is measurable. The schematic is also deterministic, which makes a diff between two runs a regression
165
+ a human can see.
166
+
167
+ ## 1.8.0
168
+
169
+ ### New: `hj map` — what can I interact with, and what is it wired to?
170
+
171
+ An affordance map of the page. Usually a better first move than `hj tree` or a screenshot when
172
+ you're deciding what to *do*: structural, deterministic (no fonts/theme/viewport/animation timing),
173
+ and dense — a small page is a few hundred bytes (~100 tokens) against ~1–1.5k vision tokens for a
174
+ screenshot.
175
+
176
+ Two tiers, and the response always says which one produced it:
177
+
178
+ - **`source: "tosi-agent"`** — when the page exposes an agent surface (`globalThis.tosiAgent`, a
179
+ tosijs app calling `enableAgentInterface()`), the map is the app's **own wiring records**, passed
180
+ through unchanged. Those carry what the DOM cannot: which state path each control is bound to and
181
+ in which **direction** (`⟷` two-way/user-writable, `⟵` display-only, absent = static), the handler
182
+ path each event calls, and the callable actions. Act through the paths rather than synthesizing
183
+ input — `hj eval "tosiAgent.write('app.filter','milk')"` — and note that writing a `⟵`
184
+ display-only path via the DOM won't stick, which is exactly the "I typed into it and nothing
185
+ happened" trap.
186
+ - **`source: "dom"`** — any other page: structural, visible-only, each node carrying a `ref` for
187
+ `hj click <ref>`. Labelled an approximation with **no** binding provenance, so it can't be
188
+ mistaken for real wiring.
189
+
190
+ Credit to the tosijs agent for the idea (#12).
191
+
192
+ ## 1.7.0
193
+
194
+ ### New: capture a `<canvas>` directly — `hj screenshot --canvas <selector>`
195
+
196
+ Reads the canvas's own pixels (`toDataURL`) instead of capturing the screen. For a WebGL scene
197
+ (Babylon/three.js) or a UI rendered into a texture that means **exact pixels at native resolution,
198
+ no screen-share grant, no desktop app required** — and it works even when the canvas is scrolled
199
+ out of view or the tab isn't frontmost. Takes the same `--scale`/`--format`/`--max-width`/file
200
+ options as any screenshot.
201
+
202
+ It also handles the trap that makes naive canvas capture untrustworthy: a WebGL context clears its
203
+ drawing buffer after compositing unless created with `{ preserveDrawingBuffer: true }`, so
204
+ `toDataURL` can hand back a **blank image with no error**. Haltija samples the result and returns a
205
+ `warning` explaining the likely cause instead of a silent empty picture — and deliberately doesn't
206
+ cry wolf: a canvas with real content warns not at all, and a uniform *opaque* colour (which may be a
207
+ perfectly legitimate solid background) gets a softer note than a fully transparent one. A canvas
208
+ tainted by cross-origin textures returns a clear CORS error rather than crashing.
209
+
210
+ ### New: adopter-context test lane
211
+
212
+ The suite now includes tests that reproduce the *dirty machine* adopters actually have — a server
213
+ already running with zero windows, two projects in different directories each expecting their own,
214
+ and ambiguous targeting from an unrelated directory. Every field bug this project has shipped lived
215
+ in that gap, invisible to a suite that starts from nothing.
216
+
3
217
  ## 1.6.1
4
218
 
5
219
  Makes haltija's detection reachable by automation ([#8](https://github.com/tonioloewald/haltija/issues/8),
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "haltija-desktop",
3
- "version": "1.6.1",
3
+ "version": "1.11.2",
4
4
  "private": true,
5
5
  "description": "Haltija Desktop - God Mode Browser for AI Agents",
6
6
  "homepage": "https://github.com/tonioloewald/haltija",