harnery 0.17.0 → 0.19.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.
Files changed (61) hide show
  1. package/README.md +1 -1
  2. package/dist/commands/browse.d.ts.map +1 -1
  3. package/dist/commands/browse.js +187 -4
  4. package/dist/commands/supervisor.d.ts.map +1 -1
  5. package/dist/commands/supervisor.js +76 -4
  6. package/dist/core/supervisor/index.d.ts +3 -3
  7. package/dist/core/supervisor/index.d.ts.map +1 -1
  8. package/dist/core/supervisor/index.js +2 -2
  9. package/dist/core/supervisor/plan-read.d.ts +2 -1
  10. package/dist/core/supervisor/plan-read.d.ts.map +1 -1
  11. package/dist/core/supervisor/plan-read.js +222 -3
  12. package/dist/core/supervisor/plan-types.d.ts +60 -3
  13. package/dist/core/supervisor/plan-types.d.ts.map +1 -1
  14. package/dist/core/supervisor/plan-types.js +2 -0
  15. package/dist/core/supervisor/planning.d.ts.map +1 -1
  16. package/dist/core/supervisor/planning.js +804 -56
  17. package/dist/core/supervisor/read.d.ts +3 -3
  18. package/dist/core/supervisor/read.d.ts.map +1 -1
  19. package/dist/core/supervisor/read.js +2 -2
  20. package/dist/core/supervisor/runner.d.ts.map +1 -1
  21. package/dist/core/supervisor/runner.js +7 -2
  22. package/dist/core/supervisor/service.js +3 -0
  23. package/dist/core/supervisor/state.d.ts +17 -2
  24. package/dist/core/supervisor/state.d.ts.map +1 -1
  25. package/dist/core/supervisor/state.js +211 -33
  26. package/dist/core/workflow/engine.d.ts.map +1 -1
  27. package/dist/core/workflow/engine.js +24 -6
  28. package/dist/core/workflow/types.d.ts +6 -0
  29. package/dist/core/workflow/types.d.ts.map +1 -1
  30. package/dist/core/workflow/validate.d.ts +3 -2
  31. package/dist/core/workflow/validate.d.ts.map +1 -1
  32. package/dist/core/workflow/validate.js +31 -3
  33. package/dist/lib/browser/client.d.ts +18 -0
  34. package/dist/lib/browser/client.d.ts.map +1 -1
  35. package/dist/lib/browser/client.js +39 -0
  36. package/dist/lib/browser/geometry.d.ts +146 -0
  37. package/dist/lib/browser/geometry.d.ts.map +1 -0
  38. package/dist/lib/browser/geometry.js +525 -0
  39. package/dist/lib/browser/index.d.ts +2 -0
  40. package/dist/lib/browser/index.d.ts.map +1 -1
  41. package/dist/lib/browser/target-size.d.ts +65 -0
  42. package/dist/lib/browser/target-size.d.ts.map +1 -0
  43. package/dist/lib/browser/target-size.js +108 -0
  44. package/package.json +7 -1
  45. package/src/commands/browse.ts +319 -0
  46. package/src/commands/supervisor.ts +92 -5
  47. package/src/core/supervisor/index.ts +17 -1
  48. package/src/core/supervisor/plan-read.ts +292 -2
  49. package/src/core/supervisor/plan-types.ts +69 -1
  50. package/src/core/supervisor/planning.ts +1012 -51
  51. package/src/core/supervisor/read.ts +16 -1
  52. package/src/core/supervisor/runner.ts +9 -2
  53. package/src/core/supervisor/service.ts +3 -0
  54. package/src/core/supervisor/state.ts +272 -31
  55. package/src/core/workflow/engine.ts +29 -6
  56. package/src/core/workflow/types.ts +6 -0
  57. package/src/core/workflow/validate.ts +34 -3
  58. package/src/lib/browser/client.ts +62 -0
  59. package/src/lib/browser/geometry.ts +695 -0
  60. package/src/lib/browser/index.ts +25 -0
  61. package/src/lib/browser/target-size.ts +180 -0
@@ -2,8 +2,9 @@
2
2
  * Minimal validator for the StageSchema JSON-schema subset. Deliberately tiny:
3
3
  * a full JSON Schema implementation would pull a dependency (ajv) for
4
4
  * validation depth workflow gates don't need. Supported: type, properties,
5
- * required, items, enum. Returns a list of human-readable problems (empty =
6
- * valid) so the engine can feed failures back into the retry prompt verbatim.
5
+ * required, items, minItems/maxItems, minLength/maxLength, pattern, and enum.
6
+ * Returns a list of human-readable problems (empty = valid) so the engine can
7
+ * feed failures back into the retry prompt verbatim.
7
8
  */
8
9
 
9
10
  import type { StageSchema } from "./types.ts";
@@ -34,6 +35,12 @@ export function validateAgainstSchema(value: unknown, schema: StageSchema, path
34
35
  }
