@reticlehq/test 2.14.0 → 3.2.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.
@@ -1,7 +1,7 @@
1
1
  import { ReticleTool } from '@reticlehq/server';
2
2
  import { InputMode } from '@reticlehq/core';
3
- import { ReticleSkip } from './skip.js';
4
- import { SKIP_REASON_REAL_INPUT } from './constants.js';
3
+ import { ReticleSkip } from '../outcome/skip.js';
4
+ import { SKIP_REASON_REAL_INPUT } from '../outcome/constants.js';
5
5
  function isRecord(value) {
6
6
  return 'object' === typeof value && value !== null;
7
7
  }
@@ -1,7 +1,7 @@
1
1
  import { ReticleTool } from '@reticlehq/server';
2
2
  import { Verified } from '@reticlehq/core';
3
- import { ReticleAssertionError } from './skip.js';
4
- import { CONSOLE_LEVEL_ERROR, DEFAULT_ASSERT_TIMEOUT_MS, PredicateKind } from './constants.js';
3
+ import { ReticleAssertionError } from '../outcome/skip.js';
4
+ import { CONSOLE_LEVEL_ERROR, DEFAULT_ASSERT_TIMEOUT_MS, PredicateKind, } from '../outcome/constants.js';
5
5
  /**
6
6
  * Did this verdict PROVE the thing the spec asserted?
7
7
  *
@@ -1,7 +1,7 @@
1
1
  import { ReticleTool } from '@reticlehq/server';
2
2
  import { QueryBy } from '@reticlehq/core';
3
- import { ReticleQueryEmptyError } from './skip.js';
4
- import { NO_ELEMENT_FOR_TESTID } from './constants.js';
3
+ import { ReticleQueryEmptyError } from '../outcome/skip.js';
4
+ import { NO_ELEMENT_FOR_TESTID } from '../outcome/constants.js';
5
5
  function asQueryEnvelope(value) {
6
6
  if (typeof value !== 'object' || null === value)
7
7
  return {};
@@ -1,8 +1,8 @@
1
1
  import { type FlowErrorCode, type FlowFile, type FlowStepResult } from '@reticlehq/core';
2
2
  import { FlowStore } from '@reticlehq/server';
3
3
  import type { Clock, EvalResult, FileSystemPort, FlowReplaySession, WaitForSignal } from '@reticlehq/server';
4
- import { SpecKind, SpecMessage, SpecOutcome } from './constants.js';
5
- /** FLOW2SPEC — the result of running one RUNNABLE flow spec, evidence-bearing on a FAIL. */
4
+ import { SpecKind, SpecMessage, SpecOutcome } from './outcome/constants.js';
5
+ /** The result of running one RUNNABLE flow spec, evidence-bearing on a FAIL. */
6
6
  export interface SpecRunResult {
7
7
  outcome: SpecOutcome;
8
8
  /** Verbatim from replayFlow — carries each step's drift/nearest evidence. */
@@ -13,7 +13,7 @@ export interface SpecRunResult {
13
13
  message?: SpecMessage;
14
14
  }
15
15
  /**
16
- * FLOW2SPEC — one flow rendered as a runnable spec. Every spec carries `run`. A RUNNABLE spec
16
+ * One flow rendered as a runnable spec. Every spec carries `run`. A RUNNABLE spec
17
17
  * replays + asserts success; an ERROR spec (file missing/malformed/badly-named) carries `loadError`
18
18
  * and a `run` whose returned SpecRunResult is FAIL, so a corrupted flow fails loudly in the suite
19
19
  * rather than vanishing. The vitest binding (register.ts) turns the load error into a thrown Error.
@@ -45,7 +45,7 @@ export interface FlowsAsSpecsOptions extends FlowSpecOptions {
45
45
  clock?: Clock;
46
46
  }
47
47
  /**
48
- * FLOW2SPEC — enumerate a flows dir (or a live FlowStore) into FlowSpec[]. The map (.reticle/flows)
48
+ * Enumerate a flows dir (or a live FlowStore) into FlowSpec[]. The map (.reticle/flows)
49
49
  * IS the suite. An empty/absent dir yields [] (no throw). A malformed/badly-named file becomes an
50
50
  * ERROR spec; enumeration of its siblings is never aborted.
51
51
  */
package/dist/flow-spec.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { AnchorKind, FLOW_SIGNAL_TIMEOUT_MS, } from '@reticlehq/core';
2
2
  import { FlowStore, createNodeFileSystem, replayFlow, waitForPredicate } from '@reticlehq/server';
3
- import { SpecKind, SpecMessage, SpecOutcome } from './constants.js';
4
- import { assertSuccess } from './success-assert.js';
3
+ import { SpecKind, SpecMessage, SpecOutcome } from './outcome/constants.js';
4
+ import { assertSuccess } from './outcome/success-assert.js';
5
5
  /** Derive the dynamic testid skip-set exactly as replayFlow does (testid anchors only). */
6
6
  function toDynamicSet(flow) {
7
7
  return new Set((flow.dynamic ?? [])
@@ -55,7 +55,7 @@ function errorSpec(name, code) {
55
55
  };
56
56
  }
57
57
  /**
58
- * FLOW2SPEC — enumerate a flows dir (or a live FlowStore) into FlowSpec[]. The map (.reticle/flows)
58
+ * Enumerate a flows dir (or a live FlowStore) into FlowSpec[]. The map (.reticle/flows)
59
59
  * IS the suite. An empty/absent dir yields [] (no throw). A malformed/badly-named file becomes an
60
60
  * ERROR spec; enumeration of its siblings is never aborted.
61
61
  */
package/dist/index.d.ts CHANGED
@@ -5,18 +5,18 @@ export { summarize, printSummary } from './summary.js';
5
5
  export { toJUnitXml, writeJUnit } from './junit.js';
6
6
  export { bootSession } from './boot.js';
7
7
  export type { BootedRun, BootOptions } from './boot.js';
8
- export { ReticleSkip, ReticleAssertionError, ReticleQueryEmptyError, isSkip } from './skip.js';
9
- export type { AssertionDetail } from './skip.js';
8
+ export { ReticleSkip, ReticleAssertionError, ReticleQueryEmptyError, isSkip, } from './outcome/skip.js';
9
+ export type { AssertionDetail } from './outcome/skip.js';
10
10
  export { createTestContext } from './test-context.js';
11
11
  export type { TestContext, TestContextOptions, Predicate } from './test-context.js';
12
- export type { TestClock } from './clock.js';
13
- export { resolveTestid } from './resolve.js';
14
- export { expectInputModeReal, InputModeTracker, readInputMode } from './input-mode.js';
15
- export { TestStatus, STATUS_GLYPH, SUMMARY_FOOTER_PREFIX, JUnit, DEFAULT_JUNIT_SUITE_NAME, SKIP_REASON_REAL_INPUT, DEFAULT_ASSERT_TIMEOUT_MS, PredicateKind, PROBE_TESTID, } from './constants.js';
12
+ export type { TestClock } from './context/clock.js';
13
+ export { resolveTestid } from './context/resolve.js';
14
+ export { expectInputModeReal, InputModeTracker, readInputMode } from './context/input-mode.js';
15
+ export { TestStatus, STATUS_GLYPH, SUMMARY_FOOTER_PREFIX, JUnit, DEFAULT_JUNIT_SUITE_NAME, SKIP_REASON_REAL_INPUT, DEFAULT_ASSERT_TIMEOUT_MS, PredicateKind, PROBE_TESTID, } from './outcome/constants.js';
16
16
  export type { SpecContext, SpecFn, ReticleSpec, SpecResult, RunSummary, ContextFactory, RunnerOptions, } from './types.js';
17
17
  export { flowToSpec, flowsAsSpecs } from './flow-spec.js';
18
18
  export type { FlowSpec, FlowSpecOptions, FlowsAsSpecsOptions, SpecRunResult } from './flow-spec.js';
19
- export { assertSuccess, successToPredicate } from './success-assert.js';
19
+ export { assertSuccess, successToPredicate } from './outcome/success-assert.js';
20
20
  export { registerFlowSpecs, FlowMalformedError, SpecFailure } from './register.js';
21
21
  export type { RegisterFn, RegisterFlowSpecsOptions } from './register.js';
22
- export { SpecKind, SpecOutcome, SpecMessage, FLOW_LOAD_ERROR_PREFIX } from './constants.js';
22
+ export { SpecKind, SpecOutcome, SpecMessage, FLOW_LOAD_ERROR_PREFIX } from './outcome/constants.js';
package/dist/index.js CHANGED
@@ -4,13 +4,13 @@ export { runSpecs, runOne } from './runner.js';
4
4
  export { summarize, printSummary } from './summary.js';
5
5
  export { toJUnitXml, writeJUnit } from './junit.js';
6
6
  export { bootSession } from './boot.js';
7
- export { ReticleSkip, ReticleAssertionError, ReticleQueryEmptyError, isSkip } from './skip.js';
7
+ export { ReticleSkip, ReticleAssertionError, ReticleQueryEmptyError, isSkip, } from './outcome/skip.js';
8
8
  export { createTestContext } from './test-context.js';
9
- export { resolveTestid } from './resolve.js';
10
- export { expectInputModeReal, InputModeTracker, readInputMode } from './input-mode.js';
11
- export { TestStatus, STATUS_GLYPH, SUMMARY_FOOTER_PREFIX, JUnit, DEFAULT_JUNIT_SUITE_NAME, SKIP_REASON_REAL_INPUT, DEFAULT_ASSERT_TIMEOUT_MS, PredicateKind, PROBE_TESTID, } from './constants.js';
9
+ export { resolveTestid } from './context/resolve.js';
10
+ export { expectInputModeReal, InputModeTracker, readInputMode } from './context/input-mode.js';
11
+ export { TestStatus, STATUS_GLYPH, SUMMARY_FOOTER_PREFIX, JUnit, DEFAULT_JUNIT_SUITE_NAME, SKIP_REASON_REAL_INPUT, DEFAULT_ASSERT_TIMEOUT_MS, PredicateKind, PROBE_TESTID, } from './outcome/constants.js';
12
12
  // flows under .reticle/flows become the runnable suite.
13
13
  export { flowToSpec, flowsAsSpecs } from './flow-spec.js';
14
- export { assertSuccess, successToPredicate } from './success-assert.js';
14
+ export { assertSuccess, successToPredicate } from './outcome/success-assert.js';
15
15
  export { registerFlowSpecs, FlowMalformedError, SpecFailure } from './register.js';
16
- export { SpecKind, SpecOutcome, SpecMessage, FLOW_LOAD_ERROR_PREFIX } from './constants.js';
16
+ export { SpecKind, SpecOutcome, SpecMessage, FLOW_LOAD_ERROR_PREFIX } from './outcome/constants.js';
package/dist/junit.js CHANGED
@@ -1,4 +1,4 @@
1
- import { DEFAULT_JUNIT_SUITE_NAME, JUnit, TestStatus } from './constants.js';
1
+ import { DEFAULT_JUNIT_SUITE_NAME, JUnit, TestStatus } from './outcome/constants.js';
2
2
  import { summarize } from './summary.js';
3
3
  /**
4
4
  * XML 1.0 section 2.2, the whole `Char` production:
@@ -64,14 +64,14 @@ export declare const SpecKind: {
64
64
  readonly ERROR: "error";
65
65
  };
66
66
  export type SpecKind = (typeof SpecKind)[keyof typeof SpecKind];
67
- /** FLOW2SPEC: the binary outcome of running one RUNNABLE flow spec. */
67
+ /** The binary outcome of running one RUNNABLE flow spec. */
68
68
  export declare const SpecOutcome: {
69
69
  readonly PASS: "pass";
70
70
  readonly FAIL: "fail";
71
71
  };
72
72
  export type SpecOutcome = (typeof SpecOutcome)[keyof typeof SpecOutcome];
73
73
  /**
74
- * FLOW2SPEC: the named failure/diagnostic messages a flow spec can carry — never a free string.
74
+ * The named failure/diagnostic messages a flow spec can carry — never a free string.
75
75
  * SUCCESS_NOT_MET: replay was clean but flow.success did not hold. STEP_DRIFT: a step anchor
76
76
  * drifted or its expect did not hold (replay stopped). EMPTY_DIR: documentation-only note that an
77
77
  * empty .reticle/flows yields zero specs.
@@ -82,5 +82,5 @@ export declare const SpecMessage: {
82
82
  readonly EMPTY_DIR: "no flows under .reticle/flows — zero specs registered";
83
83
  };
84
84
  export type SpecMessage = (typeof SpecMessage)[keyof typeof SpecMessage];
85
- /** FLOW2SPEC: prefix of the Error a malformed/missing flow file raises when its spec runs. */
85
+ /** Prefix of the Error a malformed/missing flow file raises when its spec runs. */
86
86
  export declare const FLOW_LOAD_ERROR_PREFIX = "flow could not be loaded";
@@ -54,10 +54,10 @@ export const PROBE_TESTID = 'reticle-root';
54
54
  * missing/malformed/badly-named, surfaces as an ERROR spec that fails loudly (never a silent skip).
55
55
  */
56
56
  export const SpecKind = { RUNNABLE: 'runnable', ERROR: 'error' };
57
- /** FLOW2SPEC: the binary outcome of running one RUNNABLE flow spec. */
57
+ /** The binary outcome of running one RUNNABLE flow spec. */
58
58
  export const SpecOutcome = { PASS: 'pass', FAIL: 'fail' };
59
59
  /**
60
- * FLOW2SPEC: the named failure/diagnostic messages a flow spec can carry — never a free string.
60
+ * The named failure/diagnostic messages a flow spec can carry — never a free string.
61
61
  * SUCCESS_NOT_MET: replay was clean but flow.success did not hold. STEP_DRIFT: a step anchor
62
62
  * drifted or its expect did not hold (replay stopped). EMPTY_DIR: documentation-only note that an
63
63
  * empty .reticle/flows yields zero specs.
@@ -67,5 +67,5 @@ export const SpecMessage = {
67
67
  STEP_DRIFT: 'a step anchor drifted or its expect did not hold',
68
68
  EMPTY_DIR: 'no flows under .reticle/flows — zero specs registered',
69
69
  };
70
- /** FLOW2SPEC: prefix of the Error a malformed/missing flow file raises when its spec runs. */
70
+ /** Prefix of the Error a malformed/missing flow file raises when its spec runs. */
71
71
  export const FLOW_LOAD_ERROR_PREFIX = 'flow could not be loaded';
@@ -1,5 +1,5 @@
1
1
  /**
2
- * FLOW2SPEC — the flow success-assertion oracle now lives in @reticlehq/server so the live MCP
2
+ * The flow success-assertion oracle now lives in @reticlehq/server so the live MCP
3
3
  * `reticle_flow_replay` tool and this spec runner share ONE implementation (no divergent oracle).
4
4
  * Re-exported here to keep the spec-runner's import surface stable.
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * FLOW2SPEC — the flow success-assertion oracle now lives in @reticlehq/server so the live MCP
2
+ * The flow success-assertion oracle now lives in @reticlehq/server so the live MCP
3
3
  * `reticle_flow_replay` tool and this spec runner share ONE implementation (no divergent oracle).
4
4
  * Re-exported here to keep the spec-runner's import surface stable.
5
5
  */
@@ -19,7 +19,7 @@ export interface RegisterFlowSpecsOptions extends FlowsAsSpecsOptions {
19
19
  register?: RegisterFn;
20
20
  }
21
21
  /**
22
- * FLOW2SPEC — register one vitest test per flow under `source`. The agent-readable map (.reticle/flows)
22
+ * Register one vitest test per flow under `source`. The agent-readable map (.reticle/flows)
23
23
  * becomes the executable suite: a passing flow registers a green `it`, a malformed file registers a
24
24
  * loudly-failing ERROR `it`, an empty dir registers nothing. `getSession` is the seam — the
25
25
  * `reticle drive` launched session in CI, a fake in unit tests. MUST be awaited at module top level so
package/dist/register.js CHANGED
@@ -1,4 +1,4 @@
1
- import { FLOW_LOAD_ERROR_PREFIX, SpecKind, SpecOutcome } from './constants.js';
1
+ import { FLOW_LOAD_ERROR_PREFIX, SpecKind, SpecOutcome } from './outcome/constants.js';
2
2
  import { flowsAsSpecs } from './flow-spec.js';
3
3
  /** A loaded flow file was missing/malformed/badly-named — its spec throws this when run. */
4
4
  export class FlowMalformedError extends Error {
@@ -55,7 +55,7 @@ function specToCase(spec, getSession) {
55
55
  };
56
56
  }
57
57
  /**
58
- * FLOW2SPEC — register one vitest test per flow under `source`. The agent-readable map (.reticle/flows)
58
+ * Register one vitest test per flow under `source`. The agent-readable map (.reticle/flows)
59
59
  * becomes the executable suite: a passing flow registers a green `it`, a malformed file registers a
60
60
  * loudly-failing ERROR `it`, an empty dir registers nothing. `getSession` is the seam — the
61
61
  * `reticle drive` launched session in CI, a fake in unit tests. MUST be awaited at module top level so
package/dist/runner.js CHANGED
@@ -1,5 +1,5 @@
1
- import { TestStatus } from './constants.js';
2
- import { isSkip } from './skip.js';
1
+ import { TestStatus } from './outcome/constants.js';
2
+ import { isSkip } from './outcome/skip.js';
3
3
  import { getRegistered } from './registry.js';
4
4
  import { summarize, printSummary } from './summary.js';
5
5
  /** Classify a thrown value: skip (sentinel) vs fail (everything else). */
package/dist/summary.js CHANGED
@@ -1,4 +1,4 @@
1
- import { STATUS_GLYPH, SUMMARY_FOOTER_PREFIX, TestStatus } from './constants.js';
1
+ import { STATUS_GLYPH, SUMMARY_FOOTER_PREFIX, TestStatus } from './outcome/constants.js';
2
2
  export function summarize(results) {
3
3
  let passed = 0;
4
4
  let failed = 0;
@@ -1,6 +1,6 @@
1
1
  import { type ToolInvoker } from '@reticlehq/server';
2
2
  import { ActionType, type ElementQuery, type ElementState } from '@reticlehq/core';
3
- import { type TestClock } from './clock.js';
3
+ import { type TestClock } from './context/clock.js';
4
4
  /** A declarative predicate (the reticle_assert/until DSL). Kept structural to avoid a server type dep. */
5
5
  export type Predicate = Record<string, unknown>;
6
6
  export interface TestContextOptions {
@@ -1,11 +1,11 @@
1
1
  import { ReticleTool } from '@reticlehq/server';
2
2
  import { ActionType } from '@reticlehq/core';
3
- import { resolveTestid } from './resolve.js';
4
- import { buildClock } from './clock.js';
5
- import { InputModeTracker, expectInputModeReal } from './input-mode.js';
6
- import { failFromVerdict, proved } from './matchers.js';
7
- import { expectAbsent, expectElement, expectNet, expectNoConsoleErrors, expectSignal, expectText, } from './matchers.js';
8
- import { DEFAULT_ASSERT_TIMEOUT_MS } from './constants.js';
3
+ import { resolveTestid } from './context/resolve.js';
4
+ import { buildClock } from './context/clock.js';
5
+ import { InputModeTracker, expectInputModeReal } from './context/input-mode.js';
6
+ import { failFromVerdict, proved } from './context/matchers.js';
7
+ import { expectAbsent, expectElement, expectNet, expectNoConsoleErrors, expectSignal, expectText, } from './context/matchers.js';
8
+ import { DEFAULT_ASSERT_TIMEOUT_MS } from './outcome/constants.js';
9
9
  function asVerdict(value) {
10
10
  const record = 'object' === typeof value && value !== null ? value : {};
11
11
  const verdict = record['verdict'];
package/dist/types.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { ToolInvoker } from '@reticlehq/server';
2
2
  import type { TestContext } from './test-context.js';
3
- import type { TestStatus } from './constants.js';
3
+ import type { TestStatus } from './outcome/constants.js';
4
4
  /**
5
5
  * The per-spec `t` handed to a spec body.
6
6
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reticlehq/test",
3
- "version": "2.14.0",
3
+ "version": "3.2.0",
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.14.0",
16
- "@reticlehq/server": "2.14.0"
15
+ "@reticlehq/core": "3.2.0",
16
+ "@reticlehq/server": "3.2.0"
17
17
  },
18
18
  "peerDependencies": {
19
19
  "vitest": "^3.2.6"
@@ -23,12 +23,12 @@
23
23
  "optional": true
24
24
  }
25
25
  },
26
- "license": "SEE LICENSE IN LICENSE",
26
+ "license": "FSL-1.1-ALv2",
27
27
  "author": "Reticle contributors",
28
28
  "repository": {
29
29
  "type": "git",
30
30
  "url": "git+https://github.com/reticlehq/reticle.git",
31
- "directory": "packages/test"
31
+ "directory": "spec-runner"
32
32
  },
33
33
  "homepage": "https://github.com/reticlehq/reticle#readme",
34
34
  "bugs": "https://github.com/reticlehq/reticle/issues",
@@ -49,7 +49,7 @@
49
49
  "node": ">=20.0.0"
50
50
  },
51
51
  "scripts": {
52
- "build": "tsc -b",
52
+ "build": "tsc -b && node ../scripts/alias-dist.mjs",
53
53
  "typecheck": "tsc -b",
54
54
  "lint": "eslint src",
55
55
  "test:unit": "vitest run src --passWithNoTests",
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes