@jitsusama/agentic-harness.core 0.1.0 → 0.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.
@@ -47,12 +47,26 @@ export function renderVitals(vitals, measures) {
47
47
  // person to interact: nothing here observes event timing, so a
48
48
  // reader told only that four were measured has no way to know
49
49
  // responsiveness was never among them, and assumes it passed.
50
+ const sampled = Math.max(...measures.map((one) => one.spread?.samples ?? 1));
51
+ // A rating that changed between loads is the finding, not the
52
+ // median beside it: the median alone reads as settled.
53
+ const unstable = measures.filter((one) => one.spread?.straddles);
50
54
  const caveat = ` Interaction to next paint is not among them: it needs an ` +
51
55
  `interaction, and this measures a load.` +
56
+ (sampled <= 1 ? "" : ` Each value is the median of ${sampled} loads.`) +
57
+ (unstable.length === 0
58
+ ? ""
59
+ : ` Rated differently between loads: ${unstable
60
+ .map((one) => one.name)
61
+ .join(", ")}.`) +
52
62
  (missing.length === 0 ? "" : ` Not observed: ${missing.join("; ")}.`);
53
63
  const width = Math.max(...measures.map((one) => one.name.length));
54
64
  const lines = measures.map((one) => ` ${one.name.padEnd(width)} ${MARK[one.rating].padEnd(4)} ` +
55
65
  `${say(one.value, one.unit).padStart(9)}` +
66
+ `${one.spread && one.spread.samples > 1
67
+ ? ` ${say(one.spread.low, one.unit)}-${say(one.spread.high, one.unit)}` +
68
+ ` over ${one.spread.samples}`
69
+ : ""}` +
56
70
  `${one.detail ? ` ${one.detail}` : ""}`);
57
71
  const blame = worstShiftSources(vitals.shifts);
58
72
  if (blame.length > 0) {
@@ -71,7 +85,11 @@ export function renderVitals(vitals, measures) {
71
85
  // A partial capture cannot pass: an observer that never
72
86
  // installed reports nothing, which reads the same as a page
73
87
  // with nothing wrong.
74
- standing: missing.length > 0 && overall(measures) === "pass"
88
+ // A pass that only holds on the median is not a pass: a
89
+ // metric that rated poor on any load is worth a look even
90
+ // when the middle run was fine.
91
+ standing: (missing.length > 0 || unstable.length > 0) &&
92
+ overall(measures) === "pass"
75
93
  ? "warn"
76
94
  : overall(measures),
77
95
  headline: failing.length === 0
@@ -128,6 +128,15 @@ export declare function worstShiftSources(shifts: readonly Shift[], limit?: numb
128
128
  readonly node: string;
129
129
  readonly moved: number;
130
130
  }[];
131
+ /** How a metric varied across repeated loads. */
132
+ export interface Spread {
133
+ readonly low: number;
134
+ readonly high: number;
135
+ /** How many loads actually reported this metric. */
136
+ readonly samples: number;
137
+ /** Whether the rating differed between loads. */
138
+ readonly straddles: boolean;
139
+ }
131
140
  /** One metric, rated. */
132
141
  export interface Measure {
133
142
  readonly name: string;
@@ -136,6 +145,26 @@ export interface Measure {
136
145
  readonly rating: Rating;
137
146
  /** What the value points at, when the browser said. */
138
147
  readonly detail?: string;
148
+ /** Present when the value is a median over several loads. */
149
+ readonly spread?: Spread;
139
150
  }
140
151
  /** Read the vitals into rated measures. */
141
152
  export declare function measure(vitals: Vitals): readonly Measure[];
153
+ /**
154
+ * Read several captures of the same page into rated measures,
155
+ * one per metric, each the median over the loads that reported
156
+ * it.
157
+ *
158
+ * A single headless load drifts: the same page can rate good on
159
+ * one run and poor on the next without anything changing. The
160
+ * median is the defensible middle, and the spread is reported
161
+ * beside it because a rating that straddles the runs is the
162
+ * finding, not the number.
163
+ *
164
+ * The rating is taken from the sample nearest the median rather
165
+ * than re-derived, so a metric keeps exactly the thresholds
166
+ * `measure` gave it. For an even count the worse of the two
167
+ * middle samples decides, which errs toward the reading a
168
+ * person would want to hear about.
169
+ */
170
+ export declare function measureSamples(samples: readonly Vitals[]): readonly Measure[];
@@ -173,3 +173,73 @@ export function measure(vitals) {
173
173
  }
174
174
  return measures;
175
175
  }
176
+ /**
177
+ * Read several captures of the same page into rated measures,
178
+ * one per metric, each the median over the loads that reported
179
+ * it.
180
+ *
181
+ * A single headless load drifts: the same page can rate good on
182
+ * one run and poor on the next without anything changing. The
183
+ * median is the defensible middle, and the spread is reported
184
+ * beside it because a rating that straddles the runs is the
185
+ * finding, not the number.
186
+ *
187
+ * The rating is taken from the sample nearest the median rather
188
+ * than re-derived, so a metric keeps exactly the thresholds
189
+ * `measure` gave it. For an even count the worse of the two
190
+ * middle samples decides, which errs toward the reading a
191
+ * person would want to hear about.
192
+ */
193
+ export function measureSamples(samples) {
194
+ const first = samples[0];
195
+ if (first === undefined)
196
+ return [];
197
+ if (samples.length === 1)
198
+ return measure(first);
199
+ const order = [];
200
+ const byName = new Map();
201
+ for (const capture of samples) {
202
+ for (const one of measure(capture)) {
203
+ const group = byName.get(one.name);
204
+ if (group === undefined) {
205
+ byName.set(one.name, [one]);
206
+ order.push(one.name);
207
+ }
208
+ else {
209
+ group.push(one);
210
+ }
211
+ }
212
+ }
213
+ return order.map((name) => {
214
+ // Set above for every name in order; the map cannot miss.
215
+ const group = byName.get(name);
216
+ const sorted = [...group].sort((a, b) => a.value - b.value);
217
+ const mid = Math.floor(sorted.length / 2);
218
+ const upper = sorted[mid];
219
+ const lower = sorted[Math.max(0, mid - 1)];
220
+ const odd = sorted.length % 2 === 1;
221
+ const median = odd ? upper.value : (lower.value + upper.value) / 2;
222
+ const worseMiddle = SEVERITY_ORDER.indexOf(lower.rating) >=
223
+ SEVERITY_ORDER.indexOf(upper.rating)
224
+ ? lower
225
+ : upper;
226
+ const nearest = odd ? upper : worseMiddle;
227
+ const low = sorted[0].value;
228
+ const high = sorted[sorted.length - 1].value;
229
+ return {
230
+ name,
231
+ value: median,
232
+ unit: nearest.unit,
233
+ rating: nearest.rating,
234
+ ...(nearest.detail === undefined ? {} : { detail: nearest.detail }),
235
+ spread: {
236
+ low,
237
+ high,
238
+ samples: group.length,
239
+ straddles: new Set(group.map((one) => one.rating)).size > 1,
240
+ },
241
+ };
242
+ });
243
+ }
244
+ /** Mildest to worst, for choosing the reading to stand on. */
245
+ const SEVERITY_ORDER = ["good", "needs-improvement", "poor"];
@@ -18,9 +18,10 @@ import { type Animation, type BoxModel, type DelegatedListeners, type HoverRepor
18
18
  import { type Divergence, type EmulationState, type NetworkRule, type ObservedEnvironment, type SavedState, type SessionStatus, type StorageSnapshot, type TabRecord, type ThrottleConditions } from "./environment/index.js";
19
19
  import { type ChordRefusal, type Point, type PointerEventStep, type TouchStep } from "./input/index.js";
20
20
  import { type Settled, type WaitCondition, type WaitOutcome } from "./wait/index.js";
21
- import { type A11yFinding, type BehindReport, type CapturedTarget, type ConformanceBar, type ContrastLevel, type PageBox, type PairReport, type StructureNode, type VisualNode } from "./audit/index.js";
22
- import { type StyleSample } from "./design/index.js";
21
+ import { type A11yFinding, type BehindReport, type CapturedTarget, type ConformanceBar, type ContrastLevel, type MotionCapture, type PageBox, type PairReport, type StructureNode, type VisualNode } from "./audit/index.js";
22
+ import { type StyleSample, type TextBlock } from "./design/index.js";
23
23
  import { type EvalFrame, type EvalOutcome } from "./evaluate/index.js";
24
+ import { type HydrationCapture } from "./hydration/index.js";
24
25
  import { type HeapComparison, type Hotspots, type LayerReport, type TraceCapture, type TraceProfile, type Vitals } from "./perf/index.js";
25
26
  import { type IndexedNode } from "./snapshot/index.js";
26
27
  import { type PropertyTrace, type StyleGroup } from "./styles/index.js";
@@ -810,6 +811,18 @@ export declare class BrowserSession {
810
811
  * a click or a navigation without disturbing what it reports.
811
812
  */
812
813
  focusHolder(): Promise<FocusHolder | undefined>;
814
+ /**
815
+ * What the page keeps doing when asked to hold still.
816
+ *
817
+ * Emulates prefers-reduced-motion: reduce, reloads so the page
818
+ * decides its motion under the preference rather than being
819
+ * caught mid-flight, reads what is still moving, then puts the
820
+ * emulation back exactly as it was. The reload matters: a page
821
+ * picks most of its motion at load, so flipping the preference
822
+ * on a settled page measures its reaction to a change, not its
823
+ * behaviour for a visitor who arrived with the preference set.
824
+ */
825
+ motionUnderReduce(): Promise<MotionCapture>;
813
826
  structure(): Promise<readonly StructureNode[]>;
814
827
  /**
815
828
  * What the layout actually did, as the browser measured it.
@@ -828,6 +841,22 @@ export declare class BrowserSession {
828
841
  * criterion turns on.
829
842
  */
830
843
  targets(): Promise<readonly CapturedTarget[]>;
844
+ /**
845
+ * Both renders of the current page: what the server sends and
846
+ * what hydration made of it.
847
+ *
848
+ * The server render is fetched from inside the page, so it
849
+ * travels with the session's cookies, and parsed without
850
+ * running a script. Judging the capture is the hydration
851
+ * subdomain's job; pair it with logs() so the framework's own
852
+ * complaints are read beside the comparison.
853
+ */
854
+ hydration(): Promise<HydrationCapture>;
855
+ /**
856
+ * How the page's text blocks wrap, measured from real line
857
+ * boxes rather than estimated from fonts.
858
+ */
859
+ typography(): Promise<readonly TextBlock[]>;
831
860
  layout(): Promise<{
832
861
  readonly nodes: readonly VisualNode[];
833
862
  readonly viewport: PageBox;
@@ -82,9 +82,10 @@ const WAIT_POLL_MS = 100;
82
82
  const KNOWN_KEYS = new Set(Object.keys(_keyDefinitions));
83
83
  import { readFile } from "node:fs/promises";
84
84
  import { createRequire } from "node:module";
85
- import { buildStructure, enabledRules, foldBehind, foldPair, parseRgb, readAxeRun, TARGET_CAPTURE, visualCaptureSource, } from "./audit/index.js";
86
- import { inventorySource } from "./design/index.js";
85
+ import { buildStructure, enabledRules, foldBehind, foldPair, MOTION_CAPTURE, parseRgb, readAxeRun, TARGET_CAPTURE, visualCaptureSource, } from "./audit/index.js";
86
+ import { inventorySource, TYPOGRAPHY_CAPTURE, } from "./design/index.js";
87
87
  import { describeThrow, evaluationSource, } from "./evaluate/index.js";
88
+ import { HYDRATION_CAPTURE } from "./hydration/index.js";
88
89
  import { categoriesFor, compareHeap, foldLayers, foldProfile, foldTrace, LAYER_SETTLE_MS, nameNode, observerBootstrap, readVitalsSource, } from "./perf/index.js";
89
90
  import { captureTiles } from "./screenshot.js";
90
91
  import { ArtifactLedger } from "./session/artifacts.js";
@@ -1874,6 +1875,39 @@ export class BrowserSession {
1874
1875
  });
1875
1876
  return result.value;
1876
1877
  }
1878
+ /**
1879
+ * What the page keeps doing when asked to hold still.
1880
+ *
1881
+ * Emulates prefers-reduced-motion: reduce, reloads so the page
1882
+ * decides its motion under the preference rather than being
1883
+ * caught mid-flight, reads what is still moving, then puts the
1884
+ * emulation back exactly as it was. The reload matters: a page
1885
+ * picks most of its motion at load, so flipping the preference
1886
+ * on a settled page measures its reaction to a change, not its
1887
+ * behaviour for a visitor who arrived with the preference set.
1888
+ */
1889
+ async motionUnderReduce() {
1890
+ await this.ready();
1891
+ const before = this.emulation.asked;
1892
+ try {
1893
+ await this.emulation.change({ reducedMotion: true });
1894
+ await this.reload();
1895
+ const response = await this.cdp.send("Runtime.evaluate", {
1896
+ expression: MOTION_CAPTURE,
1897
+ returnByValue: true,
1898
+ });
1899
+ if (response.exceptionDetails) {
1900
+ const threw = describeThrow(response.exceptionDetails);
1901
+ throw new Error(`Could not read the motion: ${threw.message}`);
1902
+ }
1903
+ return response.result.value;
1904
+ }
1905
+ finally {
1906
+ // Wholesale, not merged: a merge cannot clear the reduce
1907
+ // this added when the session had no opinion before.
1908
+ await this.emulation.restore(before);
1909
+ }
1910
+ }
1877
1911
  async structure() {
1878
1912
  // Every sibling read waits out a crash recovery first, and
1879
1913
  // this one did not. Promise.all evaluates this.cdp.send when
@@ -1937,6 +1971,45 @@ export class BrowserSession {
1937
1971
  }
1938
1972
  return response.result.value;
1939
1973
  }
1974
+ /**
1975
+ * Both renders of the current page: what the server sends and
1976
+ * what hydration made of it.
1977
+ *
1978
+ * The server render is fetched from inside the page, so it
1979
+ * travels with the session's cookies, and parsed without
1980
+ * running a script. Judging the capture is the hydration
1981
+ * subdomain's job; pair it with logs() so the framework's own
1982
+ * complaints are read beside the comparison.
1983
+ */
1984
+ async hydration() {
1985
+ await this.ready();
1986
+ const response = await this.cdp.send("Runtime.evaluate", {
1987
+ expression: HYDRATION_CAPTURE,
1988
+ awaitPromise: true,
1989
+ returnByValue: true,
1990
+ });
1991
+ if (response.exceptionDetails) {
1992
+ const threw = describeThrow(response.exceptionDetails);
1993
+ throw new Error(`Could not read the renders: ${threw.message}`);
1994
+ }
1995
+ return response.result.value;
1996
+ }
1997
+ /**
1998
+ * How the page's text blocks wrap, measured from real line
1999
+ * boxes rather than estimated from fonts.
2000
+ */
2001
+ async typography() {
2002
+ await this.ready();
2003
+ const response = await this.cdp.send("Runtime.evaluate", {
2004
+ expression: TYPOGRAPHY_CAPTURE,
2005
+ returnByValue: true,
2006
+ });
2007
+ if (response.exceptionDetails) {
2008
+ const threw = describeThrow(response.exceptionDetails);
2009
+ throw new Error(`Could not measure the text: ${threw.message}`);
2010
+ }
2011
+ return response.result.value;
2012
+ }
1940
2013
  async layout() {
1941
2014
  await this.ready();
1942
2015
  const response = await this.cdp.send("Runtime.evaluate", {
package/package.json CHANGED
@@ -1,145 +1,145 @@
1
1
  {
2
- "name": "@jitsusama/agentic-harness.core",
3
- "version": "0.1.0",
4
- "description": "Pi-agnostic business logic for agentic-harness: state machines, guardian decisions, quest/TDD domain model.",
5
- "license": "MIT",
6
- "type": "module",
7
- "overrides": {
8
- "google-auth-library": "$google-auth-library"
9
- },
10
- "exports": {
11
- "./tdd": "./dist/tdd/index.js",
12
- "./tdd/presentation": "./dist/tdd/presentation.js",
13
- "./shell": "./dist/shell/index.js",
14
- "./command": "./dist/command/index.js",
15
- "./git-cli": "./dist/git-cli/index.js",
16
- "./github-cli": "./dist/github-cli/index.js",
17
- "./attribution": "./dist/attribution/index.js",
18
- "./verify": "./dist/verify/index.js",
19
- "./memory": "./dist/memory/index.js",
20
- "./governance": "./dist/governance/index.js",
21
- "./observability": "./dist/observability/index.js",
22
- "./completion": "./dist/completion/index.js",
23
- "./advisor": "./dist/advisor/index.js",
24
- "./quest": "./dist/quest/index.js",
25
- "./quest/lifecycle": "./dist/quest/lifecycle.js",
26
- "./quest/lookup": "./dist/quest/lookup.js",
27
- "./quest/state": "./dist/quest/state.js",
28
- "./quest/machine": "./dist/quest/machine.js",
29
- "./quest/actions": "./dist/quest/actions.js",
30
- "./quest/config": "./dist/quest/config.js",
31
- "./quest/render-rows": "./dist/quest/render-rows.js",
32
- "./quest/verbs/shared": "./dist/quest/verbs/shared.js",
33
- "./quest/verbs/alias": "./dist/quest/verbs/alias.js",
34
- "./quest/verbs/reorder": "./dist/quest/verbs/reorder.js",
35
- "./quest/verbs/structural": "./dist/quest/verbs/structural.js",
36
- "./quest/verbs/stage": "./dist/quest/verbs/stage.js",
37
- "./quest/verbs/queries": "./dist/quest/verbs/queries.js",
38
- "./quest/verbs/lifecycle": "./dist/quest/verbs/lifecycle.js",
39
- "./quest/verbs/tree-ops": "./dist/quest/verbs/tree-ops.js",
40
- "./tree": "./dist/tree/index.js",
41
- "./lsp": "./dist/lsp/index.js",
42
- "./result": "./dist/result/index.js",
43
- "./refs": "./dist/refs/index.js",
44
- "./prose": "./dist/prose/index.js",
45
- "./gate": "./dist/gate/index.js",
46
- "./sections": "./dist/sections/index.js",
47
- "./title": "./dist/title/index.js",
48
- "./guardian": "./dist/guardian/index.js",
49
- "./guardian/prose-gate": "./dist/internal/guardian/prose-gate.js",
50
- "./guardian/section-gate": "./dist/internal/guardian/section-gate.js",
51
- "./guardian/title-gate": "./dist/internal/guardian/title-gate.js",
52
- "./guardian/redirect-gate": "./dist/internal/guardian/redirect-gate.js",
53
- "./guardian/history-gate": "./dist/internal/guardian/history-gate.js",
54
- "./guardian/commit-shell": "./dist/internal/guardian/commit-shell.js",
55
- "./guardian/commit-format": "./dist/internal/guardian/commit-format.js",
56
- "./guardian/commit-file": "./dist/internal/guardian/commit-file.js",
57
- "./github/cli": "./dist/internal/github/cli.js",
58
- "./clock": "./dist/clock/index.js",
59
- "./exec": "./dist/exec/index.js",
60
- "./remote": "./dist/remote/index.js",
61
- "./process": "./dist/process/index.js",
62
- "./work": "./dist/work/index.js",
63
- "./review": "./dist/review/index.js",
64
- "./web": "./dist/web/index.js",
65
- "./web/a11y": "./dist/web/a11y/index.js",
66
- "./web/audit": "./dist/web/audit/index.js",
67
- "./web/audit/verdict": "./dist/web/audit/verdict.js",
68
- "./web/browser": "./dist/web/browser.js",
69
- "./web/compare": "./dist/web/compare/index.js",
70
- "./web/cookies": "./dist/web/cookies/index.js",
71
- "./web/design": "./dist/web/design/index.js",
72
- "./web/element": "./dist/web/element/index.js",
73
- "./web/environment": "./dist/web/environment/index.js",
74
- "./web/environment/devices": "./dist/web/environment/devices.js",
75
- "./web/evaluate": "./dist/web/evaluate/index.js",
76
- "./web/input": "./dist/web/input/index.js",
77
- "./web/mermaid": "./dist/web/mermaid.js",
78
- "./web/perf": "./dist/web/perf/index.js",
79
- "./web/reader": "./dist/web/reader.js",
80
- "./web/search": "./dist/web/search.js",
81
- "./web/session": "./dist/web/session.js",
82
- "./web/snapshot": "./dist/web/snapshot/index.js",
83
- "./web/target": "./dist/web/target/index.js",
84
- "./web/telemetry": "./dist/web/telemetry/index.js",
85
- "./web/wait": "./dist/web/wait/index.js",
86
- "./slack": "./dist/slack/index.js",
87
- "./slack/auth/browser": "./dist/slack/auth/browser.js",
88
- "./slack/auth/browser-extract": "./dist/slack/auth/browser-extract.js",
89
- "./slack/auth/extract": "./dist/slack/auth/extract.js",
90
- "./slack/auth/oauth": "./dist/slack/auth/oauth.js",
91
- "./slack/auth/server": "./dist/slack/auth/server.js",
92
- "./slack/types": "./dist/slack/types.js",
93
- "./google": "./dist/google/index.js",
94
- "./google/auth/browser": "./dist/google/auth/browser.js",
95
- "./google/auth/oauth": "./dist/google/auth/oauth.js",
96
- "./google/auth/server": "./dist/google/auth/server.js",
97
- "./google/auth/setup-instructions": "./dist/google/auth/setup-instructions.js",
98
- "./google/types": "./dist/google/types.js"
99
- },
100
- "bin": {
101
- "agentic-harness-core": "./dist/bin/cli.js"
102
- },
103
- "files": [
104
- "dist"
105
- ],
106
- "scripts": {
107
- "build": "tsc -p tsconfig.build.json",
108
- "prepare": "npm run build",
109
- "lint": "biome check .",
110
- "lint:fix": "biome check --write .",
111
- "typecheck": "tsc --noEmit",
112
- "pretest": "npm run build",
113
- "test": "vitest run",
114
- "test:watch": "vitest",
115
- "test:browser": "vitest run --config vitest.browser.config.ts"
116
- },
117
- "engines": {
118
- "node": ">=22.19.0"
119
- },
120
- "dependencies": {
121
- "axe-core": "^4.12.1",
122
- "defuddle": "^0.19.1",
123
- "google-auth-library": "^10.9.0",
124
- "googleapis": "^173.0.0",
125
- "jsdom": "^29.1.1",
126
- "jsonpath-plus": "^10.4.0",
127
- "pixelmatch": "^7.2.0",
128
- "pngjs": "^7.0.0",
129
- "puppeteer-core": "^25.3.0",
130
- "sqlite3": "^6.0.1",
131
- "vscode-jsonrpc": "^9.0.1",
132
- "vscode-languageserver-protocol": "^3.18.2",
133
- "yaml": "^2.9.0"
134
- },
135
- "devDependencies": {
136
- "@biomejs/biome": "^2.5.9",
137
- "@types/jsdom": "^28.0.3",
138
- "@types/node": "^26.1.1",
139
- "@types/pngjs": "^6.0.5",
140
- "@types/ws": "^8.18.1",
141
- "typescript": "^7.0.2",
142
- "vitest": "^4.1.11",
143
- "ws": "^8.21.1"
144
- }
145
- }
2
+ "name": "@jitsusama/agentic-harness.core",
3
+ "version": "0.2.0",
4
+ "description": "Pi-agnostic business logic for agentic-harness: state machines, guardian decisions, quest/TDD domain model.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "overrides": {
8
+ "google-auth-library": "$google-auth-library"
9
+ },
10
+ "exports": {
11
+ "./tdd": "./dist/tdd/index.js",
12
+ "./tdd/presentation": "./dist/tdd/presentation.js",
13
+ "./shell": "./dist/shell/index.js",
14
+ "./command": "./dist/command/index.js",
15
+ "./git-cli": "./dist/git-cli/index.js",
16
+ "./github-cli": "./dist/github-cli/index.js",
17
+ "./attribution": "./dist/attribution/index.js",
18
+ "./verify": "./dist/verify/index.js",
19
+ "./memory": "./dist/memory/index.js",
20
+ "./governance": "./dist/governance/index.js",
21
+ "./observability": "./dist/observability/index.js",
22
+ "./completion": "./dist/completion/index.js",
23
+ "./advisor": "./dist/advisor/index.js",
24
+ "./quest": "./dist/quest/index.js",
25
+ "./quest/lifecycle": "./dist/quest/lifecycle.js",
26
+ "./quest/lookup": "./dist/quest/lookup.js",
27
+ "./quest/state": "./dist/quest/state.js",
28
+ "./quest/machine": "./dist/quest/machine.js",
29
+ "./quest/actions": "./dist/quest/actions.js",
30
+ "./quest/config": "./dist/quest/config.js",
31
+ "./quest/render-rows": "./dist/quest/render-rows.js",
32
+ "./quest/verbs/shared": "./dist/quest/verbs/shared.js",
33
+ "./quest/verbs/alias": "./dist/quest/verbs/alias.js",
34
+ "./quest/verbs/reorder": "./dist/quest/verbs/reorder.js",
35
+ "./quest/verbs/structural": "./dist/quest/verbs/structural.js",
36
+ "./quest/verbs/stage": "./dist/quest/verbs/stage.js",
37
+ "./quest/verbs/queries": "./dist/quest/verbs/queries.js",
38
+ "./quest/verbs/lifecycle": "./dist/quest/verbs/lifecycle.js",
39
+ "./quest/verbs/tree-ops": "./dist/quest/verbs/tree-ops.js",
40
+ "./tree": "./dist/tree/index.js",
41
+ "./lsp": "./dist/lsp/index.js",
42
+ "./result": "./dist/result/index.js",
43
+ "./refs": "./dist/refs/index.js",
44
+ "./prose": "./dist/prose/index.js",
45
+ "./gate": "./dist/gate/index.js",
46
+ "./sections": "./dist/sections/index.js",
47
+ "./title": "./dist/title/index.js",
48
+ "./guardian": "./dist/guardian/index.js",
49
+ "./guardian/prose-gate": "./dist/internal/guardian/prose-gate.js",
50
+ "./guardian/section-gate": "./dist/internal/guardian/section-gate.js",
51
+ "./guardian/title-gate": "./dist/internal/guardian/title-gate.js",
52
+ "./guardian/redirect-gate": "./dist/internal/guardian/redirect-gate.js",
53
+ "./guardian/history-gate": "./dist/internal/guardian/history-gate.js",
54
+ "./guardian/commit-shell": "./dist/internal/guardian/commit-shell.js",
55
+ "./guardian/commit-format": "./dist/internal/guardian/commit-format.js",
56
+ "./guardian/commit-file": "./dist/internal/guardian/commit-file.js",
57
+ "./github/cli": "./dist/internal/github/cli.js",
58
+ "./clock": "./dist/clock/index.js",
59
+ "./exec": "./dist/exec/index.js",
60
+ "./remote": "./dist/remote/index.js",
61
+ "./process": "./dist/process/index.js",
62
+ "./work": "./dist/work/index.js",
63
+ "./review": "./dist/review/index.js",
64
+ "./web": "./dist/web/index.js",
65
+ "./web/a11y": "./dist/web/a11y/index.js",
66
+ "./web/audit": "./dist/web/audit/index.js",
67
+ "./web/audit/verdict": "./dist/web/audit/verdict.js",
68
+ "./web/browser": "./dist/web/browser.js",
69
+ "./web/compare": "./dist/web/compare/index.js",
70
+ "./web/cookies": "./dist/web/cookies/index.js",
71
+ "./web/design": "./dist/web/design/index.js",
72
+ "./web/element": "./dist/web/element/index.js",
73
+ "./web/environment": "./dist/web/environment/index.js",
74
+ "./web/environment/devices": "./dist/web/environment/devices.js",
75
+ "./web/evaluate": "./dist/web/evaluate/index.js",
76
+ "./web/hydration": "./dist/web/hydration/index.js",
77
+ "./web/input": "./dist/web/input/index.js",
78
+ "./web/mermaid": "./dist/web/mermaid.js",
79
+ "./web/perf": "./dist/web/perf/index.js",
80
+ "./web/reader": "./dist/web/reader.js",
81
+ "./web/search": "./dist/web/search.js",
82
+ "./web/session": "./dist/web/session.js",
83
+ "./web/snapshot": "./dist/web/snapshot/index.js",
84
+ "./web/target": "./dist/web/target/index.js",
85
+ "./web/telemetry": "./dist/web/telemetry/index.js",
86
+ "./web/wait": "./dist/web/wait/index.js",
87
+ "./slack": "./dist/slack/index.js",
88
+ "./slack/auth/browser": "./dist/slack/auth/browser.js",
89
+ "./slack/auth/browser-extract": "./dist/slack/auth/browser-extract.js",
90
+ "./slack/auth/extract": "./dist/slack/auth/extract.js",
91
+ "./slack/auth/oauth": "./dist/slack/auth/oauth.js",
92
+ "./slack/auth/server": "./dist/slack/auth/server.js",
93
+ "./slack/types": "./dist/slack/types.js",
94
+ "./google": "./dist/google/index.js",
95
+ "./google/auth/browser": "./dist/google/auth/browser.js",
96
+ "./google/auth/oauth": "./dist/google/auth/oauth.js",
97
+ "./google/auth/server": "./dist/google/auth/server.js",
98
+ "./google/auth/setup-instructions": "./dist/google/auth/setup-instructions.js",
99
+ "./google/types": "./dist/google/types.js"
100
+ },
101
+ "bin": {
102
+ "agentic-harness-core": "./dist/bin/cli.js"
103
+ },
104
+ "files": [
105
+ "dist"
106
+ ],
107
+ "engines": {
108
+ "node": ">=22.19.0"
109
+ },
110
+ "dependencies": {
111
+ "axe-core": "^4.12.1",
112
+ "defuddle": "^0.19.1",
113
+ "google-auth-library": "^10.9.0",
114
+ "googleapis": "^173.0.0",
115
+ "jsdom": "^29.1.1",
116
+ "jsonpath-plus": "^10.4.0",
117
+ "pixelmatch": "^7.2.0",
118
+ "pngjs": "^7.0.0",
119
+ "puppeteer-core": "^25.3.0",
120
+ "sqlite3": "^6.0.1",
121
+ "vscode-jsonrpc": "^9.0.1",
122
+ "vscode-languageserver-protocol": "^3.18.2",
123
+ "yaml": "^2.9.0"
124
+ },
125
+ "devDependencies": {
126
+ "@biomejs/biome": "^2.5.9",
127
+ "@types/jsdom": "^28.0.3",
128
+ "@types/node": "^26.1.1",
129
+ "@types/pngjs": "^6.0.5",
130
+ "@types/ws": "^8.18.1",
131
+ "typescript": "^7.0.2",
132
+ "vitest": "^4.1.11",
133
+ "ws": "^8.21.1"
134
+ },
135
+ "scripts": {
136
+ "build": "tsc -p tsconfig.build.json",
137
+ "lint": "biome check .",
138
+ "lint:fix": "biome check --write .",
139
+ "typecheck": "tsc --noEmit",
140
+ "pretest": "tsc -p tsconfig.build.json",
141
+ "test": "vitest run",
142
+ "test:watch": "vitest",
143
+ "test:browser": "vitest run --config vitest.browser.config.ts"
144
+ }
145
+ }
@@ -1,15 +0,0 @@
1
- /**
2
- * Thin promise wrapper over the callback-based sqlite3 driver.
3
- * sqlite3 is a native module, so it is lazy-imported on first
4
- * open; callers speak promises and never touch the driver
5
- * directly.
6
- */
7
- /** A promise-speaking handle to a SQLite database. */
8
- export interface Db {
9
- run(sql: string, params?: readonly unknown[]): Promise<void>;
10
- all<T>(sql: string, params?: readonly unknown[]): Promise<T[]>;
11
- exec(sql: string): Promise<void>;
12
- close(): Promise<void>;
13
- }
14
- /** Open a SQLite database at the given path (`:memory:` for tests). */
15
- export declare function openDb(dbPath: string): Promise<Db>;