lazycodex-ai 5.1.34 → 5.1.35

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 (60) hide show
  1. package/dist/cli/index.js +116 -45
  2. package/dist/cli-node/index.js +116 -45
  3. package/package.json +1 -1
  4. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  5. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  6. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  7. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  8. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  9. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  10. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  11. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  12. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  13. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +2 -2
  14. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  15. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  16. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  17. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  18. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  19. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  20. package/packages/omo-codex/plugin/components/telemetry/dist/cli.js +2 -1
  21. package/packages/omo-codex/plugin/components/telemetry/dist/posthog.js +2 -1
  22. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  23. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  24. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  25. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  26. package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +1 -1
  27. package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +1 -1
  28. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +5 -5
  29. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  30. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  31. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  32. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  33. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  34. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  35. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  36. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  37. package/packages/omo-codex/plugin/hooks/post-tool-use-recording-spawn-admission.json +1 -1
  38. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  39. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  40. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  41. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  42. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  43. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  44. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  45. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +1 -1
  46. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  47. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  48. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  49. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  50. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  51. package/packages/omo-codex/plugin/package-lock.json +12 -12
  52. package/packages/omo-codex/plugin/package.json +1 -1
  53. package/packages/omo-codex/plugin/skills/browser/runtime/omowright/manifest.json +1 -1
  54. package/packages/omo-codex/plugin/skills/ulw-research/references/report-gates.md +1 -1
  55. package/packages/omo-codex/plugin/skills/ulw-research/scripts/gates-figures.mjs +22 -6
  56. package/packages/omo-codex/scripts/install-dist/install-local.mjs +50 -3
  57. package/packages/shared-skills/skills/browser/runtime/omowright/manifest.json +1 -1
  58. package/packages/shared-skills/skills/ulw-research/references/report-gates.md +1 -1
  59. package/packages/shared-skills/skills/ulw-research/scripts/gates-figures.mjs +22 -6
  60. package/packages/shared-skills/skills/ulw-research/scripts/gates-static.test.ts +13 -0
@@ -5,5 +5,5 @@
5
5
  "index.js": "f577c49fe18bcc78293e136e112a83861e86cca5d908ebceaaec524dff8b8ccc",
6
6
  "page-bundle.js": "bfd51e8383cf47200d57387bbbed258bce5a3a3d00c38fc108034d2888e23f0c"
7
7
  },
8
- "stagedAtUtc": "2026-10-16T07:26:31.363Z"
8
+ "stagedAtUtc": "2026-10-17T03:46:57.473Z"
9
9
  }
