@reticlehq/server 3.8.0 → 3.8.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.
Files changed (115) hide show
  1. package/SKILL.md +2 -2
  2. package/dist/command/cli/answers/gate-hook-message.d.ts +2 -0
  3. package/dist/command/cli/answers/gate-hook-message.js +5 -1
  4. package/dist/command/cli/auth/cloud-session.d.ts +1 -19
  5. package/dist/command/cli/auth/device-flow.d.ts +3 -37
  6. package/dist/command/cli/cli-doctor.js +30 -23
  7. package/dist/command/cli/cli-flow-commands.js +7 -1
  8. package/dist/command/cli/cli-parse-serve.d.ts +24 -0
  9. package/dist/command/cli/cli-parse-serve.js +124 -0
  10. package/dist/command/cli/cli-parse.d.ts +1 -10
  11. package/dist/command/cli/cli-parse.js +62 -121
  12. package/dist/command/cli/cli-usage.js +5 -2
  13. package/dist/command/cli/cloud-link.d.ts +1 -20
  14. package/dist/command/cli/doctor/doctor-agent-link.d.ts +23 -0
  15. package/dist/command/cli/doctor/doctor-agent-link.js +28 -0
  16. package/dist/command/cli/ports/port-holder.js +6 -1
  17. package/dist/command/cli/project-name.d.ts +1 -7
  18. package/dist/command/cli/project-name.js +1 -0
  19. package/dist/command/daemon/daemon.d.ts +6 -0
  20. package/dist/command/daemon/daemon.js +52 -2
  21. package/dist/command/daemon/win32-escape.d.ts +32 -0
  22. package/dist/command/daemon/win32-escape.js +119 -0
  23. package/dist/command/setup/bringup/dev-server-files.d.ts +1 -9
  24. package/dist/command/setup/bringup/dev-server-wait.js +5 -1
  25. package/dist/command/version/version-skew.d.ts +2 -0
  26. package/dist/command/version/version-skew.js +7 -3
  27. package/dist/features/crawl/crawl-tools.js +2 -2
  28. package/dist/features/exhaust/ledger.d.ts +15 -96
  29. package/dist/features/exhaust/ledger.js +3 -3
  30. package/dist/features/license/license.d.ts +2 -14
  31. package/dist/hooks/hook-commands.js +19 -9
  32. package/dist/judgement/capsule/capsule-store.d.ts +2 -39
  33. package/dist/language/flows/annotate-tools.js +1 -1
  34. package/dist/language/flows/fields/flow-secret-field.js +1 -1
  35. package/dist/language/flows/flow-expect-grammar.js +14 -6
  36. package/dist/language/flows/flow-lease.d.ts +27 -0
  37. package/dist/language/flows/flow-lease.js +59 -0
  38. package/dist/language/flows/flow-replay-run.d.ts +1 -87
  39. package/dist/language/flows/flow-replay-run.js +88 -283
  40. package/dist/language/flows/flow-replayable.d.ts +1 -1
  41. package/dist/language/flows/flow-start-path.d.ts +108 -0
  42. package/dist/language/flows/flow-start-path.js +313 -0
  43. package/dist/language/flows/flow-tools.d.ts +2 -23
  44. package/dist/language/flows/flow-tools.js +34 -66
  45. package/dist/language/flows/recording/flake.d.ts +3 -27
  46. package/dist/language/flows/recording/flake.js +1 -1
  47. package/dist/language/flows/stores/assertion-tiers-store.js +1 -1
  48. package/dist/machine/git-tracks.js +1 -0
  49. package/dist/memory/cloud/cloud-sync.d.ts +2 -24
  50. package/dist/memory/intent/intent-shard.d.ts +41 -266
  51. package/dist/memory/journal/envelope-store.js +1 -1
  52. package/dist/memory/journal/envelope.d.ts +6 -154
  53. package/dist/memory/journal/on-disk/ambient-file.d.ts +1 -7
  54. package/dist/memory/journal/on-disk/ambient-file.js +1 -1
  55. package/dist/memory/journal/self-observation.js +3 -1
  56. package/dist/memory/journal/session-journal.js +39 -20
  57. package/dist/portal/input/drive-error.d.ts +6 -0
  58. package/dist/portal/input/drive-error.js +9 -0
  59. package/dist/portal/input/real-input-press.d.ts +34 -0
  60. package/dist/portal/input/real-input-press.js +150 -0
  61. package/dist/portal/input/real-input.d.ts +6 -23
  62. package/dist/portal/input/real-input.js +95 -192
  63. package/dist/portal/input/viewport-tools.d.ts +19 -15
  64. package/dist/portal/pool/browser-pool.d.ts +5 -55
  65. package/dist/portal/pool/browser-pool.js +121 -100
  66. package/dist/portal/pool/pool-lease.d.ts +128 -0
  67. package/dist/portal/pool/pool-lease.js +49 -0
  68. package/dist/portal/production/production-activation.d.ts +5 -27
  69. package/dist/portal/session/control-envelope.d.ts +1 -1
  70. package/dist/portal/session/zero-install-first-call.d.ts +3 -0
  71. package/dist/portal/session/zero-install-first-call.js +33 -12
  72. package/dist/surface/mcp/mcp.d.ts +3 -3
  73. package/dist/surface/mcp/mcp.js +4 -6
  74. package/dist/surface/tools/act/act-danger.js +32 -17
  75. package/dist/surface/tools/act/durable.js +1 -1
  76. package/dist/surface/tools/act-sequence-tool.js +3 -3
  77. package/dist/surface/tools/act-tools.js +15 -16
  78. package/dist/surface/tools/agent/compact-envelope.d.ts +2 -2
  79. package/dist/surface/tools/coverage-tools.js +1 -1
  80. package/dist/surface/tools/dynamic-tools.d.ts +8 -0
  81. package/dist/surface/tools/dynamic-tools.js +36 -16
  82. package/dist/surface/tools/empty-session-list.d.ts +5 -29
  83. package/dist/surface/tools/feedback-tools.js +1 -1
  84. package/dist/surface/tools/gap-novelty.d.ts +1 -1
  85. package/dist/surface/tools/gaps/capability-absences.js +4 -3
  86. package/dist/surface/tools/harness-gate.d.ts +1 -1
  87. package/dist/surface/tools/harness-toolset.js +3 -4
  88. package/dist/surface/tools/lease-permissions.d.ts +1 -1
  89. package/dist/surface/tools/lease-readiness.d.ts +23 -1
  90. package/dist/surface/tools/lease-readiness.js +75 -9
  91. package/dist/surface/tools/lease-tools.d.ts +1 -52
  92. package/dist/surface/tools/lease-tools.js +79 -142
  93. package/dist/surface/tools/observe-tools.js +3 -1
  94. package/dist/surface/tools/read-tools.js +5 -5
  95. package/dist/surface/tools/real-input-attempt.js +70 -31
  96. package/dist/surface/tools/session-ports.d.ts +57 -0
  97. package/dist/surface/tools/session-ports.js +102 -0
  98. package/dist/surface/tools/tool-kit.d.ts +5 -3
  99. package/dist/surface/tools/tools.js +1 -1
  100. package/dist/telemetry/daemon-telemetry.d.ts +3 -1
  101. package/dist/telemetry/daemon-telemetry.js +9 -2
  102. package/dist/telemetry/telemetry.d.ts +3 -1
  103. package/dist/telemetry/telemetry.js +2 -0
  104. package/docs/agent-cheatsheet.md +12 -0
  105. package/docs/cli/gate.mdx +1 -1
  106. package/docs/cli/verify.mdx +8 -1
  107. package/docs/first-drive.md +7 -0
  108. package/docs/multi-agent-testing.md +2 -0
  109. package/docs/packages/react.mdx +14 -2
  110. package/docs/packages/vite-plugin.mdx +1 -0
  111. package/docs/predicates.mdx +6 -0
  112. package/docs/skill.md +3 -3
  113. package/docs/troubleshooting.mdx +10 -0
  114. package/docs/usage.md +1 -1
  115. package/package.json +8 -9
