@ggui-ai/ui-gen 0.23.0 → 0.25.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 (123) hide show
  1. package/dist/adapter-Cg_rkpGq.d.ts +201 -0
  2. package/dist/adapters/generation-dispatch.d.ts +58 -15
  3. package/dist/adapters/generation-dispatch.js +1418 -180
  4. package/dist/adapters/generation-dispatch.js.map +1 -1
  5. package/dist/adapters/index.js +3 -1
  6. package/dist/adapters/index.js.map +1 -1
  7. package/dist/advanced/index.d.ts +12 -8
  8. package/dist/advanced/index.js +1467 -239
  9. package/dist/advanced/index.js.map +1 -1
  10. package/dist/{axes-CzLEMDeB.d.ts → axes-CKVCzR_x.d.ts} +1 -1
  11. package/dist/bank-CT4eEkta.d.ts +118 -0
  12. package/dist/blueprint-validator.js +153 -59
  13. package/dist/blueprint-validator.js.map +1 -1
  14. package/dist/boilerplate.js +24 -12
  15. package/dist/boilerplate.js.map +1 -1
  16. package/dist/check/index.d.ts +12 -4
  17. package/dist/check/index.js +94 -2
  18. package/dist/check/index.js.map +1 -1
  19. package/dist/classifier/index.d.ts +2 -2
  20. package/dist/compose.d.ts +2 -2
  21. package/dist/{create-ui-generator-D0kbWwln.d.ts → create-ui-generator-DFnnArrv.d.ts} +43 -11
  22. package/dist/{dispatch-wxaIMwZt.d.ts → dispatch-CStl9eAw.d.ts} +5 -3
  23. package/dist/evaluation/axis-checks/index.d.ts +6 -5
  24. package/dist/evaluation/axis-checks/index.js +90 -2
  25. package/dist/evaluation/axis-checks/index.js.map +1 -1
  26. package/dist/evaluation/axis-checks/registry.d.ts +4 -3
  27. package/dist/evaluation/axis-checks/registry.js +88 -1
  28. package/dist/evaluation/axis-checks/registry.js.map +1 -1
  29. package/dist/evaluation/index.d.ts +301 -23
  30. package/dist/evaluation/index.js +746 -30
  31. package/dist/evaluation/index.js.map +1 -1
  32. package/dist/evaluation/types.d.ts +9 -1
  33. package/dist/evaluation/types.js.map +1 -1
  34. package/dist/fragments/index.d.ts +3 -3
  35. package/dist/harness/check/runtime-render/index.d.ts +30 -11
  36. package/dist/harness/check/runtime-render/index.js +203 -60
  37. package/dist/harness/check/runtime-render/index.js.map +1 -1
  38. package/dist/harness/check/runtime-render/render-check-worker.d.ts +8 -1
  39. package/dist/harness/check/runtime-render/render-check-worker.js +72 -32
  40. package/dist/harness/check/runtime-render/render-check-worker.js.map +1 -1
  41. package/dist/harness/index.d.ts +5 -4
  42. package/dist/harness/index.js +33 -15
  43. package/dist/harness/index.js.map +1 -1
  44. package/dist/harness/prompts.js.map +1 -1
  45. package/dist/harness/result-types.d.ts +4 -3
  46. package/dist/harness/runtime.d.ts +11 -4
  47. package/dist/harness/runtime.js +26 -14
  48. package/dist/harness/runtime.js.map +1 -1
  49. package/dist/harness/types-public.d.ts +13 -4
  50. package/dist/harness/types-public.js +33 -15
  51. package/dist/harness/types-public.js.map +1 -1
  52. package/dist/harness/validator-trace-sink.d.ts +4 -3
  53. package/dist/hash.d.ts +1 -1
  54. package/dist/index.d.ts +59 -8
  55. package/dist/index.js +1476 -241
  56. package/dist/index.js.map +1 -1
  57. package/dist/{llm-router-DwwUK1bz.d.ts → llm-router-nfO7wPec.d.ts} +3 -1
  58. package/dist/patch.d.ts +4 -3
  59. package/dist/policy.d.ts +8 -5
  60. package/dist/policy.js.map +1 -1
  61. package/dist/tools/get-primitives-ts.d.ts +1 -1
  62. package/dist/tools/get-primitives-ts.js +1 -1
  63. package/dist/tools/get-primitives-ts.js.map +1 -1
  64. package/dist/tools/render-check-worker.d.ts +7 -1
  65. package/dist/tools/render-check-worker.js +55 -23
  66. package/dist/tools/render-check-worker.js.map +1 -1
  67. package/dist/{types-BOvHNG7K.d.ts → types-Dh1s4K9j.d.ts} +1 -1
  68. package/dist/{types-public-Ow-tNtFE.d.ts → types-public-BJTLpzWn.d.ts} +208 -15
  69. package/dist/validation/index.d.ts +1 -1
  70. package/dist/validation/index.js +1 -1
  71. package/dist/validation/index.js.map +1 -1
  72. package/dist/workflows.d.ts +4 -3
  73. package/package.json +12 -12
  74. package/src/adapters/generation-dispatch.ts +173 -98
  75. package/src/adapters/tools.ts +2 -1
  76. package/src/boilerplate/free-design-prompt.ts +1 -1
  77. package/src/boilerplate/generate.ts +26 -1
  78. package/src/boilerplate/hard-sections.ts +13 -13
  79. package/src/boilerplate/system-prompt.ts +1 -1
  80. package/src/check/index.ts +1 -0
  81. package/src/check/run-tier0.ts +80 -1
  82. package/src/check/sample-props.ts +63 -0
  83. package/src/coding-agent/tools.ts +4 -1
  84. package/src/create-harness.ts +3 -3
  85. package/src/create-ui-generator.ts +204 -95
  86. package/src/evaluation/__fixtures__/png.ts +100 -0
  87. package/src/evaluation/axis-checks/checks/state-merge.ts +1 -1
  88. package/src/evaluation/axis-checks/checks/universal.ts +111 -0
  89. package/src/evaluation/axis-checks/dispatch.ts +4 -1
  90. package/src/evaluation/criteria/bank.ts +85 -0
  91. package/src/evaluation/criteria/context.ts +52 -0
  92. package/src/evaluation/criteria/resolve.ts +159 -0
  93. package/src/evaluation/criteria/select.ts +79 -0
  94. package/src/evaluation/index.ts +23 -0
  95. package/src/evaluation/ink-extent.ts +200 -0
  96. package/src/evaluation/theme-css.ts +12 -5
  97. package/src/evaluation/types-public.ts +200 -11
  98. package/src/evaluation/types.ts +9 -0
  99. package/src/evaluation/visual-evaluator.ts +636 -30
  100. package/src/harness/check/runtime-render/adapter.ts +221 -75
  101. package/src/harness/check/runtime-render/index.ts +75 -2
  102. package/src/harness/check/runtime-render/render-check-host.ts +82 -19
  103. package/src/harness/check/runtime-render/render-check-worker.ts +83 -29
  104. package/src/harness/check/runtime-render/render-check.ts +154 -117
  105. package/src/harness/coding/generate-task-runner.ts +60 -4
  106. package/src/harness/coding/init-session.ts +13 -0
  107. package/src/harness/coding/run-coding-turn.ts +7 -3
  108. package/src/harness/coding/run-eval-round.ts +257 -15
  109. package/src/harness/policy.ts +11 -0
  110. package/src/harness/primitive-slice.ts +104 -0
  111. package/src/harness/runtime.ts +5 -0
  112. package/src/harness/types-public.ts +9 -1
  113. package/src/harness-tool-names.ts +38 -0
  114. package/src/index.ts +16 -0
  115. package/src/policy.ts +7 -4
  116. package/src/run-check.ts +2 -0
  117. package/src/tools/get-primitives-ts.ts +1 -1
  118. package/src/tools/get-wire.ts +1 -1
  119. package/src/tools/render-check-worker.ts +74 -23
  120. package/src/tools/render-check.ts +0 -60
  121. package/src/tools.ts +11 -1
  122. package/src/validation/primitives.ts +1 -1
  123. package/dist/render-check-Blwj8gB6.d.ts +0 -105