35
36
  case "array": {
36
37
  if (!Array.isArray(value)) return [`${path}: expected array, got ${short(value)}`];
38
+ if (schema.minItems !== undefined && value.length < schema.minItems) {
39
+ problems.push(`${path}: expected at least ${schema.minItems} item(s), got ${value.length}`);
40
+ }
41
+ if (schema.maxItems !== undefined && value.length > schema.maxItems) {
42
+ problems.push(`${path}: expected at most ${schema.maxItems} item(s), got ${value.length}`);
43
+ }
37
44
  if (schema.items) {
38
45
  for (const [i, item] of value.entries()) {
39
46
  problems.push(
@@ -43,7 +50,31 @@ export function validateAgainstSchema(value: unknown, schema: StageSchema, path
43
50
  }
44
51
  return problems;
45
52
  }
46
- case "string":
53
+ case "string": {
54
+ if (typeof value !== "string") {
55
+ return [`${path}: expected string, got ${short(value)}`];
56
+ }
57
+ if (schema.minLength !== undefined && value.length < schema.minLength) {
58
+ problems.push(
59
+ `${path}: expected at least ${schema.minLength} character(s), got ${value.length}`,
60
+ );
61
+ }
62
+ if (schema.maxLength !== undefined && value.length > schema.maxLength) {
63
+ problems.push(
64
+ `${path}: expected at most ${schema.maxLength} character(s), got ${value.length}`,
65
+ );
66
+ }
67
+ if (schema.pattern !== undefined) {
68
+ try {
69
+ if (!new RegExp(schema.pattern).test(value)) {
70
+ problems.push(`${path}: expected string matching ${JSON.stringify(schema.pattern)}`);
71
+ }
72
+ } catch {
73
+ problems.push(`${path}: schema pattern is invalid`);
74
+ }
75
+ }
76
+ return problems;
77
+ }
47
78
  case "number":
48
79
  case "boolean": {
49
80
  if (typeof value !== schema.type) {
@@ -1,6 +1,7 @@
1
1
  import { mkdirSync } from "node:fs";
2
2
  import { homedir } from "node:os";
3
3
  import { resolve } from "node:path";
4
+ import axe from "axe-core";
4
5
  import {
5
6
  type BrowserContext,
6
7
  type ConsoleMessage,
@@ -10,6 +11,13 @@ import {
10
11
  type Request,
11
12
  } from "playwright";
12
13
  import type { CookieJar, Cookie as JarCookie } from "../cookies/index.ts";
14
+ import {
15
+ buildClearLayoutLintAnnotationsScript,
16
+ buildLayoutLintAnnotateScript,
17
+ buildLayoutLintCheck,
18
+ type LayoutLintRequest,
19
+ type LayoutLintResult,
20
+ } from "./geometry.js";
13
21
  import {
14
22
  buildClearLayoutAnnotationsScript,
15
23
  buildLayoutAnnotateScript,
@@ -24,6 +32,13 @@ import {
24
32
  buildRuntsCheck,
25
33
  type RuntsResult,
26
34
  } from "./runts.js";
35
+ import {
36
+ buildClearTargetSizeAnnotationsScript,
37
+ buildTargetSizeAnnotateScript,
38
+ buildTargetSizeCheck,
39
+ type TargetSizeProfile,
40
+ type TargetSizeResult,
41
+ } from "./target-size.js";
27
42
  import {
28
43
  buildAnnotateScript,
29
44
  buildClearAnnotationsScript,
@@ -441,6 +456,53 @@ export class Browser {
441
456
  await this.currentPage.evaluate(buildClearLayoutAnnotationsScript());
442
457
  }
443
458
 
459
+ /** Run the selector-scoped rendered-geometry rule family in one page evaluation. */
460
+ async checkLayoutLint(request: LayoutLintRequest): Promise<LayoutLintResult> {
461
+ return await this.currentPage.evaluate(buildLayoutLintCheck(), request);
462
+ }
463
+
464
+ /** Draw one document-space annotation layer for rendered-geometry results. */
465
+ async annotateLayoutLint(result: LayoutLintResult): Promise<void> {
466
+ await this.currentPage.evaluate(buildLayoutLintAnnotateScript(), result);
467
+ }
468
+
469
+ /** Remove rendered-geometry annotations. */
470
+ async clearLayoutLintAnnotations(): Promise<void> {
471
+ await this.currentPage.evaluate(buildClearLayoutLintAnnotationsScript());
472
+ }
473
+
474
+ /**
475
+ * Run the target-size rule against the page or explicit scopes. The
476
+ * dependency's browser bundle is evaluated directly in the page context so
477
+ * a document CSP cannot silently block a script element.
478
+ */
479
+ async checkTargetSize(
480
+ selectors: Array<string | null>,
481
+ profile: TargetSizeProfile,
482
+ ): Promise<TargetSizeResult[]> {
483
+ await this.currentPage.evaluate(axe.source);
484
+ const results: TargetSizeResult[] = [];
485
+ for (const selector of selectors) {
486
+ results.push(
487
+ await this.currentPage.evaluate(buildTargetSizeCheck(), {
488
+ selector,
489
+ profile,
490
+ }),
491
+ );
492
+ }
493
+ return results;
494
+ }
495
+
496
+ /** Draw target-size failures and unknowns on the screenshot. */
497
+ async annotateTargetSize(results: TargetSizeResult[]): Promise<void> {
498
+ await this.currentPage.evaluate(buildTargetSizeAnnotateScript(), results);
499
+ }
500
+
501
+ /** Remove target-size annotations. */
502
+ async clearTargetSizeAnnotations(): Promise<void> {
503
+ await this.currentPage.evaluate(buildClearTargetSizeAnnotationsScript());
504
+ }
505
+
444
506
  /**
445
507
  * Inject a script that runs in every page context before page scripts
446
508
  * execute. Useful for seeding localStorage before an SSR/CSR comparison;