@@ -38,9 +38,21 @@ The bridge refuses a connect without the pairing token, also on localhost. `reti
38
38
 
39
39
  | Export | Signature | What it does |
40
40
  | --- | --- | --- |
41
- | `install` | `(): void` | Idempotent. Registers the `react` adapter and installs the render meter. Call it once, before `connect()` |
41
+ | `install` | `(options?: InstallOptions): void` | Idempotent. Registers the `react` adapter and installs the render meter. Call it once, before `connect()` |
42
42
 
43
- The [Vite plugin](/packages/vite-plugin) injects `install()` and `reticle.connect()` for you, so a Vite user never writes either line.
43
+ #### `InstallOptions`
44
+
45
+ | Option | Type | Default | What it does |
46
+ | --- | --- | --- | --- |
47
+ | `discoverStores` | `boolean` | `true` | When `true`, `install` walks the React fiber tree after each of the first ten commits and registers stores it finds in Redux `Provider`, TanStack `QueryClientProvider`, and similar context providers. Set to `false` to skip auto-discovery. Use this when your app has more than one context provider and you want only the stores you name with `registerStore` to appear in `reticle_look`. The render meter still runs. |
48
+
49
+ ```ts
50
+ // Only expose the store you control:
51
+ install({ discoverStores: false });
52
+ registerStore('safe', safeStore);
53
+ ```
54
+
55
+ The [Vite plugin](/packages/vite-plugin) injects `install()` and `reticle.connect()` for you. In Vite, pass `discoverStores: false` to the plugin (`reticle({ discoverStores: false })`) to disable auto-discovery. With manual setup, pass `{ discoverStores: false }` to `install()` before calling `reticle.connect()`.
44
56
 
45
57
  ### Mapping a node to its component
46
58
 
@@ -67,6 +67,7 @@ Plus a dynamic import of your dev module if one exists. It looks for `src/reticl
67
67
  | `present` | `boolean` | `true`. Set `false` to hide Reticle's presenter while keeping the agent connection active |