@@ -1,19 +1,23 @@
1
- import { C as CanvasJudgeRecord, E as EvalIssue, V as VisualEvalSummary, d as VisualCoverage } from '../types-public-Ow-tNtFE.js';
2
- export { A as AxisCheck, a as AxisCheckInput, e as CRITERIA, f as CanvasVisualSummary, g as ContractFeedbackRecord, h as CriterionCoverage, i as CriterionRunStatus, D as DEFAULT_QUALITY_CONFIG, j as EvalCategory, k as EvalCriterion, l as EvalOutcome, b as EvalResult, c as EvalTier, L as LLM_EVAL_STATIC_CRITERIA, n as Priority, Q as QualityConfig, o as QualityMode, p as buildCodingCriteriaSummary, q as criteriaFor, r as getActionableIssues, s as getCriteriaByPriority, t as getCriterionById, u as getLLMCriteria, v as isBlocked, m as matches, w as notApplicableCoverage, x as priorityForIssue } from '../types-public-Ow-tNtFE.js';
1
+ import { C as CriteriaContext, d as CriteriaChroma, e as CanvasJudgeRecord, f as CriteriaBlock, g as CanvasPresentationOutcome, h as CanvasHostPresentation, E as EvalIssue, V as VisualEvalSummary, i as VisualCoverage, j as CriteriaSelection } from '../types-public-BJTLpzWn.js';
2
+ export { A as AxisCheck, a as AxisCheckInput, k as CRITERIA, l as CanvasVisualSummary, n as ContractFeedbackRecord, o as CriterionCoverage, p as CriterionRunStatus, D as DEFAULT_QUALITY_CONFIG, q as EvalCategory, r as EvalCriterion, s as EvalOutcome, b as EvalResult, c as EvalTier, H as HostInlineFrame, t as HostPresentationIgnoredReason, L as LLM_EVAL_STATIC_CRITERIA, u as Priority, Q as QualityConfig, v as QualityMode, w as buildCodingCriteriaSummary, x as criteriaFor, y as getActionableIssues, z as getCriteriaByPriority, B as getCriterionById, F as getLLMCriteria, G as isBlocked, m as matches, I as notApplicableCoverage, J as priorityForIssue } from '../types-public-BJTLpzWn.js';
3
3
  import * as _anthropic_ai_claude_agent_sdk from '@anthropic-ai/claude-agent-sdk';
4
4
  import { McpServerConfig } from '@anthropic-ai/claude-agent-sdk';
