@reticlehq/test 2.1.0 → 2.2.1

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/README.md ADDED
@@ -0,0 +1,73 @@
1
+ # @reticlehq/test
2
+
3
+ Reticle's spec runner for CI: write behavioral specs against your running app with `reticleTest`, drive them through Reticle's verification tools (DOM + network + console + app state) **without MCP/stdio**, and get a summary + JUnit XML your pipeline can gate on.
4
+
5
+ Part of [Reticle](https://github.com/reticlehq/reticle) — the in-app verification layer for AI agents. Use this package when you want the same inside-the-app assertions (signals, store state, network counts — the things a DOM-only tool can't see) as a plain CI test suite.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm i -D @reticlehq/test
11
+ ```
12
+
13
+ `vitest` is a peer dependency for the matcher integration; the standalone runner below needs only Node.
14
+
15
+ ## Write a spec
16
+
17
+ ```ts
18
+ import { reticleTest } from '@reticlehq/test';
19
+
20
+ reticleTest('add a task', async (t) => {
21
+ await t.act('add-task', 'click');
22
+ await t.expectElement({ testid: 'task-list' }, 'visible');
23
+ });
24
+
25
+ reticleTest('ai chat edit', async (t) => {
26
+ await t.fill('chat-input', 'Make the hook punchier');
27
+ await t.act('chat-send', 'click');
28
+ await t.expectNet('POST', '/chat-script', 200);
29
+ await t.expectSignal('chat:edit-applied', { sections: ['hook'] });
30
+ });
31
+ ```
32
+
33
+ The context `t` is a thin, typed façade over Reticle's tools — it resolves `data-testid`s to live elements for you, so specs never touch refs, selectors, or the DOM directly, and assertions run against the app's real network buffer, console, signals, and registered stores.
34
+
35
+ ## Run in CI
36
+
37
+ ```ts
38
+ import { bootSession, runSpecs, createTestContext, writeJUnit } from '@reticlehq/test';
39
+
40
+ // … reticleTest(...) registrations above …
41
+
42
+ const booted = await bootSession({ driveUrl: 'http://localhost:4310', headless: true });
43
+ const { summary } = await runSpecs({
44
+ invoke: booted.invoke,
45
+ now: () => Date.now(),
46
+ buildContext: (invoke) => createTestContext(invoke, { sessionId: 'my-app' }),
47
+ print: (line) => process.stdout.write(line + '\n'),
48
+ });
49
+ await booted.close();
50
+ process.exit(summary.failed === 0 ? 0 : 1);
51
+ ```
52
+
53
+ `bootSession` launches a headless browser against your dev server via the Reticle daemon; `runSpecs` executes every registered spec and returns a machine-readable summary. `writeJUnit(...)` emits JUnit XML for CI dashboards.
54
+
55
+ ## Main exports
56
+
57
+ | Export | Purpose |
58
+ | --- | --- |
59
+ | `reticleTest`, `register`, `getRegistered`, `clearRegistry` | spec registration |
60
+ | `runSpecs`, `runOne`, `summarize`, `printSummary` | execution + reporting |
61
+ | `toJUnitXml`, `writeJUnit` | CI artifact output |
62
+ | `bootSession` | boot a driven browser session without MCP |
63
+ | `createTestContext` | the `t` façade (act / expectElement / expectNet / expectSignal / expectState …) |
64
+ | `ReticleSkip`, `ReticleAssertionError`, `isSkip` | control-flow + failure types |
65
+
66
+ ## Docs
67
+
68
+ - [Testing guide](https://github.com/reticlehq/reticle/blob/main/docs/testing.md)
69
+ - [Getting started with Reticle](https://github.com/reticlehq/reticle/blob/main/docs/getting-started.md)
70
+
71
+ ## License
72
+
73
+ FSL-1.1-ALv2 — free for any use except reselling Reticle itself; converts to Apache-2.0 after two years. See [LICENSE](./LICENSE).
@@ -29,12 +29,12 @@ export declare const JUnit: {
29
29
  /** Default JUnit <testsuite name=...> when the caller does not supply one. */
30
30
  export declare const DEFAULT_JUNIT_SUITE_NAME = "reticle";
31
31
  /**
32
- * Skip reason `t.expectInputModeReal()` raises when the active input mode is 'synthetic'.
32
+ * Skip reason `t.expectInputModeReal` raises when the active input mode is 'synthetic'.
33
33
  * The runner turns the ReticleSkip carrying this into status:'skip' (never a silent pass).
34
34
  */
35
35
  export declare const SKIP_REASON_REAL_INPUT = "real input not active \u2014 run via reticle drive";
36
- /** Default wait window for assertion matchers (reticle_assert timeout_ms). */
37
- export declare const DEFAULT_ASSERT_TIMEOUT_MS = 4000;
36
+ /** Default wait window for assertion matchers — re-exported from core so it matches the server default. */
37
+ export { DEFAULT_ASSERT_TIMEOUT_MS } from '@reticlehq/core';
38
38
  /** Predicate `kind` discriminants the matchers build. Mirrors @reticlehq/server's Predicate union. */
39
39
  export declare const PredicateKind: {
40
40
  readonly SIGNAL: "signal";
@@ -50,7 +50,7 @@ export declare const CONSOLE_LEVEL_ERROR = "error";
50
50
  export declare const NO_ELEMENT_FOR_TESTID = "no element for testid";
51
51
  /**
52
52
  * Default testid the input-mode probe resolves to when no act has run yet. Apps that opt into
53
- * `expectInputModeReal()` before any act should tag a stable benign element with this testid;
53
+ * `expectInputModeReal` before any act should tag a stable benign element with this testid;
54
54
  * the probe runs a non-mutating SCROLL_INTO_VIEW against it purely to read the reported inputMode.
55
55
  */
56
56
  export declare const PROBE_TESTID = "reticle-root";
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,eAAO,MAAM,UAAU;;;;CAAwD,CAAC;AAChF,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,OAAO,UAAU,CAAC,CAAC;AAEtE,iEAAiE;AACjE,eAAO,MAAM,YAAY;;;;CAIsB,CAAC;AAEhD,mGAAmG;AACnG,eAAO,MAAM,qBAAqB,kBAAkB,CAAC;AAErD,wEAAwE;AACxE,eAAO,MAAM,KAAK;;;;;;;;;;;CAWR,CAAC;AAEX,8EAA8E;AAC9E,eAAO,MAAM,wBAAwB,YAAY,CAAC;AAElD;;;GAGG;AACH,eAAO,MAAM,sBAAsB,uDAAkD,CAAC;AAEtF,8EAA8E;AAC9E,eAAO,MAAM,yBAAyB,OAAO,CAAC;AAE9C,sGAAsG;AACtG,eAAO,MAAM,aAAa;;;;;;CAMhB,CAAC;AACX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,OAAO,aAAa,CAAC,CAAC;AAE/E,yEAAyE;AACzE,eAAO,MAAM,mBAAmB,UAAU,CAAC;AAE3C,sFAAsF;AACtF,eAAO,MAAM,qBAAqB,0BAA0B,CAAC;AAE7D;;;;GAIG;AACH,eAAO,MAAM,YAAY,iBAAiB,CAAC;AAE3C;;;;GAIG;AACH,eAAO,MAAM,QAAQ;;;CAAoD,CAAC;AAC1E,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,QAAQ,CAAC,CAAC,MAAM,OAAO,QAAQ,CAAC,CAAC;AAEhE,uEAAuE;AACvE,eAAO,MAAM,WAAW;;;CAA0C,CAAC;AACnE,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,OAAO,WAAW,CAAC,CAAC;AAEzE;;;;;GAKG;AACH,eAAO,MAAM,WAAW;;;;CAId,CAAC;AACX,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,OAAO,WAAW,CAAC,CAAC;AAEzE,8FAA8F;AAC9F,eAAO,MAAM,sBAAsB,6BAA6B,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,eAAO,MAAM,UAAU;;;;CAAwD,CAAC;AAChF,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,OAAO,UAAU,CAAC,CAAC;AAEtE,iEAAiE;AACjE,eAAO,MAAM,YAAY;;;;CAIsB,CAAC;AAEhD,mGAAmG;AACnG,eAAO,MAAM,qBAAqB,kBAAkB,CAAC;AAErD,wEAAwE;AACxE,eAAO,MAAM,KAAK;;;;;;;;;;;CAWR,CAAC;AAEX,8EAA8E;AAC9E,eAAO,MAAM,wBAAwB,YAAY,CAAC;AAElD;;;GAGG;AACH,eAAO,MAAM,sBAAsB,uDAAkD,CAAC;AAEtF,2GAA2G;AAC3G,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAE5D,sGAAsG;AACtG,eAAO,MAAM,aAAa;;;;;;CAMhB,CAAC;AACX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,OAAO,aAAa,CAAC,CAAC;AAE/E,yEAAyE;AACzE,eAAO,MAAM,mBAAmB,UAAU,CAAC;AAE3C,sFAAsF;AACtF,eAAO,MAAM,qBAAqB,0BAA0B,CAAC;AAE7D;;;;GAIG;AACH,eAAO,MAAM,YAAY,iBAAiB,CAAC;AAE3C;;;;GAIG;AACH,eAAO,MAAM,QAAQ;;;CAAoD,CAAC;AAC1E,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,QAAQ,CAAC,CAAC,MAAM,OAAO,QAAQ,CAAC,CAAC;AAEhE,uEAAuE;AACvE,eAAO,MAAM,WAAW;;;CAA0C,CAAC;AACnE,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,OAAO,WAAW,CAAC,CAAC;AAEzE;;;;;GAKG;AACH,eAAO,MAAM,WAAW;;;;CAId,CAAC;AACX,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,OAAO,WAAW,CAAC,CAAC;AAEzE,8FAA8F;AAC9F,eAAO,MAAM,sBAAsB,6BAA6B,CAAC"}
package/dist/constants.js CHANGED
@@ -24,12 +24,12 @@ export const JUnit = {
24
24
  /** Default JUnit <testsuite name=...> when the caller does not supply one. */
25
25
  export const DEFAULT_JUNIT_SUITE_NAME = 'reticle';
26
26
  /**
27
- * Skip reason `t.expectInputModeReal()` raises when the active input mode is 'synthetic'.
27
+ * Skip reason `t.expectInputModeReal` raises when the active input mode is 'synthetic'.
28
28
  * The runner turns the ReticleSkip carrying this into status:'skip' (never a silent pass).
29
29
  */
30
30
  export const SKIP_REASON_REAL_INPUT = 'real input not active — run via reticle drive';
31
- /** Default wait window for assertion matchers (reticle_assert timeout_ms). */
32
- export const DEFAULT_ASSERT_TIMEOUT_MS = 4000;
31
+ /** Default wait window for assertion matchers — re-exported from core so it matches the server default. */
32
+ export { DEFAULT_ASSERT_TIMEOUT_MS } from '@reticlehq/core';
33
33
  /** Predicate `kind` discriminants the matchers build. Mirrors @reticlehq/server's Predicate union. */
34
34
  export const PredicateKind = {
35
35
  SIGNAL: 'signal',
@@ -44,7 +44,7 @@ export const CONSOLE_LEVEL_ERROR = 'error';
44
44
  export const NO_ELEMENT_FOR_TESTID = 'no element for testid';
45
45
  /**
46
46
  * Default testid the input-mode probe resolves to when no act has run yet. Apps that opt into
47
- * `expectInputModeReal()` before any act should tag a stable benign element with this testid;
47
+ * `expectInputModeReal` before any act should tag a stable benign element with this testid;
48
48
  * the probe runs a non-mutating SCROLL_INTO_VIEW against it purely to read the reported inputMode.
49
49
  */
50
50
  export const PROBE_TESTID = 'reticle-root';
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,MAAM,CAAC,MAAM,UAAU,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAW,CAAC;AAGhF,iEAAiE;AACjE,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,IAAI,EAAE,MAAM;IACZ,IAAI,EAAE,MAAM;IACZ,IAAI,EAAE,MAAM;CACiC,CAAC;AAEhD,mGAAmG;AACnG,MAAM,CAAC,MAAM,qBAAqB,GAAG,eAAe,CAAC;AAErD,wEAAwE;AACxE,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,KAAK,EAAE,WAAW;IAClB,IAAI,EAAE,UAAU;IAChB,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,SAAS,EAAE,MAAM;IACjB,UAAU,EAAE,OAAO;IACnB,aAAa,EAAE,UAAU;IACzB,YAAY,EAAE,SAAS;IACvB,SAAS,EAAE,MAAM;IACjB,YAAY,EAAE,SAAS;CACf,CAAC;AAEX,8EAA8E;AAC9E,MAAM,CAAC,MAAM,wBAAwB,GAAG,SAAS,CAAC;AAElD;;;GAGG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,+CAA+C,CAAC;AAEtF,8EAA8E;AAC9E,MAAM,CAAC,MAAM,yBAAyB,GAAG,IAAI,CAAC;AAE9C,sGAAsG;AACtG,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,MAAM,EAAE,QAAQ;IAChB,GAAG,EAAE,KAAK;IACV,OAAO,EAAE,SAAS;IAClB,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,SAAS;CACV,CAAC;AAGX,yEAAyE;AACzE,MAAM,CAAC,MAAM,mBAAmB,GAAG,OAAO,CAAC;AAE3C,sFAAsF;AACtF,MAAM,CAAC,MAAM,qBAAqB,GAAG,uBAAuB,CAAC;AAE7D;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,cAAc,CAAC;AAE3C;;;;GAIG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAW,CAAC;AAG1E,uEAAuE;AACvE,MAAM,CAAC,MAAM,WAAW,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAW,CAAC;AAGnE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,eAAe,EAAE,kDAAkD;IACnE,UAAU,EAAE,kDAAkD;IAC9D,SAAS,EAAE,uDAAuD;CAC1D,CAAC;AAGX,8FAA8F;AAC9F,MAAM,CAAC,MAAM,sBAAsB,GAAG,0BAA0B,CAAC"}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,MAAM,CAAC,MAAM,UAAU,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAW,CAAC;AAGhF,iEAAiE;AACjE,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,IAAI,EAAE,MAAM;IACZ,IAAI,EAAE,MAAM;IACZ,IAAI,EAAE,MAAM;CACiC,CAAC;AAEhD,mGAAmG;AACnG,MAAM,CAAC,MAAM,qBAAqB,GAAG,eAAe,CAAC;AAErD,wEAAwE;AACxE,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,KAAK,EAAE,WAAW;IAClB,IAAI,EAAE,UAAU;IAChB,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,SAAS,EAAE,MAAM;IACjB,UAAU,EAAE,OAAO;IACnB,aAAa,EAAE,UAAU;IACzB,YAAY,EAAE,SAAS;IACvB,SAAS,EAAE,MAAM;IACjB,YAAY,EAAE,SAAS;CACf,CAAC;AAEX,8EAA8E;AAC9E,MAAM,CAAC,MAAM,wBAAwB,GAAG,SAAS,CAAC;AAElD;;;GAGG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,+CAA+C,CAAC;AAEtF,2GAA2G;AAC3G,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAE5D,sGAAsG;AACtG,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,MAAM,EAAE,QAAQ;IAChB,GAAG,EAAE,KAAK;IACV,OAAO,EAAE,SAAS;IAClB,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,SAAS;CACV,CAAC;AAGX,yEAAyE;AACzE,MAAM,CAAC,MAAM,mBAAmB,GAAG,OAAO,CAAC;AAE3C,sFAAsF;AACtF,MAAM,CAAC,MAAM,qBAAqB,GAAG,uBAAuB,CAAC;AAE7D;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,cAAc,CAAC;AAE3C;;;;GAIG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAW,CAAC;AAG1E,uEAAuE;AACvE,MAAM,CAAC,MAAM,WAAW,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAW,CAAC;AAGnE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,eAAe,EAAE,kDAAkD;IACnE,UAAU,EAAE,kDAAkD;IAC9D,SAAS,EAAE,uDAAuD;CAC1D,CAAC;AAGX,8FAA8F;AAC9F,MAAM,CAAC,MAAM,sBAAsB,GAAG,0BAA0B,CAAC"}
package/dist/flow-spec.js CHANGED
@@ -39,7 +39,7 @@ export function flowToSpec(flow, opts) {
39
39
  },
40
40
  };
41
41
  }
42
- /** An ERROR spec for a flow file that failed to load. Its run() returns a FAIL with no steps. */
42
+ /** An ERROR spec for a flow file that failed to load. Its run returns a FAIL with no steps. */
43
43
  function errorSpec(name, code) {
44
44
  const result = {
45
45
  outcome: SpecOutcome.FAIL,
@@ -1 +1 @@
1
- {"version":3,"file":"flow-spec.js","sourceRoot":"","sources":["../src/flow-spec.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,sBAAsB,GAIvB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAQlG,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAiCpD,2FAA2F;AAC3F,SAAS,YAAY,CAAC,IAAc;IAClC,OAAO,IAAI,GAAG,CACZ,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;SACjB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,MAAM,CAAC;SAC3C,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAC7D,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,IAAc,EAAE,IAAsB;IAC/D,MAAM,aAAa,GAAG,IAAI,EAAE,aAAa,IAAI,gBAAgB,CAAC;IAC9D,MAAM,SAAS,GAAG,IAAI,EAAE,eAAe,IAAI,sBAAsB,CAAC;IAClE,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,IAAI,EAAE,QAAQ,CAAC,QAAQ;QACvB,GAAG,EAAE,KAAK,EAAE,OAA0B,EAA0B,EAAE;YAChE,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,SAAS,CAAC,CAAC;YACxE,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACzC,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;YACnC,MAAM,aAAa,GAAG,MAAM,aAAa,CACvC,OAAO,EACP,IAAI,CAAC,OAAO,EACZ,OAAO,EACP,aAAa,EACb,SAAS,CACV,CAAC;YACF,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,WAAW,CAAC,UAAU,EAAE,CAAC;YAC9F,CAAC;YACD,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC;gBACxB,OAAO;oBACL,OAAO,EAAE,WAAW,CAAC,IAAI;oBACzB,KAAK;oBACL,aAAa;oBACb,OAAO,EAAE,WAAW,CAAC,eAAe;iBACrC,CAAC;YACJ,CAAC;YACD,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC;QAC7D,CAAC;KACF,CAAC;AACJ,CAAC;AAED,iGAAiG;AACjG,SAAS,SAAS,CAAC,IAAY,EAAE,IAAmB;IAClD,MAAM,MAAM,GAAkB;QAC5B,OAAO,EAAE,WAAW,CAAC,IAAI;QACzB,KAAK,EAAE,EAAE;QACT,aAAa,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE;QACnD,OAAO,EAAE,WAAW,CAAC,UAAU;KAChC,CAAC;IACF,OAAO;QACL,IAAI;QACJ,IAAI,EAAE,QAAQ,CAAC,KAAK;QACpB,SAAS,EAAE,EAAE,IAAI,EAAE;QACnB,GAAG,EAAE,GAA2B,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC;KAC3D,CAAC;AACJ,CAAC;AASD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,MAA0B,EAC1B,IAA0B;IAE1B,MAAM,KAAK,GACT,OAAO,MAAM,KAAK,QAAQ;QACxB,CAAC,CAAC,IAAI,SAAS,CAAC,IAAI,EAAE,EAAE,IAAI,oBAAoB,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC;QAC5F,CAAC,CAAC,MAAM,CAAC;IAEb,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;IACjC,MAAM,KAAK,GAAe,EAAE,CAAC;IAC7B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtC,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;YACd,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;QAC7C,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
1
+ {"version":3,"file":"flow-spec.js","sourceRoot":"","sources":["../src/flow-spec.ts"],"names":[],"mappings":"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"}
@@ -3,7 +3,7 @@ import { InputMode } from '@reticlehq/core';
3
3
  /** The act envelope's inputMode field, narrowed from the raw tool result. */
4
4
  export declare function readInputMode(actResult: unknown): InputMode | undefined;
5
5
  /**
6
- * Tracks the most recent act's inputMode across a spec so `expectInputModeReal()` can read it
6
+ * Tracks the most recent act's inputMode across a spec so `expectInputModeReal` can read it
7
7
  * without re-touching the page. The context records every act through `record`.
8
8
  */
9
9
  export declare class InputModeTracker {
@@ -15,7 +15,7 @@ export function readInputMode(actResult) {
15
15
  return undefined;
16
16
  }
17
17
  /**
18
- * Tracks the most recent act's inputMode across a spec so `expectInputModeReal()` can read it
18
+ * Tracks the most recent act's inputMode across a spec so `expectInputModeReal` can read it
19
19
  * without re-touching the page. The context records every act through `record`.
20
20
  */
21
21
  export class InputModeTracker {
package/dist/skip.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * The skip sentinel. MATCHERS' `t.expectInputModeReal()` throws this when the active input mode
2
+ * The skip sentinel. MATCHERS' `t.expectInputModeReal` throws this when the active input mode
3
3
  * is not 'real', so the runner reports `status:'skip'` (with the reason) instead of a silent pass.
4
4
  */
5
5
  export declare class ReticleSkip extends Error {
package/dist/skip.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * The skip sentinel. MATCHERS' `t.expectInputModeReal()` throws this when the active input mode
2
+ * The skip sentinel. MATCHERS' `t.expectInputModeReal` throws this when the active input mode
3
3
  * is not 'real', so the runner reports `status:'skip'` (with the reason) instead of a silent pass.
4
4
  */
5
5
  export class ReticleSkip extends Error {
package/dist/spec.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  import type { SpecFn } from './types.js';
2
- /** Public registration entry: `reticleTest('does X', async (t) => { ... })`. */
2
+ /** Public registration entry: `reticleTest('does X', async (t) => {... })`. */
3
3
  export declare function reticleTest(name: string, fn: SpecFn): void;
4
4
  //# sourceMappingURL=spec.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"spec.d.ts","sourceRoot":"","sources":["../src/spec.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC,gFAAgF;AAChF,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAE1D"}
1
+ {"version":3,"file":"spec.d.ts","sourceRoot":"","sources":["../src/spec.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC,+EAA+E;AAC/E,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAE1D"}
package/dist/spec.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { register } from './registry.js';
2
- /** Public registration entry: `reticleTest('does X', async (t) => { ... })`. */
2
+ /** Public registration entry: `reticleTest('does X', async (t) => {... })`. */
3
3
  export function reticleTest(name, fn) {
4
4
  register({ name, fn });
5
5
  }
package/dist/spec.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"spec.js","sourceRoot":"","sources":["../src/spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGzC,gFAAgF;AAChF,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,EAAU;IAClD,QAAQ,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;AACzB,CAAC"}
1
+ {"version":3,"file":"spec.js","sourceRoot":"","sources":["../src/spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGzC,+EAA+E;AAC/E,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,EAAU;IAClD,QAAQ,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;AACzB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reticlehq/test",
3
- "version": "2.1.0",
3
+ "version": "2.2.1",
4
4
  "description": "Reticle test runner: reticleTest spec registry + a runner that drives Reticle tools without MCP/stdio.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -12,8 +12,8 @@
12
12
  }
13
13
  },
14
14
  "dependencies": {
15
- "@reticlehq/core": "2.1.0",
16
- "@reticlehq/server": "2.1.0"
15
+ "@reticlehq/core": "2.2.1",
16
+ "@reticlehq/server": "2.2.1"
17
17
  },
18
18
  "peerDependencies": {
19
19
  "vitest": "^3.2.6"
@@ -45,6 +45,9 @@
45
45
  "publishConfig": {
46
46
  "access": "public"
47
47
  },
48
+ "engines": {
49
+ "node": ">=20.0.0"
50
+ },
48
51
  "scripts": {
49
52
  "build": "tsc -b",
50
53
  "typecheck": "tsc -b",