68
68
  | `sourceMapping` | `boolean` | `true`. Set `false` to skip the Babel pass |
69
69
  | `inject` | `boolean` | `true`. Set `false` to call `connect()` yourself |
70
+ | `discoverStores` | `boolean` | `true`. Set `false` to disable auto-discovery of context stores in React apps (`install({ discoverStores: false })`) |
70
71
  | `desktop` | `boolean` | `false`. When `true` the connect passes `allowInProduction: true`, which an Electron or Tauri renderer needs, and a `vite build` in a non-production mode (`--mode development`) is instrumented too. A production-mode build is stubbed like a web build |
71
72
  | `captureNetworkBodies` | `boolean` | `false`. Also enabled by `VITE_RETICLE_CAPTURE_BODIES=1` |
72
73
  | `networkBodyMaxChars` | `number` | `8192`, clamped to 256 to 262144. Also `VITE_RETICLE_BODY_MAX_CHARS` |
@@ -73,6 +73,12 @@ Add `"absent": true` to assert something is **gone**. The predicate for a remova
73
73
 
74
74
  `contains` is the field the published schema declares. `value`, `text` and `query` are accepted as aliases and rewritten to it. The match is case-sensitive. `ignoreCase: true` relaxes that. Curly quotes (`‘ ’ “ ”`), the en dash and the em dash match their plain forms. So `It's saved - done` matches a page that shows `It’s saved – done`. Text that Reticle reports back keeps the page's own characters. `absent: true` asserts the text is not present, and `visible: true` requires it to be on screen rather than merely in the DOM.
75
75
 
76
+ `text` reads the text that the page renders. It does not read what is typed into an `<input>` or a `<textarea>`, because that is the field's value, not text on the page. `value` on a `text` predicate is only an alias for `contains`, so it also reads rendered text. To assert what a field holds, use an `element` predicate with `value`:
77
+
78
+ ```json
79
+ { "kind": "element", "query": { "role": "textbox", "name": "Notes", "value": "Ship on Friday" } }
80
+ ```
81
+
76
82
  Use `scope` to restrict the search to a CSS selector or element ref. If Reticle reports that the text is split across the scope's children, retry its generated predicate with `"self": true`; that checks the scope root's combined subtree text while still enforcing `contains`.
77
83
 