5
- import { EvaluationContext, EvaluationConfig, QualityMetadata, EvaluationResult, EvaluationIssue } from './types.js';
5
+ import { EvaluationContext, EvaluationConfig, QualityMetadata, EvaluationResult, EvaluationIssue, CriteriaAnswer } from './types.js';
6
6
  export { DEFAULT_EVAL_MAX_ROUNDS, DimensionScores, MAX_EVAL_ROUNDS_HARD_LIMIT } from './types.js';
7
- export { R as RunAxisChecksInput, r as runAxisChecks } from '../dispatch-wxaIMwZt.js';
8
- import { A as AgentConfig, L as LLMResponse } from '../llm-router-DwwUK1bz.js';
7
+ export { R as RunAxisChecksInput, r as runAxisChecks } from '../dispatch-CStl9eAw.js';
8
+ import { A as AgentConfig, L as LLMResponse } from '../llm-router-nfO7wPec.js';
9
9
  import { G as GenerationProfileInput } from '../styling-profile-CxfvV48g.js';
10
+ import { C as CriteriaBank } from '../bank-CT4eEkta.js';
11
+ export { B as BankRow, a as CriteriaScope, b as bankRows, c as criteriaBankSchema, p as parseCriteriaBank } from '../bank-CT4eEkta.js';
12
+ import { DataContract, JsonObject, AppTheme } from '@ggui-ai/protocol';
13
+ import { C as Classification } from '../axes-CKVCzR_x.js';
10
14
  import { LaunchOptions } from 'puppeteer-core';
11
15
  import { C as CanvasClass, g as CanvasViewport } from '../design-mode-DLufhrNp.js';
12
16
  export { a as CANVAS_BREAKPOINTS, b as CANVAS_CLASSES, c as CANVAS_DESCRIPTORS, d as CANVAS_VIEWPORTS, e as CanvasDescriptor, f as CanvasDisplayMode, j as canvasDisplayModeForShell, k as canvasForRendering, l as canvasForViewportWidth, m as describeCanvas } from '../design-mode-DLufhrNp.js';
13
- import { AppTheme } from '@ggui-ai/protocol';
14
- import '../axes-CzLEMDeB.js';
15
- import '../types-BOvHNG7K.js';
17
+ import '@ggui-ai/mcp-server-core';
18
+ import '../types-Dh1s4K9j.js';
16
19
  import '../llm.js';
20
+ import 'zod';
17
21
 
18
22
  /**
19
23
  * Options for running the evaluation loop.
@@ -185,6 +189,26 @@ declare function extractCompiledCode(messages: SdkMessage[]): string | undefined
185
189
  */
186
190
  declare function extractSourceCode(messages: SdkMessage[]): string | undefined;
187
191
 