@@ -19,7 +19,7 @@ This reference catalogs every defect code the report gates (`static`, `layout`,
19
19
  | `chart_without_figure` | major | false | An image or chart lacks a figure wrapper with a caption. Uncaptioned charts isolate visuals from narrative flow. | Wrap the image or chart in a figure container with a caption. |
20
20
  | `chart_svg_no_text` | major | false | An SVG chart or diagram lacks a title, axis labels, units, or value labels. Visuals cannot stand alone without text guidance. | Give the chart a title, axis labels, units, and value labels as SVG text. |
21
21
  | `chart_svg_missing_labels` | minor | false | An SVG chart has some labels (e.g., title) but is missing others (e.g., axis ticks or unit). | Add the missing title, axis ticks, or unit label to the chart. |
22
- | `report_without_visual` | major | false | The report body has no chart, diagram, or figure image at all (header logos, icons, and images marked decorative do not count; only rendered output counts, so a Mermaid source block or a zero-size image does not). A text-only report hides structure and trends the reader would see at a glance. | Add at least one captioned visual of the findings: a chart from the data table, a rendered Mermaid diagram, or a figure image (references/report-visualization.md). |
22
+ | `report_without_visual` | major | false | The report body has no chart, diagram, or figure image at all (header logos, icons, and images marked decorative do not count; only rendered output counts, so a Mermaid source block or an image with any zero dimension (attribute, inline style, or viewBox) does not; an element with no declared size counts, because the browser sizes it, and the layout gate is where rendering is proven). A text-only report hides structure and trends the reader would see at a glance. | Add at least one captioned visual of the findings: a chart from the data table, a rendered Mermaid diagram, or a figure image (references/report-visualization.md). |
23
23
  | `image_missing_alt` | minor | false | A figure image has a missing or empty `alt` and is not marked decorative. Screen readers and failed image loads leave the reader with nothing. An image is decorative only with an empty `alt` plus `role="presentation"` (or `role="none"`, or `aria-hidden="true"`): it raises nothing here and does not count as a visual. | Give the image an alt attribute that states what it shows, not its file name; mark a purely decorative image alt="" with role="presentation". |
24
24
  | `korean_serif_font` | major | false | A serif or brush Korean font family is applied to Korean text. The design spec mandates gothic (sans) Korean typefaces. | Use a gothic (sans) Korean family; serif and brush families are banned by the design spec. |
25
25
  | `section_without_citation` | major | false | A major section or subsection contains no in-text citations or reference marks. Source attribution is missing. | Cite at least one source inside this section or merge it into a cited one. |
@@ -27,14 +27,30 @@ function pixels(value) {
27
27
  return match ? Number(match[1]) : null
28
28
  }
29
29
 
30
+ function fromStyle(node, prop) {
31
+ return pixels(new RegExp(`(?:^|;)\\s*${prop}\\s*:\\s*([^;]+)`, "i").exec(node.attrs.style ?? "")?.[1])
32
+ }
33
+
34
+ function viewBoxSize(node) {
35
+ const box = String(node.attrs.viewbox ?? "").trim().split(/[\s,]+/).map(Number)
36
+ return box.length === 4 && box.every(Number.isFinite) ? { width: box[2], height: box[3] } : null
37
+ }
38
+
30
39
  /** Largest declared dimension: width/height attributes or style, else the viewBox. */
31
40
  function declaredSize(node) {
32
- const style = node.attrs.style ?? ""
33
- const fromStyle = (prop) => pixels(new RegExp(`(?:^|;)\\s*${prop}\\s*:\\s*([^;]+)`, "i").exec(style)?.[1])
34
- const sizes = [pixels(node.attrs.width), pixels(node.attrs.height), fromStyle("width"), fromStyle("height")].filter((n) => n !== null)
41
+ const sizes = [pixels(node.attrs.width), pixels(node.attrs.height), fromStyle(node, "width"), fromStyle(node, "height")].filter((n) => n !== null)
35
42
  if (sizes.length) return Math.max(...sizes)
36
- const box = String(node.attrs.viewbox ?? "").trim().split(/[\s,]+/).map(Number)
37
- return box.length === 4 && box.every(Number.isFinite) ? Math.max(box[2], box[3]) : null
43
+ const box = viewBoxSize(node)
44
+ return box ? Math.max(box.width, box.height) : null
45
+ }
46
+
47
+ /**
48
+ * True when any declared dimension is zero, so the element cannot render visibly. Each axis reads its inline
49
+ * style first, then its attribute, then the viewBox. An undeclared axis is not zero: the browser sizes it.
50
+ */
51
+ function hasZeroDimension(node) {
52
+ const box = viewBoxSize(node)
53
+ return ["width", "height"].some((axis) => (fromStyle(node, axis) ?? pixels(node.attrs[axis]) ?? box?.[axis] ?? null) === 0)
38
54
  }
39
55
 
40
56
  function isIcon(ctx, node) {
@@ -174,7 +190,7 @@ export const figureGates = [
174
190
  {
175
191
  codes: ["report_without_visual"],
176
192
  run(ctx) {
177
- if (visuals(ctx).some((node) => declaredSize(node) !== 0 && !isDecorative(node))) return []
193
+ if (visuals(ctx).some((node) => !hasZeroDimension(node) && !isDecorative(node))) return []
178
194
  return [ctx.defect("report_without_visual", ctx.body, "the report has no chart, diagram, or figure image")]
179
195
  },
180
196
  },
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- // omo-codex-install:d6461760b0b2f0e272b51bfe2d55e5280cc505338f455df43303564f2465006c:3cb54cd0b22fe0bced6a100c92fc2b9f2eddc93cb6a82a57257140c4f8171750
2
+ // omo-codex-install:514fc40172f940764ac855efabb7ca823e26934b5971d91584ab388939e7cc2d:88692e67b85a3acb06158a9dac624e0206d47fe90d21ce1ce599751a2f8e7d93
3
3
  var __esm = (fn, res, err) => () => {
4
4
  if (fn)
5
5
  try {
@@ -234,6 +234,9 @@ var init_activity_state = __esm(() => {
234
234
  capturedDaysByStateDir = new Map;
235
235
  });
236
236
 
237
+ // packages/telemetry-core/src/consent-gated-fetch.ts
238
+ var init_consent_gated_fetch = () => {};
239
+
237
240
  // packages/telemetry-core/src/constants.ts
238
241
  var DEFAULT_POSTHOG_HOST = "https://us.i.posthog.com", DEFAULT_POSTHOG_API_KEY = "phc_CFJhj5HyvA62QPhvyaUCtaq23aUfznnijg5VaaGkNk74", UNCONFIGURED_POSTHOG_API_KEY = "phc_REPLACE_ME_OMO_NATIVE";
239
242
 
@@ -281,6 +284,7 @@ function toDiagnosticRecord(input, now) {
281
284
  timestamp: now.toISOString(),
282
285
  event: input.event,
283
286
  source: input.source,
287
+ ...input.count === undefined ? {} : { count: input.count },
284
288
  ...serializeError(input.error, input.errorKind)
285
289
  };
286
290
  }
@@ -373,7 +377,7 @@ function shouldDisableTelemetry(input) {
373
377
  const env = input.env ?? process.env;
374
378
  const globalPrefix = input.globalEnvPrefix ?? "OMO";
375
379
  const prefixes = Array.from(new Set([globalPrefix, input.productEnvPrefix]));
376
- if (isDisableFlag(env["DO_NOT_TRACK"])) {
380
+ if (isDisableFlag(env["DO_NOT_TRACK"]) || isDisableFlag(env[`${globalPrefix}_DISABLE_TELEMETRY`])) {
377
381
  return true;
378
382
  }
379
383
  for (const prefix of prefixes) {
@@ -405,6 +409,47 @@ var init_env = __esm(() => {
405
409
  SEND_OPT_OUT_VALUES = ["0", "false", "no", "yes"];
406
410
  });
407
411
 
412
+ // packages/telemetry-core/src/event-id.ts
413
+ import { randomBytes as nodeRandomBytes } from "node:crypto";
414
+ function createUuidV7Generator(source = {}) {
415
+ const now = source.now ?? Date.now;
416
+ const randomBytes = source.randomBytes ?? ((size) => new Uint8Array(nodeRandomBytes(size)));
417
+ let lastMs = -1;
418
+ let counter = 0;
419
+ return () => {
420
+ const random = randomBytes(10);
421
+ const wallMs = Math.floor(now());
422
+ if (wallMs > lastMs) {
423
+ lastMs = wallMs;
424
+ counter = (random[0] << 8 | random[1]) & COUNTER_SEED_MASK;
425
+ } else if (counter < MAX_COUNTER) {
426
+ counter += 1;
427
+ } else {
428
+ lastMs += 1;
429
+ counter = (random[0] << 8 | random[1]) & COUNTER_SEED_MASK;
430
+ }
431
+ const bytes = new Uint8Array(16);
432
+ let timestamp = lastMs;
433
+ for (let index = 5;index >= 0; index -= 1) {
434
+ bytes[index] = timestamp % 256;
435
+ timestamp = Math.floor(timestamp / 256);
436
+ }
437
+ bytes[6] = 112 | counter >> 8;
438
+ bytes[7] = counter & 255;
439
+ bytes[8] = 128 | random[2] & 63;
440
+ bytes.set(random.subarray(3, 10), 9);
441
+ return formatUuid(bytes);
442
+ };
443
+ }
444
+ function formatUuid(bytes) {
445
+ const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
446
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
447
+ }
448
+ var MAX_COUNTER = 4095, COUNTER_SEED_MASK = 2047, fallbackEventId;
449
+ var init_event_id = __esm(() => {
450
+ fallbackEventId = createUuidV7Generator();
451
+ });
452
+
408
453
  // node_modules/.bun/posthog-node@5.52.4/node_modules/posthog-node/dist/extensions/error-tracking/modifiers/module.node.mjs
409
454
  import { dirname as dirname11, posix as posix3, sep as sep7 } from "node:path";
410
455
  function createModulerModifier() {
@@ -9971,8 +10016,10 @@ var init_record_daily_active = () => {};
9971
10016
  // packages/telemetry-core/src/index.ts
9972
10017
  var init_src = __esm(() => {
9973
10018
  init_activity_state();
10019
+ init_consent_gated_fetch();
9974
10020
  init_diagnostics();
9975
10021
  init_env();
10022
+ init_event_id();
9976
10023
  init_events();
9977
10024
  init_machine_id();
9978
10025
  init_posthog_client();
@@ -9984,7 +10031,7 @@ var package_default;
9984
10031
  var init_package = __esm(() => {
9985
10032
  package_default = {
9986
10033
  name: "@oh-my-opencode/omo-codex",
9987
- version: "5.1.34",
10034
+ version: "5.1.35",
9988
10035
  type: "module",
9989
10036
  private: true,
9990
10037
  description: "Codex harness adapter for oh-my-openagent. Vendored Codex plugin namespace (omo) + TypeScript installer + telemetry.",
@@ -5,5 +5,5 @@
5
5
  "index.js": "f577c49fe18bcc78293e136e112a83861e86cca5d908ebceaaec524dff8b8ccc",
6
6
  "page-bundle.js": "bfd51e8383cf47200d57387bbbed258bce5a3a3d00c38fc108034d2888e23f0c"
7
7
  },
8
- "stagedAtUtc": "2026-10-16T07:26:31.363Z"
8
+ "stagedAtUtc": "2026-10-17T03:46:57.473Z"
9
9
  }
@@ -19,7 +19,7 @@ This reference catalogs every defect code the report gates (`static`, `layout`,
19
19
  | `chart_without_figure` | major | false | An image or chart lacks a figure wrapper with a caption. Uncaptioned charts isolate visuals from narrative flow. | Wrap the image or chart in a figure container with a caption. |
20
20
  | `chart_svg_no_text` | major | false | An SVG chart or diagram lacks a title, axis labels, units, or value labels. Visuals cannot stand alone without text guidance. | Give the chart a title, axis labels, units, and value labels as SVG text. |
21
21
  | `chart_svg_missing_labels` | minor | false | An SVG chart has some labels (e.g., title) but is missing others (e.g., axis ticks or unit). | Add the missing title, axis ticks, or unit label to the chart. |
22
- | `report_without_visual` | major | false | The report body has no chart, diagram, or figure image at all (header logos, icons, and images marked decorative do not count; only rendered output counts, so a Mermaid source block or a zero-size image does not). A text-only report hides structure and trends the reader would see at a glance. | Add at least one captioned visual of the findings: a chart from the data table, a rendered Mermaid diagram, or a figure image (references/report-visualization.md). |
22
+ | `report_without_visual` | major | false | The report body has no chart, diagram, or figure image at all (header logos, icons, and images marked decorative do not count; only rendered output counts, so a Mermaid source block or an image with any zero dimension (attribute, inline style, or viewBox) does not; an element with no declared size counts, because the browser sizes it, and the layout gate is where rendering is proven). A text-only report hides structure and trends the reader would see at a glance. | Add at least one captioned visual of the findings: a chart from the data table, a rendered Mermaid diagram, or a figure image (references/report-visualization.md). |
23
23
  | `image_missing_alt` | minor | false | A figure image has a missing or empty `alt` and is not marked decorative. Screen readers and failed image loads leave the reader with nothing. An image is decorative only with an empty `alt` plus `role="presentation"` (or `role="none"`, or `aria-hidden="true"`): it raises nothing here and does not count as a visual. | Give the image an alt attribute that states what it shows, not its file name; mark a purely decorative image alt="" with role="presentation". |
24
24
  | `korean_serif_font` | major | false | A serif or brush Korean font family is applied to Korean text. The design spec mandates gothic (sans) Korean typefaces. | Use a gothic (sans) Korean family; serif and brush families are banned by the design spec. |
25
25
  | `section_without_citation` | major | false | A major section or subsection contains no in-text citations or reference marks. Source attribution is missing. | Cite at least one source inside this section or merge it into a cited one. |
@@ -27,14 +27,30 @@ function pixels(value) {
27
27
  return match ? Number(match[1]) : null
28
28
  }
29
29
 
30
+ function fromStyle(node, prop) {
31
+ return pixels(new RegExp(`(?:^|;)\\s*${prop}\\s*:\\s*([^;]+)`, "i").exec(node.attrs.style ?? "")?.[1])
32
+ }
33
+
34
+ function viewBoxSize(node) {
35
+ const box = String(node.attrs.viewbox ?? "").trim().split(/[\s,]+/).map(Number)
36
+ return box.length === 4 && box.every(Number.isFinite) ? { width: box[2], height: box[3] } : null
37
+ }
38
+
30
39
  /** Largest declared dimension: width/height attributes or style, else the viewBox. */
31
40
  function declaredSize(node) {
32
- const style = node.attrs.style ?? ""
33
- const fromStyle = (prop) => pixels(new RegExp(`(?:^|;)\\s*${prop}\\s*:\\s*([^;]+)`, "i").exec(style)?.[1])
34
- const sizes = [pixels(node.attrs.width), pixels(node.attrs.height), fromStyle("width"), fromStyle("height")].filter((n) => n !== null)
41
+ const sizes = [pixels(node.attrs.width), pixels(node.attrs.height), fromStyle(node, "width"), fromStyle(node, "height")].filter((n) => n !== null)
35
42
  if (sizes.length) return Math.max(...sizes)
36
- const box = String(node.attrs.viewbox ?? "").trim().split(/[\s,]+/).map(Number)
37
- return box.length === 4 && box.every(Number.isFinite) ? Math.max(box[2], box[3]) : null
43
+ const box = viewBoxSize(node)
44
+ return box ? Math.max(box.width, box.height) : null
45
+ }
46
+
47
+ /**
48
+ * True when any declared dimension is zero, so the element cannot render visibly. Each axis reads its inline
49
+ * style first, then its attribute, then the viewBox. An undeclared axis is not zero: the browser sizes it.
50
+ */
51
+ function hasZeroDimension(node) {
52
+ const box = viewBoxSize(node)
53
+ return ["width", "height"].some((axis) => (fromStyle(node, axis) ?? pixels(node.attrs[axis]) ?? box?.[axis] ?? null) === 0)
38
54
  }
39
55
 
40
56
  function isIcon(ctx, node) {
@@ -174,7 +190,7 @@ export const figureGates = [
174
190
  {
175
191
  codes: ["report_without_visual"],
176
192
  run(ctx) {
177
- if (visuals(ctx).some((node) => declaredSize(node) !== 0 && !isDecorative(node))) return []
193
+ if (visuals(ctx).some((node) => !hasZeroDimension(node) && !isDecorative(node))) return []
178
194
  return [ctx.defect("report_without_visual", ctx.body, "the report has no chart, diagram, or figure image")]
179
195
  },
180
196
  },
@@ -263,6 +263,19 @@ describe("report-level visuals", () => {
263
263
  expect(chartCodes(htmlLabels)).toEqual(["chart_svg_no_text"])
264
264
  })
265
265
 
266
+ test("#given a single visual with one zero dimension #when checked #then report_without_visual is raised; viewBox-only and unsized visuals still count", () => {
267
+ // given
268
+ const only = (el: string) => `<figure>${el}<figcaption>c</figcaption></figure>`
269
+ const flat = only('<img src="data:image/png;base64,iVBORw0KGgo=" alt="chart" width="600" height="0">')
270
+ const narrow = only('<svg width="0" height="300"><text>A</text></svg>')
271
+ const styled = only('<img src="data:image/png;base64,iVBORw0KGgo=" alt="chart" width="600" height="300" style="height: 0">')
272
+ const viewBoxOnly = only('<svg viewBox="0 0 600 300" aria-roledescription="flowchart-v2"><text>A</text></svg>')
273
+ const unsized = only('<img src="data:image/png;base64,iVBORw0KGgo=" alt="Deploys per week">')
274
+ // when / then
275
+ for (const html of [flat, narrow, styled]) expect(has(html, "report_without_visual")).toBe(true)
276
+ for (const html of [viewBoxOnly, unsized]) expect(has(html, "report_without_visual")).toBe(false)
277
+ })
278
+
266
279
  test("#given figure images with no alt, a bare empty alt, role- and aria-marked decorative alts and a descriptive alt #when checked #then only the unmarked two raise image_missing_alt", () => {
267
280
  // given
268
281
  const img = (alt: string) => `<figure><img src="data:image/png;base64,iVBORw0KGgo=" ${alt} width="480" height="240"><figcaption>c</figcaption></figure>`