78
84
  `satisfies` asserts a PROPERTY of the rendered text instead of its exact bytes: the same shape and the same properties [`state` accepts](#satisfies-asserting-a-property-instead-of-exact-bytes), applied where the user actually reads the value:
package/docs/skill.md CHANGED
@@ -3,7 +3,7 @@ name: reticle-docs
3
3
  description: Install, instrument and verify this running web app from the inside (DOM, network, routing, console and framework state) instead of screenshots or guessing. Drives one real flow end to end and returns a verdict with the file:line to fix. Use when the user asks to set up or install Reticle, when a user-facing change needs proving before you call it done, when a test passes but the UI is broken, or when the user types /reticle.
4
4
  license: Apache-2.0
5
5
  metadata:
6
- version: 3.8.0
6
+ version: 3.8.2
7
7
  homepage: https://docs.reticle.sh
8
8
  repository: https://github.com/reticlehq/reticle
9
9
  internal: true
@@ -149,7 +149,7 @@ Stop at the first row that fits. Replaying a saved journey costs a few hundred t
149
149
  | "Did my edit break anything?" | `reticle_verify { action: "change", files: ["src/App.tsx"] }` |
150
150
  | "Does every saved journey still work?" | `reticle_verify { action: "flows" }` |
151
151
  | "Does this new behaviour work?" | `reticle_act_and_wait` on the step that ENDS the journey |
152
- | No MCP at all | `npx @reticlehq/server verify <url> --expect '<predicate JSON>'` |
152
+ | No MCP tools (a cloud agent, a worker) | `npx @reticlehq/server serve`, then `npx @reticlehq/server verify <url> --expect '<predicate JSON>'`. `open <url> --navigate` moves a connected tab to `<url>` |
153
153
 
154
154
  `change` answers `unknown` when no saved flow covers your files: nothing ran, so drive it yourself and never read it as a pass. A locator that was renamed rather than broken: `reticle_verify { action: "heal", flowName }` proposes the rebind, and `apply: true` writes it after it proves the saved consequence again.
155
155
 
@@ -172,7 +172,7 @@ A journey in one call: `reticle_act { steps: [{ target, action, args?, expect? }
172
172
  | ref no longer resolves | the DOM re-rendered: target by `testid` or `role`+`name` |
173
173
  | predicate did not parse | it names the field: fix the shape against the table above |
174
174
  | destructive action blocked | `args.confirmDangerous: true`, only if the user wants that press |
175
- | version skew | `npx @reticlehq/server stop`, then retry |
175
+ | version skew | update the CLI and the app SDK (`npx @reticlehq/server update` in the app's folder), then restart the MCP host |
176
176
  | port held by a non-Reticle process | stop that process, or run Reticle on another `--port` |
177
177
  | tab served from another worktree | start the dev server in your own worktree; keep the port |
178
178
 
@@ -240,6 +240,16 @@ A dev server on `https://` with a self-signed or mkcert certificate makes `retic
240
240
 
241
241
  It is off by default. When it is on, certificate checks are skipped for every site opened in that lease's browser context, including resources loaded from other sites. Other leases keep their checks. A context cannot change the setting once it is made, so acquiring again with the other value replaces the lease instead of reusing it.
242
242
 
243
+ ## The page never connects under a strict CSP
244
+
245
+ A build that sends a strict Content-Security-Policy blocks the bridge socket. A production build that you run locally (`next start`, `vite preview`) often sends one. The app runs, and the SDK never connects, with no error in the app. Add the bridge to `connect-src`, with your bridge port if it is not `4400`:
246
+
247
+ ```text
248
+ connect-src 'self' ws://localhost:4400 ws://127.0.0.1:4400
249
+ ```
250
+
251
+ Add it only in the builds that Reticle drives, never in the policy that you deploy. If the policy also blocks inline scripts, `script-src` stops a pasted connect snippet before it runs: serve that snippet as an external module. `reticle doctor` reads the policy that the page serves and names the line to add, and a lease result says the same. For [production mode](/production-mode), add the `wss://` bridge from the ticket instead. Desktop apps have their own note in [Desktop](/desktop).
252
+
243
253
  ## `ERESOLVE` installing next to a prerelease
244
254
 
245
255
  `@reticlehq/next` declares `peer next >=13` and `@reticlehq/react` declares `peer react >=18`. On a Next canary or React RC, npm refuses. See [the prerelease notes](/getting-started#installing-alongside-a-next-js-or-react-prerelease).
package/docs/usage.md CHANGED
@@ -387,7 +387,7 @@ A **predicate** declares what should be true. `reticle_assert` / `reticle_assert
387
387
  { "kind": "state", "store": "app", "path": "deployments.0.status", "equals": "live" }
388
388
  ```
389
389
 
390
- `visible` excludes elements whose boxes are fully clipped by an ancestor's `overflow:hidden` or `overflow:clip`; a partly clipped element stays visible. Expanding a clamped card can therefore prove that its previously hidden paragraph became visible. `overflow:auto` and `overflow:scroll` keep their existing visibility semantics, including content beyond the scrollport. Ordinary document content outside the window remains visible; `inViewport` checks the window intersection after any hidden/clip ancestor clipping, without introducing scrollport clipping.
390
+ `visible` excludes elements whose boxes are fully clipped by an ancestor's `overflow:hidden` or `overflow:clip`; a partly clipped element stays visible. It also excludes screen-reader-only text: a positioned box with a `clip: rect()` of no area, a `clip-path: inset()` whose edges meet, or a 1×1 box that clips its own overflow. That text stays `present` and still names its control. Expanding a clamped card can therefore prove that its previously hidden paragraph became visible. `overflow:auto` and `overflow:scroll` keep their existing visibility semantics, including content beyond the scrollport. Ordinary document content outside the window remains visible; `inViewport` checks the window intersection after any hidden/clip ancestor clipping, without introducing scrollport clipping.
391
391
 
392
392
  A `state` assertion is graded as a **consequence** (a wrong element or stale render cannot fake it), and is usable the same three ways anywhere predicates flow: ad-hoc (`reticle_assert` / `reticle_act_and_wait` `until`), as a flow step invariant (`reticle_annotate { kind: "assert-state", statePath, store?, equals? }`), and as a flow's golden end-condition (`reticle_annotate { kind: "success-state", statePath, … }`). On a miss it names the real store value and the keys that were available: legible, not a blind fail.
393
393
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reticlehq/server",
3
- "version": "3.8.0",
3
+ "version": "3.8.2",
4
4
  "mcpName": "io.github.reticlehq/reticle",
5
5
  "description": "Reticle CLI, bridge and MCP server: a coding agent drives your running web app from the inside and gets a verdict with evidence, for change verification, access control, accessibility, performance and SEO checks.",
6
6
  "type": "module",
@@ -22,13 +22,12 @@
22
22
  "dependencies": {
23
23
  "@modelcontextprotocol/sdk": "^1.31.0",
24
24
  "ws": "^8.21.3",
25
- "zod": "^3.24.1",
26
- "zod-to-json-schema": "^3.24.0",
27
- "@reticlehq/browser": "3.8.0",
28
- "@reticlehq/init": "3.8.0",
29
- "@reticlehq/core": "3.8.0",
30
- "@reticlehq/engine": "3.8.0",
31
- "open-verification": "1.0.0"
25
+ "zod": "^4.6.6",
26
+ "@reticlehq/browser": "3.8.2",
27
+ "@reticlehq/engine": "3.8.2",
28
+ "open-verification": "1.1.0",
29
+ "@reticlehq/core": "3.8.2",
30
+ "@reticlehq/init": "3.8.2"
32
31
  },
33
32
  "devDependencies": {
34
33
  "@types/pngjs": "^6.0.5",
@@ -65,7 +64,7 @@
65
64
  "cli"
66
65
  ],
67
66
  "reticle": {
68
- "changelog": "Reticle works in git worktrees: each agent reaches only the tabs its own worktree serves, and each run names its branch. reticle init now installs a prompt hook for the agents it finds: each prompt is kept, redacted, in .reticle/, and a linked project sends it with its runs unless \"shareRequests\": false. Background sync sends a linked project while you are signed in, or with RETICLE_API_KEY in CI. See MIGRATION.md (3.7 to 3.8).",
67
+ "changelog": "3.8.1 could not record a verdict: every run it built or read failed with an Invalid element at key subject error. 3.8.2 fixes it. Update the CLI and the SDK in your app.",
69
68
  "breakingChanges": []
70
69
  },
71
70
  "publishConfig": {