192
+ /**
193
+ * The selector's inputs for one card — ggui#1436. Every key here is hashed into `criteriaSetId`
194
+ * and STORED in the block (the CTO's A1), so a stored verdict reproduces its own set from the
195
+ * record alone. `canvas` is added per canvas inside the judge; the rest is the harness's.
196
+ */
197
+
198
+ /** Read the theme's chroma off its tokens; `unknown` when no primary is named. */
199
+ declare function chromaOfCssTokens(cssTokens: string | undefined): CriteriaChroma;
200
+ interface CriteriaContextSources {
201
+ readonly classification: Classification;
202
+ readonly contract: DataContract | undefined;
203
+ readonly cssTokens: string | undefined;
204
+ readonly profile: GenerationProfileInput | undefined;
205
+ readonly shell: string;
206
+ readonly kind?: string;
207
+ }
208
+ /** The context minus `canvas` — the judge fills that per canvas. */
209
+ type CriteriaContextInput = Omit<CriteriaContext, 'canvas'>;
210
+ declare function criteriaContextFor(src: CriteriaContextSources): CriteriaContextInput;
211
+
188
212
  interface JudgeDesignIdentity {
189
213
  /** Absolute path of the design `src` tree the judge bundled against. */
190
214
  readonly src: string;
@@ -259,6 +283,14 @@ interface VisualEvalConfig {
259
283
  * `viewport` all carry that same integer box.
260
284
  */
261
285
  canvasViewports?: Partial<Readonly<Record<CanvasClass, CanvasViewport>>>;
286
+ /**
287
+ * ggui#1492 — how a host presents each canvas, as data the caller supplies (a lane that knows its host). Keyed by
288
+ * canvas; a canvas without an entry is judged exactly as before (the generic stand-in round the inline card, the
289
+ * scrim under a panel). The box stays in {@link canvasViewports}. An entry this judge cannot use (a colour that is
290
+ * not `#rrggbb`, a number out of range, a frame on a canvas that is not the inline card) is ignored for its canvas,
291
+ * said once in the log, never partly applied.
292
+ */
293
+ hostPresentations?: Partial<Readonly<Record<CanvasClass, CanvasHostPresentation>>>;
262
294
  /**
263
295
  * Optional provider-routing override — see
264
296
  * `AgentConfig.routeOverride`. Threaded onto the agent this
@@ -291,6 +323,14 @@ interface VisualEvalConfig {
291
323
  */
292
324
  onRetry?: AgentConfig['onRetry'];
293
325
  }
326
+ /**
327
+ * ggui#1436 — what the report-only criteria call spent. Kept APART from the scoring calls' `inputTokens` /
328
+ * `outputTokens`: those price the judgement a caller may meter, and the criteria call is a measurement beside it.
329
+ */
330
+ interface CriteriaCallTokens {
331
+ readonly inputTokens: number;
332
+ readonly outputTokens: number;
333
+ }
294
334
  /** One canvas's verdict — screenshot + judge score at that class's viewport. */
295
335
  interface CanvasVisualResult {
296
336
  canvas: CanvasClass;
@@ -310,32 +350,91 @@ interface CanvasVisualResult {
310
350
  /** `contentHeight > viewport.height` — a measurement; what it MEANS is {@link canvasFitPolicy}'s. */
311
351
  overflow: boolean;
312
352
  /** How `score` was reached — always present (ggui#1072). */
353
+ /**
354
+ * ggui#1120 — how far down the capture anything was painted (the last inked row over the measured
355
+ * region's height, read against the capture's dominant colour, inside a drawn panel's chrome); `0`
356
+ * is the blank the judge fails, `null` an unreadable capture.
357
+ */
358
+ inkRatio: number | null;
313
359
  judge: CanvasJudgeRecord;
314
360
  /** How the judge composed the mount (ggui#1100): `'fill'` on every fullscreen canvas, absent on the inline card. */
315
361
  fit?: 'fill';
316
362
  /** ggui#1195 — `true` when the order DECLARED this canvas's box (`config.canvasViewports` carried an entry), whatever its value. */
317
363
  declared?: true;
364
+ /** ggui#1436 — the typed criteria block, when a bank was configured. */
365
+ criteria?: CriteriaBlock;
366
+ /** ggui#1436 — the criteria call's own spend, when one was asked and answered; never inside the canvas's scoring tokens. */
367
+ criteriaTokens?: CriteriaCallTokens;
368
+ /** ggui#1492 — what the judge did with this canvas's host presentation (drawn, or ignored and why), when one was supplied. */
369
+ presentation?: CanvasPresentationOutcome;
318
370
  }
319
371
  /** How a canvas is captured for the judge and what an overflow means there (ggui#1027). */
320
- type CaptureMode = 'viewport' | 'full-page';
372
+ type CaptureMode = 'viewport' | 'full-page' | 'natural';
321
373
  interface CanvasFitPolicy {
322
- /** `viewport` = the judge sees the box the user sees; `full-page` = the whole scrolled document. */
374
+ /**
375
+ * `viewport` = the whole box; `full-page` = the whole scrolled document; `natural` (ggui#1475) = the
376
+ * card at its OWN height, clipped to its extent and capped at the box — the inline card a host sizes
377
+ * to its content, on the host's ground ({@link JUDGE_GROUND_MARGIN_PX}).
378
+ */
323
379
  readonly capture: CaptureMode;
324
380
  /** The verdict an overflow earns on this canvas. */
325
381
  readonly overflow: 'fail' | 'warn' | 'none';
326
382
  }
327
383
  /**
328
- * The inline chat card is a BOX — the bubble bounds the component and it
329
- * does not scroll — so the judge captures the viewport (a 1289 px hello on
330
- * a 640 px card was scored 86 from a full-page capture that showed the
331
- * judge what no user sees) and an overflow is a critical layout issue that
332
- * fails the canvas. A phone's first screen may scroll, so the overflow is
333
- * reported as a major issue and the score stands. Pages (`md`/`lg`/`xl`)
334
- * scroll by design: measured, never judged.
384
+ * The inline chat card takes its NATURAL height under a ceiling (ggui#1475):
385
+ * an MCP Apps host sizes the inline frame to the card's content
386
+ * (`ui/notifications/size-changed`, auto-resize) up to its maximum, so the
387
+ * visitor sees the card and nothing under it. The judge captures exactly
388
+ * that — the card's own extent on the host's ground, capped at the box — and
389
+ * never the box's remainder (a fixed 640 px capture scored every hello
390
+ * against a void no visitor sees). The box stays the ceiling: content taller
391
+ * than it is a critical layout issue that fails the canvas (a 1289 px hello
392
+ * on a 640 px card was scored 86 from a full-page capture that showed the
393
+ * judge what no user sees). A phone's first screen may scroll, so the
394
+ * overflow is reported as a major issue and the score stands. Pages
395
+ * (`md`/`lg`/`xl`) scroll by design: measured, never judged.
335
396
  */
336
397
  declare function canvasFitPolicy(canvas: CanvasClass): CanvasFitPolicy;
398
+ /**
399
+ * How far in from a panelled page's edges the ink is read (ggui#1120): past the panel's gap, its
400
+ * largest rounded corner (the `round` bucket, 24 px — the scrim shows through the corner) and its
401
+ * 1 px hairline, so the host's chrome never counts as paint. The card's own inset is 16 px, so the
402
+ * band skipped inside the card is 25 px of a canvas — reported ratios are over the region.
403
+ */
404
+ declare const JUDGE_INK_INSET_PX: number;
405
+ /**
406
+ * The host ground round a naturally-captured inline card (ggui#1475): the card is mounted this far in
407
+ * from the page's edges and captured with this margin, so its edge and radius are read against the
408
+ * host surface — the page's scrim ground, never the card's own. The design's one gap (the panel's).
409
+ */
410
+ declare const JUDGE_GROUND_MARGIN_PX: 16;
411
+ /**
412
+ * The bounds a host frame must meet to be drawn (ggui#1492), exported so a lane's reader applies exactly the frames
413
+ * this judge draws: an entry the reader accepts and the judge ignores would be echoed as applied while never drawn.
414
+ */
415
+ declare const HOST_COLOUR_PATTERN: RegExp;
416
+ declare const HOST_FRAME_BOUNDS: {
417
+ readonly ringWidthPx: {
418
+ readonly min: 0;
419
+ readonly max: 8;
420
+ };
421
+ readonly ringAlpha: {
422
+ readonly min: 0;
423
+ readonly max: 1;
424
+ };
425
+ readonly radiusPx: {
426
+ readonly min: 0;
427
+ readonly max: 64;
428
+ };
429
+ readonly minHeightPx: {
430
+ readonly min: 0;
431
+ readonly max: 2560;
432
+ };
433
+ };
337
434
  /** The deterministic fit issue — one per overflowing canvas, in the judge's issue shape so it rides the same channel. */
338
435
  declare function canvasOverflowIssue(canvas: CanvasClass, viewport: CanvasViewport, contentHeight: number, verdict: 'fail' | 'warn'): EvaluationIssue;
436
+ /** ggui#1120 — the deterministic blank: the capture is one flat colour, so the component mounted and painted nothing. */
437
+ declare function canvasBlankIssue(canvas: CanvasClass, viewport: CanvasViewport): EvaluationIssue;
339
438
  /**
340
439
  * `runVisualEvaluation`'s result. Identical to `EvaluationResult` when
341
440
  * `config.canvases` is unset; with canvases set, `canvases` holds the
@@ -344,6 +443,11 @@ declare function canvasOverflowIssue(canvas: CanvasClass, viewport: CanvasViewpo
344
443
  */
345
444
  interface VisualEvaluationResult extends EvaluationResult {
346
445
  canvases?: CanvasVisualResult[];
446
+ /**
447
+ * ggui#1436 — the criteria calls' spend across canvases, when any was asked and answered. `inputTokens` /
448
+ * `outputTokens` stay the SCORING calls' alone, so a cost read off them never includes the report-only block.
449
+ */
450
+ criteriaTokens?: CriteriaCallTokens;
347
451
  /** The design tree the judge painted with (ggui#1042) — present on every per-canvas judgement. */
348
452
  design?: JudgeDesignIdentity;
349
453
  /** The mode `cssTokens` were composed in, when the caller said (ggui#1076). */
@@ -363,6 +467,11 @@ interface VisualEvalContext {
363
467
  cssTokens?: string;
364
468
  /** The app's generation profile (#991) — judged relative to, never against. */
365
469
  profile?: GenerationProfileInput;
470
+ /** ggui#1436 — a criteria bank and the card's context; the judge selects per canvas and answers report-only. */
471
+ criteria?: {
472
+ readonly bank: CriteriaBank;
473
+ readonly context: CriteriaContextInput;
474
+ };
366
475
  }
367
476
  /**
368
477
  * The `@ggui-ai/design` package root — resolved by MODULE ID, never by counting
@@ -379,6 +488,13 @@ interface VisualEvalContext {
379
488
  * hoisted — and the receipt keeps working inside the image.
380
489
  */
381
490
  declare function resolveDesignPackageDir(): string;
491
+ /** A screenshot's region in page px (puppeteer's `clip`). */
492
+ interface ScreenshotClip {
493
+ readonly x: number;
494
+ readonly y: number;
495
+ readonly width: number;
496
+ readonly height: number;
497
+ }
382
498
  /** The page surface the capture uses — a structural subset of puppeteer's `Page`. */
383
499
  interface ScreenshotPage {
384
500
  setContent(html: string, options: {
@@ -397,6 +513,7 @@ interface ScreenshotPage {
397
513
  screenshot(options: {
398
514
  type: 'png';
399
515
  fullPage: boolean;
516
+ clip?: ScreenshotClip;
400
517
  }): Promise<Uint8Array>;
401
518
  }
402
519
  /** The browser surface the capture uses — a structural subset of puppeteer's `Browser`. */
@@ -445,13 +562,22 @@ interface ScreenshotAttempt {
445
562
  readonly reason?: string;
446
563
  /** The document's scroll height at the viewport (ggui#1027); `null` when unmeasurable. */
447
564
  readonly contentHeight: number | null;
565
+ /** ggui#1475 — a natural capture's horizontal overflow: how many px the card's content runs past its width; absent on every other capture. */
566
+ readonly overflowX?: number | null;
448
567
  }
449
568
  /** The expression the fit measurement evaluates in the page — the taller of the two scroll heights. */
450
569
  declare const CONTENT_HEIGHT_EXPRESSION = "Math.max(document.documentElement.scrollHeight, document.body ? document.body.scrollHeight : 0)";
570
+ /** The stand-in page's card height ({@link cardHeightExpression} at the stand-in's pad). */
571
+ declare const CARD_HEIGHT_EXPRESSION: string;
572
+ /** ggui#1492 — a natural capture's geometry: the page's pad per side, and the host's floor when it has one. */
573
+ interface NaturalCaptureOptions {
574
+ readonly padPx: number;
575
+ readonly floorPx?: number;
576
+ }
451
577
  declare function captureScreenshotDetailed(html: string, viewport?: {
452
578
  width: number;
453
579
  height: number;
454
- }, deps?: ScreenshotDeps, capture?: CaptureMode): Promise<ScreenshotAttempt>;
580
+ }, deps?: ScreenshotDeps, capture?: CaptureMode, natural?: NaturalCaptureOptions): Promise<ScreenshotAttempt>;
455
581
  declare function captureScreenshot(html: string, viewport?: {
456
582
  width: number;
457
583
  height: number;
@@ -484,7 +610,7 @@ declare const VISUAL_JUDGE_MAX_OUTPUT_TOKENS = 4096;
484
610
  */
485
611
  declare const VISUAL_JUDGE_PROMPT_VERSION = "v2-bounded-issues";
486
612
  declare const VISUAL_JUDGE_PROMPT_DIGEST: string;
487
- declare function callMultimodalLLM(config: VisualEvalConfig, model: string, prompt: string, screenshot: Buffer, originalPrompt: string, profileBlock?: string): Promise<LLMResponse>;
613
+ declare function callMultimodalLLM(config: VisualEvalConfig, model: string, prompt: string, screenshot: Buffer, originalPrompt: string, profileBlock?: string, criteriaBlock?: string): Promise<LLMResponse>;
488
614
  /**
489
615
  * Run visual evaluation on a compiled component.
490
616
  *
@@ -512,6 +638,58 @@ declare function runVisualEvaluation(context: VisualEvalContext, config: VisualE
512
638
  declare function runVisualEvaluationDetailed(context: VisualEvalContext, config: VisualEvalConfig, deps?: VisualEvalDeps): Promise<VisualEvalDetailed>;
513
639
  /** The per-canvas verdicts without the PNGs — what the harness stamps on `EvalResult.visual`. */
514
640
  declare function summarizeVisualResult(result: VisualEvaluationResult): VisualEvalSummary | undefined;
641
+ /** One stored capture to judge: the frame the judge saw at capture time, plus what the capture measured. */
642
+ interface StoredCaptureInput {
643
+ readonly canvas: CanvasClass;
644
+ /** The capture as saved (`canvas-<class>.png`). */
645
+ readonly png: Buffer;
646
+ /** The box the capture was taken at — the class box, or the declared one. */
647
+ readonly viewport: CanvasViewport;
648
+ /** The document's scroll height the capture recorded; `null` when it did not. */
649
+ readonly contentHeight: number | null;
650
+ readonly originalPrompt: string;
651
+ readonly profile?: GenerationProfileInput;
652
+ /** ggui#1436 — the bank and the card's context; absent = today's judge, no block. */
653
+ readonly criteria?: {
654
+ readonly bank: CriteriaBank;
655
+ readonly context: CriteriaContextInput;
656
+ };
657
+ /** The props the capture was rendered with — handed to the criteria block for the rows whose evidence names props. */
658
+ readonly sampleProps?: JsonObject;
659
+ }
660
+ interface StoredCaptureVerdict {
661
+ readonly canvas: CanvasClass;
662
+ readonly viewport: CanvasViewport;
663
+ readonly score: number;
664
+ readonly passed: boolean;
665
+ readonly issues: EvaluationIssue[];
666
+ readonly judge: CanvasJudgeRecord;
667
+ readonly contentHeight: number | null;
668
+ readonly overflow: boolean;
669
+ readonly inkRatio: number | null;
670
+ readonly criteria?: CriteriaBlock;
671
+ /** The scoring calls' spend. */
672
+ readonly inputTokens: number;
673
+ readonly outputTokens: number;
674
+ /** ggui#1436 — the report-only criteria call's spend, apart from the scoring calls'; absent when none was asked or answered. */
675
+ readonly criteriaTokens?: CriteriaCallTokens;
676
+ }
677
+ type StoredCaptureOutcome = {
678
+ readonly kind: 'ok';
679
+ readonly verdict: StoredCaptureVerdict;
680
+ } | {
681
+ readonly kind: 'unavailable';
682
+ readonly reason: string;
683
+ };
684
+ /**
685
+ * Judge a STORED capture exactly as the per-canvas leg judges a fresh one — the same K scoring calls on the
686
+ * same frame, the same median, the same fit and blank verdicts, the same report-only criteria call — without
687
+ * rendering.
688
+ * This is the calibration's path (ggui#1438): the frame his eye marks is the frame the judge saw, and a
689
+ * re-judge costs judge tokens only. Fit reads the capture's recorded `contentHeight`; ink is read off the
690
+ * PNG inside the canvas's chrome, as at capture.
691
+ */
692
+ declare function judgeStoredCapture(input: StoredCaptureInput, config: VisualEvalConfig, deps?: Pick<VisualEvalDeps, 'judge'>): Promise<StoredCaptureOutcome>;
515
693
 
516
694
  /** What the harness's eval round consumes from the visual leg. */
517
695
  interface VisualEvalOutcome {
@@ -536,13 +714,113 @@ interface VisualEvalOutcome {
536
714
  */
537
715
  declare function runVisualEval(context: VisualEvalContext, config: VisualEvalConfig, deps?: VisualEvalDeps): Promise<VisualEvalOutcome>;
538
716
 
717
+ /** A channel difference at or below this is the same colour (anti-aliasing and compositing noise). */
718
+ declare const INK_TOLERANCE = 8;
719
+ interface PixelRegion {
720
+ readonly x: number;
721
+ readonly y: number;
722
+ readonly width: number;
723
+ readonly height: number;
724
+ }
725
+ interface InkExtent {
726
+ /** `(lastInkRow + 1) / region.height`, rounded to 3 places; `0` when nothing differs from the ground. */
727
+ readonly ratio: number;
728
+ /** The last region row (0-based from the region's top) carrying ink; `null` when there is none — the blank. */
729
+ readonly lastInkRow: number | null;
730
+ /** The region read, in image px. */
731
+ readonly region: PixelRegion;
732
+ /** The dominant colour the ink was read against, `[r, g, b]`. */
733
+ readonly ground: readonly [number, number, number];
734
+ }
735
+ /** Why a capture could not be read — reported, never mistaken for a blank. */
736
+ interface InkUnreadable {
737
+ readonly reason: string;
738
+ }
739
+ interface DecodedImage {
740
+ readonly width: number;
741
+ readonly height: number;
742
+ readonly channels: 3 | 4;
743
+ /** Row-major, `channels` bytes per pixel, scanline filters undone. */
744
+ readonly pixels: Uint8Array;
745
+ }
746
+ /** The PNG subset the judge's browser writes: 8-bit RGB (colour type 2) or RGBA (6), not interlaced. */
747
+ declare function decodePng(png: Uint8Array): DecodedImage | InkUnreadable;
748
+ /**
749
+ * The ink extent of a capture, read `insetPx` in from every edge — the judge's inset skips a host
750
+ * panel's gap, rounded corners and hairline ({@link JUDGE_INK_INSET_PX}); `0` reads the whole image.
751
+ */
752
+ declare function readInkExtent(png: Uint8Array, insetPx?: number): InkExtent | InkUnreadable;
753
+
539
754
  /**
540
755
  * The stylesheet a visual judge renders under for an app: the app's theme
541
756
  * composed the way the runtime composes it (`composeThemeCss`, layer `page`
542
757
  * — one composition, never a second), so a judged canvas paints the tokens a
543
- * visitor's page paints. Absent theme ⇒ the design's default tokens,
544
- * byte-for-byte what the judge used before.
758
+ * visitor's page paints. `themeId` is the registered ladder the app's theme
759
+ * sits on (the runtime's base layer); an unknown id composes the default
760
+ * ladder. Neither given ⇒ the design's default tokens, byte-for-byte what the
761
+ * judge used before.
762
+ */
763
+ declare function cssTokensForAppTheme(theme: AppTheme | undefined, mode?: 'light' | 'dark', themeId?: string): string;
764
+
765
+ /** Bump when a selection rule changes: it is hashed into every `criteriaSetId`. */
766
+ declare const CRITERIA_SELECTOR_VERSION = "selector@2";
767
+ /** The context as one string, keys sorted at every level — what the id hashes and what the record stores. */
768
+ declare function canonicalCriteriaContext(ctx: CriteriaContext): string;
769
+ /** sha256(bank version | selector version | canonical context), 16 hex — a label at this scale, not a security digest. */
770
+ declare function criteriaSetIdFor(bankVersion: string, ctx: CriteriaContext): string;
771
+ interface CriteriaSelectionResult {
772
+ readonly criteriaSetId: string;
773
+ readonly selection: CriteriaSelection[];
774
+ }
775
+ /**
776
+ * Select the bank's rows for one card. The bank-level `applies` gate is read first (canvases always;
777
+ * kind only when the caller named one and the bank names kinds other than `*`); then each row's
778
+ * `scope`. An empty scope is `static`; a matched scope is `context` with the keys that matched.
779
+ */
780
+ declare function selectCriteria(bank: CriteriaBank, ctx: CriteriaContext): CriteriaSelectionResult;
781
+
782
+ /**
783
+ * From K judge answers and the capture's measurements to one `CriteriaBlock` — ggui#1436.
784
+ *
785
+ * The judge is asked every `evaluation: judge` row (this block IS their implementation; the row's
786
+ * `status` is carried on the verdict as the author wrote it). An `instrument` row is answered by a
787
+ * measurement the capture already ran when its status is `live` and a binding exists; otherwise it
788
+ * reads `n/a` with the reason from `status`. A `human` row reads `n/a` for the judge. K-majority per
789
+ * id; a tie or an unanswered id reads `n/a` (the CTO's A2) — a `must` at `n/a` is never a pass when
790
+ * a gate later reads the set.
545
791
  */
546
- declare function cssTokensForAppTheme(theme: AppTheme | undefined, mode?: 'light' | 'dark'): string;
547
792
 
548
- export { CONTENT_HEIGHT_EXPRESSION, CanvasClass, type CanvasFitPolicy, CanvasJudgeRecord, CanvasViewport, type CanvasVisualResult, type CaptureMode, type ChromiumProvider, EvalIssue, type EvaluateScoreInput, EvaluationConfig, EvaluationContext, EvaluationIssue, type EvaluationLoopOptions, type EvaluationLoopResult, EvaluationResult, type JudgeDesignIdentity, QualityMetadata, type ScreenshotAttempt, type ScreenshotBrowser, type ScreenshotDeps, type ScreenshotLauncher, type ScreenshotPage, type SdkMessage, VISUAL_EVAL_PROMPT, VISUAL_JUDGE_MAX_OUTPUT_TOKENS, VISUAL_JUDGE_PROMPT_DIGEST, VISUAL_JUDGE_PROMPT_VERSION, type VisualEvalConfig, type VisualEvalContext, type VisualEvalDeps, type VisualEvalDetailed, type VisualEvalOutcome, VisualEvalSummary, type VisualEvaluationResult, buildFixPrompt, callMultimodalLLM, canvasFitPolicy, canvasOverflowIssue, captureScreenshot, captureScreenshotDetailed, computeEvaluationScore, createEvaluationToolsServer, cssTokensForAppTheme, designTreeSha256, extractCompiledCode, extractCompiledCodeFromMessage, extractEvalResult, extractSourceCode, extractSourceCodeFromMessage, extractToolResultTexts, getEvaluatorSystemPrompt, judgeDesignIdentity, resetJudgeDesignIdentityCache, resolveDesignPackageDir, resolveLaunchOptions, runEvaluation, runEvaluationLoop, runVisualEval, runVisualEvaluation, runVisualEvaluationDetailed, summarizeVisualResult };
793
+ /** The instruments the capture runs today, by the bank ids they answer (v1 binding; a bank field may replace it). */
794
+ declare const INSTRUMENT_BY_ID: Readonly<Record<string, 'fit' | 'fill'>>;
795
+ interface CriteriaMeasurements {
796
+ readonly overflow: boolean;
797
+ readonly contentHeight: number | null;
798
+ readonly viewportHeight: number;
799
+ readonly inkRatio: number | null;
800
+ }
801
+ declare function resolveCriteriaBlock(args: {
802
+ readonly bank: CriteriaBank;
803
+ readonly context: CriteriaContext;
804
+ readonly selected: CriteriaSelectionResult;
805
+ readonly answers: readonly CriteriaAnswer[][];
806
+ readonly measurements: CriteriaMeasurements;
807
+ }): CriteriaBlock;
808
+ /** The judge's prompt block for the selected `judge` rows; empty when none is selected. */
809
+ /** The capture the judge is handed: its canvas class and the box it was taken at (the class box, or a declared one). */
810
+ interface CriteriaJudgeFrame {
811
+ readonly canvas: CriteriaContext['canvas'];
812
+ readonly width: number;
813
+ readonly height: number;
814
+ /** ggui#1492 — the host whose presentation framed this canvas (e.g. "a chat widget, inline, reference theme"); absent ⇒ the judge's own stand-in. */
815
+ readonly hostLabel?: string;
816
+ }
817
+ /** What the block carries besides the selected rows: the frame's box, and the props the card was rendered with. */
818
+ interface CriteriaJudgeInputs {
819
+ readonly frame?: CriteriaJudgeFrame;
820
+ /** JSON text of the props the card was rendered with; bounded by {@link CRITERIA_PROPS_MAX_CHARS}. */
821
+ readonly propsJson?: string;
822
+ }
823
+ /** The judge's prompt block for the selected `judge` rows; empty when none is selected. */
824
+ declare function buildCriteriaJudgeBlock(bank: CriteriaBank, selected: CriteriaSelectionResult, inputs?: CriteriaJudgeInputs): string;
825
+
826
+ export { CARD_HEIGHT_EXPRESSION, CONTENT_HEIGHT_EXPRESSION, CRITERIA_SELECTOR_VERSION, CanvasClass, type CanvasFitPolicy, CanvasHostPresentation, CanvasJudgeRecord, CanvasPresentationOutcome, CanvasViewport, type CanvasVisualResult, type CaptureMode, type ChromiumProvider, CriteriaBank, type CriteriaCallTokens, type CriteriaContextInput, type CriteriaContextSources, type CriteriaMeasurements, type CriteriaSelectionResult, type DecodedImage, EvalIssue, type EvaluateScoreInput, EvaluationConfig, EvaluationContext, EvaluationIssue, type EvaluationLoopOptions, type EvaluationLoopResult, EvaluationResult, HOST_COLOUR_PATTERN, HOST_FRAME_BOUNDS, INK_TOLERANCE, INSTRUMENT_BY_ID, type InkExtent, type InkUnreadable, JUDGE_GROUND_MARGIN_PX, JUDGE_INK_INSET_PX, type JudgeDesignIdentity, type NaturalCaptureOptions, type PixelRegion, QualityMetadata, type ScreenshotAttempt, type ScreenshotBrowser, type ScreenshotClip, type ScreenshotDeps, type ScreenshotLauncher, type ScreenshotPage, type SdkMessage, type StoredCaptureInput, type StoredCaptureOutcome, type StoredCaptureVerdict, VISUAL_EVAL_PROMPT, VISUAL_JUDGE_MAX_OUTPUT_TOKENS, VISUAL_JUDGE_PROMPT_DIGEST, VISUAL_JUDGE_PROMPT_VERSION, type VisualEvalConfig, type VisualEvalContext, type VisualEvalDeps, type VisualEvalDetailed, type VisualEvalOutcome, VisualEvalSummary, type VisualEvaluationResult, buildCriteriaJudgeBlock, buildFixPrompt, callMultimodalLLM, canonicalCriteriaContext, canvasBlankIssue, canvasFitPolicy, canvasOverflowIssue, captureScreenshot, captureScreenshotDetailed, chromaOfCssTokens, computeEvaluationScore, createEvaluationToolsServer, criteriaContextFor, criteriaSetIdFor, cssTokensForAppTheme, decodePng, designTreeSha256, extractCompiledCode, extractCompiledCodeFromMessage, extractEvalResult, extractSourceCode, extractSourceCodeFromMessage, extractToolResultTexts, getEvaluatorSystemPrompt, judgeDesignIdentity, judgeStoredCapture, readInkExtent, resetJudgeDesignIdentityCache, resolveCriteriaBlock, resolveDesignPackageDir, resolveLaunchOptions, runEvaluation, runEvaluationLoop, runVisualEval, runVisualEvaluation, runVisualEvaluationDetailed, selectCriteria, summarizeVisualResult };