@penpair/core 0.3.5 → 0.3.7
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.
- package/dist/approvals.js +6 -4
- package/dist/baseline-coverage.js +2 -2
- package/dist/baselines.js +2 -3
- package/dist/design-viewport.d.ts +3 -0
- package/dist/design-viewport.js +9 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/skills/penpair-verify/references/browser-evidence.md +1 -1
package/dist/approvals.js
CHANGED
|
@@ -2,6 +2,7 @@ import { createHash, randomUUID } from "node:crypto";
|
|
|
2
2
|
import { mkdir, open, readFile, stat, unlink } from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { atomicWriteFile } from "./atomic-output.js";
|
|
5
|
+
import { matchesDesignViewport } from "./design-viewport.js";
|
|
5
6
|
import { observationHash } from "./journal.js";
|
|
6
7
|
import { resolveProjectInput, resolveProjectOutput } from "./project-input.js";
|
|
7
8
|
import { validateBaselineCase } from "./baselines-config.js";
|
|
@@ -100,7 +101,8 @@ export async function recordApproval(root, exported, words, intent, redact) {
|
|
|
100
101
|
words = {
|
|
101
102
|
...words,
|
|
102
103
|
};
|
|
103
|
-
|
|
104
|
+
const imageSize = pngSize(exported.png);
|
|
105
|
+
if (!exported.stable || !imageSize) {
|
|
104
106
|
throw new Error("Approval requires a stable independently exported PNG");
|
|
105
107
|
}
|
|
106
108
|
if (typeof words.note !== "string" ||
|
|
@@ -114,9 +116,9 @@ export async function recordApproval(root, exported, words, intent, redact) {
|
|
|
114
116
|
const sha256 = artifactSha(exported.png);
|
|
115
117
|
const fingerprint = approvalFingerprint(exported.capture, sha256, intent);
|
|
116
118
|
if (intent &&
|
|
117
|
-
(!exported.capture.designSize ||
|
|
118
|
-
|
|
119
|
-
|
|
119
|
+
(!matchesDesignViewport(exported.capture.designSize, intent.viewport) ||
|
|
120
|
+
imageSize.width !== Math.round(intent.viewport.width * exported.capture.scale) ||
|
|
121
|
+
imageSize.height !== Math.round(intent.viewport.height * exported.capture.scale) ||
|
|
120
122
|
(intent.activeThemeIds &&
|
|
121
123
|
observationHash([
|
|
122
124
|
...(exported.capture.activeThemeIds ?? []),
|
|
@@ -3,6 +3,7 @@ import path from "node:path";
|
|
|
3
3
|
import { createHash } from "node:crypto";
|
|
4
4
|
import { resolveProjectOutput } from "./project-input.js";
|
|
5
5
|
import { pngSize } from "./png.js";
|
|
6
|
+
import { matchesDesignViewport } from "./design-viewport.js";
|
|
6
7
|
import { validateBaselines, } from "./baselines-config.js";
|
|
7
8
|
import { observationHash } from "./journal.js";
|
|
8
9
|
export const designCaseKey = (route, value) => observationHash({
|
|
@@ -75,8 +76,7 @@ export function baselineCoverage(config, results = []) {
|
|
|
75
76
|
(!result.captured ||
|
|
76
77
|
(evidence.fileId === result.captured.fileId &&
|
|
77
78
|
evidence.pageId === result.captured.pageId)) &&
|
|
78
|
-
evidence.designSize
|
|
79
|
-
evidence.designSize?.height === frame.case.viewport.height &&
|
|
79
|
+
matchesDesignViewport(evidence.designSize, frame.case.viewport) &&
|
|
80
80
|
result.imageWidth === Math.round(frame.case.viewport.width * evidence.scale) &&
|
|
81
81
|
result.imageHeight === Math.round(frame.case.viewport.height * evidence.scale) &&
|
|
82
82
|
(!frame.case.activeThemeIds ||
|
package/dist/baselines.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { matchingApproval } from "./approvals.js";
|
|
2
|
+
import { matchesDesignViewport } from "./design-viewport.js";
|
|
2
3
|
import { pngSize } from "./png.js";
|
|
3
4
|
export { pngSize } from "./png.js";
|
|
4
5
|
import { createHash, randomUUID } from "node:crypto";
|
|
@@ -180,9 +181,7 @@ export async function exportBaselines(client, projectRoot, config, options = {})
|
|
|
180
181
|
if (wanted.case) {
|
|
181
182
|
const viewport = wanted.case.viewport;
|
|
182
183
|
const size = pngSize(exported.png);
|
|
183
|
-
if (!exported.capture.designSize
|
|
184
|
-
exported.capture.designSize.width !== viewport.width ||
|
|
185
|
-
exported.capture.designSize.height !== viewport.height) {
|
|
184
|
+
if (!matchesDesignViewport(exported.capture.designSize, viewport)) {
|
|
186
185
|
caseProblems.push("Observed frame dimensions do not match the declared viewport");
|
|
187
186
|
}
|
|
188
187
|
if (size.width !== Math.round(viewport.width * exported.capture.scale) ||
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { BaselineCase } from "./baselines-config.js";
|
|
2
|
+
/** Penpot transforms can introduce subpixel noise; exported image dimensions remain exact. */
|
|
3
|
+
export declare function matchesDesignViewport(designSize: BaselineCase["viewport"] | undefined, viewport: BaselineCase["viewport"]): boolean;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
const designSizeTolerancePx = 0.01;
|
|
2
|
+
/** Penpot transforms can introduce subpixel noise; exported image dimensions remain exact. */
|
|
3
|
+
export function matchesDesignViewport(designSize, viewport) {
|
|
4
|
+
return Boolean(designSize &&
|
|
5
|
+
Number.isFinite(designSize.width) &&
|
|
6
|
+
Number.isFinite(designSize.height) &&
|
|
7
|
+
Math.abs(designSize.width - viewport.width) < designSizeTolerancePx &&
|
|
8
|
+
Math.abs(designSize.height - viewport.height) < designSizeTolerancePx);
|
|
9
|
+
}
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** Kept in its own file so that the command line and the library entry can both read it without importing each other. Equals package.json (a test checks). */
|
|
2
|
-
export declare const version = "0.3.
|
|
2
|
+
export declare const version = "0.3.7";
|
package/dist/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** Kept in its own file so that the command line and the library entry can both read it without importing each other. Equals package.json (a test checks). */
|
|
2
|
-
export const version = "0.3.
|
|
2
|
+
export const version = "0.3.7";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@penpair/core",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.7",
|
|
4
4
|
"description": "Design together. Build together. The library and engine behind penpair: connect AI agents and people to a Penpot design file, safely. Install @penpair/web or @penpair/docker for the command.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -15,7 +15,7 @@ browser dependency and working provider are still required in the project.
|
|
|
15
15
|
|
|
16
16
|
Before claiming a comparison, retain the case ID, approved reference/hash, setup
|
|
17
17
|
name, provider identity/version and actual browser observation. Check viewport,
|
|
18
|
-
theme, state, fixture, loaded fonts,
|
|
18
|
+
theme, state, fixture, loaded fonts, image dimensions and scale (PNG or static lossless WebP). Missing state
|
|
19
19
|
hooks, placeholder routes or echoed test inputs leave verification pending.
|
|
20
20
|
Inspect pointer/hover, scroll/sticky behavior, occlusion and capture-root bounds
|
|
21
21
|
when they can explain a mismatch. Do not hide them by changing the reference.
|