@penpair/web 0.1.3 → 0.3.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.
- package/README.md +38 -237
- package/docs/adapters.md +83 -0
- package/docs/approvals.md +19 -0
- package/docs/artifacts.md +13 -0
- package/docs/audits.md +13 -0
- package/docs/backup.md +54 -0
- package/docs/branch-review.md +59 -0
- package/docs/build-kit.md +59 -0
- package/docs/command-contract.md +27 -0
- package/docs/compatibility.md +46 -0
- package/docs/conventions/README.md +63 -0
- package/docs/conventions/completion-2026-10-22.md +73 -0
- package/docs/conventions/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
- package/docs/conventions/plugin-code.md +23 -0
- package/docs/conventions/structure.md +48 -0
- package/docs/conventions/templates/adapter-command.ts +28 -0
- package/docs/conventions/templates/conventions.test.ts +81 -0
- package/docs/conventions/templates/frame-inspection.ts +27 -0
- package/docs/conventions/templates/frame-label.ts +15 -0
- package/docs/conventions/tsconfig.json +13 -0
- package/docs/conventions/typescript.md +59 -0
- package/docs/conventions/vitest.config.ts +11 -0
- package/docs/cookbook.md +25 -0
- package/docs/coverage.md +50 -0
- package/docs/credentials.md +27 -0
- package/docs/design-workflow.md +13 -0
- package/docs/extensions-trust.md +13 -0
- package/docs/fixtures/browser-capture-2026-10-22.json +217 -0
- package/docs/fixtures/feedback-reproductions.md +12 -0
- package/docs/fixtures/feedback-scratch.template.json +9 -0
- package/docs/formats.md +22 -0
- package/docs/getting-started.md +12 -2
- package/docs/guide.md +83 -9
- package/docs/handoff.md +34 -0
- package/docs/improvements.md +1217 -0
- package/docs/inspection.md +38 -0
- package/docs/layout-settling.md +13 -0
- package/docs/marwes-components.md +34 -0
- package/docs/marwes-tokens.md +59 -2
- package/docs/marwes.md +9 -0
- package/docs/mcp.md +40 -0
- package/docs/mode-verification.md +35 -0
- package/docs/plans/registry-polling-fix.md +101 -0
- package/docs/plans/tradient-feedback-0.2.0.md +209 -0
- package/docs/plans/tradient-feedback-review.md +83 -0
- package/docs/pr-improvements.md +57 -0
- package/docs/recovery.md +33 -0
- package/docs/releasing.md +172 -22
- package/docs/run-file.md +71 -0
- package/docs/shots.md +15 -0
- package/docs/skill-installation.md +16 -0
- package/docs/snapshots.md +20 -0
- package/docs/status.md +7 -0
- package/docs/team.md +17 -0
- package/docs/theme-previews.md +18 -0
- package/docs/token-editing.md +22 -0
- package/docs/tradient-followups.md +77 -0
- package/docs/trials/report-template.json +76 -0
- package/docs/trials.md +41 -0
- package/docs/troubleshooting.md +26 -0
- package/docs/upstream/marwes-1.11.0-evidence.json +15 -0
- package/docs/upstream/marwes-requests.md +35 -0
- package/examples/component-pilot/renderer.mjs +100 -0
- package/examples/coverage-matrix.json +126 -0
- package/examples/hello-card/README.md +18 -0
- package/examples/hello-card/build.js +24 -0
- package/examples/hello-card/helpers.js +27 -0
- package/examples/hello-card/inspect.js +4 -0
- package/examples/hello-card/readback.js +3 -0
- package/examples/reflection-browser/README.md +49 -0
- package/examples/reflection-browser/capture.mjs +311 -0
- package/examples/reflection-browser/fixture/Abel-Regular.ttf +0 -0
- package/examples/reflection-browser/fixture/OFL.txt +93 -0
- package/examples/reflection-browser/fixture/index.html +11 -0
- package/examples/reflection-browser/fixture-hooks.mjs +24 -0
- package/examples/reflection-browser/provider.mjs +90 -0
- package/examples/reflection-browser/serve.mjs +37 -0
- package/examples/theme-preview/README.md +21 -0
- package/examples/theme-preview/apply.js +8 -0
- package/examples/theme-preview/helpers.js +12 -0
- package/examples/theme-preview/inspect.js +3 -0
- package/examples/theme-preview/readback.js +7 -0
- package/examples/trials/hold-inspect.js +5 -0
- package/examples/trials/hold-readback.js +8 -0
- package/examples/trials/hold-writer.js +16 -0
- package/examples/trials/recovery-build.js +23 -0
- package/examples/trials/recovery-inspect.js +10 -0
- package/examples/trials/recovery-readback.js +7 -0
- package/examples/trials/wrong-file-read.js +3 -0
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -1,258 +1,59 @@
|
|
|
1
|
-
|
|
2
|
-
<img src="https://raw.githubusercontent.com/niklas-westman/penpair/main/docs/assets/logo.png" alt="penpair" width="120" height="120">
|
|
3
|
-
</p>
|
|
1
|
+
# penpair
|
|
4
2
|
|
|
5
|
-
|
|
3
|
+
**Design together. Build together.** Connect people and agents to the same Penpot design, with pinned targets, recoverable writes and independent readback.
|
|
6
4
|
|
|
7
|
-
|
|
5
|
+
Inspect structure and tokens, compose reviewed recipes, capture references and hand design evidence to the implementation. Penpot holds the design; Git holds declarations, snapshots and review records.
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
One command connects your AI coding assistant to your <a href="https://penpot.app">Penpot</a> design file,<br>
|
|
11
|
-
so people and agents work on the same design, safely and repeatably.
|
|
12
|
-
</p>
|
|
7
|
+
**Design in Penpot → hand off to frontend code → check the implementation.** Add the companion adapters for the parts of that workflow your project uses:
|
|
13
8
|
|
|
14
|
-
|
|
15
|
-
<a href="https://www.npmjs.com/package/@penpair/web"><img alt="npm" src="https://img.shields.io/npm/v/@penpair/web?color=0A5CFF&label=%40penpair%2Fweb"></a>
|
|
16
|
-
<a href="https://github.com/niklas-westman/penpair/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/niklas-westman/penpair/actions/workflows/ci.yml/badge.svg"></a>
|
|
17
|
-
<a href="https://github.com/niklas-westman/penpair/blob/main/LICENSE"><img alt="MIT licence" src="https://img.shields.io/badge/licence-MIT-0A5CFF"></a>
|
|
18
|
-
<img alt="Node 22 or later" src="https://img.shields.io/badge/node-%E2%89%A522-0A5CFF">
|
|
19
|
-
</p>
|
|
20
|
-
|
|
21
|
-
<p align="center">
|
|
22
|
-
<a href="#start-here-the-setup-guide"><strong>Start here</strong></a> ·
|
|
23
|
-
<a href="#why-penpair">Why</a> ·
|
|
24
|
-
<a href="#quick-start">Quick start</a> ·
|
|
25
|
-
<a href="#web-or-docker">Web or Docker</a> ·
|
|
26
|
-
<a href="#packages">Packages</a> ·
|
|
27
|
-
<a href="#use-it-with-marwes">Marwes</a> ·
|
|
28
|
-
<a href="#check-each-page-with-reflection">Reflection</a> ·
|
|
29
|
-
<a href="#for-an-ai-agent">For an AI agent</a>
|
|
30
|
-
</p>
|
|
31
|
-
|
|
32
|
-
---
|
|
33
|
-
|
|
34
|
-
penpair makes a Penpot design file the **source of truth** for your project's UI, and makes your AI assistant dependable at working in it. Prompt for a whole page; the assistant reads the real design, builds with tested operations that look first, write once and read back, and follows written-down rules for how to work in Penpot. You review the result in Penpot as usual, and [Reflection](#check-each-page-with-reflection) can check the page it later builds in code against the design.
|
|
35
|
-
|
|
36
|
-
| | |
|
|
37
|
-
| --- | --- |
|
|
38
|
-
| **Connect it** | Point it at Penpot on the web, or your own, with one guided command and a check that it works. |
|
|
39
|
-
| **Drive it** | Inspect, build, audit, export, archive and manage design tokens through Penpot's MCP and plugin API. |
|
|
40
|
-
| **Know it** | The rules and the quirks of the tool ship with the code as skills your agent follows. |
|
|
41
|
-
| **Extend it** | Plug in your component library, your checks and your own snippets. The core stays neutral. |
|
|
42
|
-
|
|
43
|
-
## Start here: the setup guide
|
|
44
|
-
|
|
45
|
-
The easiest way in is to let your AI assistant walk you through it. **[penpair-setup-guide](https://github.com/niklas-westman/penpair/blob/main/skills/penpair-setup-guide/SKILL.md)** is a skill for Claude Code, Codex and GitHub Copilot that guides you from nothing to a first design, one step at a time:
|
|
46
|
-
|
|
47
|
-
1. checks Node and your project,
|
|
48
|
-
2. asks whether Penpot runs **on the web** (recommended) or **in Docker** on your computer,
|
|
49
|
-
3. helps you get a Penpot account and a design file,
|
|
50
|
-
4. installs penpair and connects the Penpot plugin,
|
|
51
|
-
5. shows you **where your MCP link goes**, without the key ever passing through the chat, and verifies it all with `doctor`,
|
|
52
|
-
6. asks whether you want **Marwes UI** tokens in Penpot,
|
|
53
|
-
7. installs the rules your assistant follows,
|
|
54
|
-
8. and ends with a **test POC** on its own page, so you see what it can do.
|
|
55
|
-
|
|
56
|
-
**No install needed:** in your project's folder, tell your assistant:
|
|
57
|
-
|
|
58
|
-
> Read https://raw.githubusercontent.com/niklas-westman/penpair/main/skills/penpair-setup-guide/SKILL.md and follow it to set up penpair in this project.
|
|
59
|
-
|
|
60
|
-
**Or install it as a skill** in your project, so it is there next time (also the way to go if your assistant cannot open web pages):
|
|
61
|
-
|
|
62
|
-
```bash
|
|
63
|
-
# Claude Code
|
|
64
|
-
mkdir -p .claude/skills/penpair-setup-guide && curl -fsSL https://raw.githubusercontent.com/niklas-westman/penpair/main/skills/penpair-setup-guide/SKILL.md -o .claude/skills/penpair-setup-guide/SKILL.md
|
|
65
|
-
# Codex
|
|
66
|
-
mkdir -p .agents/skills/penpair-setup-guide && curl -fsSL https://raw.githubusercontent.com/niklas-westman/penpair/main/skills/penpair-setup-guide/SKILL.md -o .agents/skills/penpair-setup-guide/SKILL.md
|
|
67
|
-
# GitHub Copilot
|
|
68
|
-
mkdir -p .github/skills/penpair-setup-guide && curl -fsSL https://raw.githubusercontent.com/niklas-westman/penpair/main/skills/penpair-setup-guide/SKILL.md -o .github/skills/penpair-setup-guide/SKILL.md
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
Then ask: *"set up penpair"*. Prefer to do it yourself? Read on: [Quick start](#quick-start).
|
|
72
|
-
|
|
73
|
-
## Why penpair
|
|
74
|
-
|
|
75
|
-
An AI assistant can already reach Penpot through its MCP server: it gets one tool that runs code inside your open file. That is power without hands-on knowledge, and designing a whole page that way fails in small, expensive ways. penpair is what makes it dependable, so you can prompt for a page and get a page.
|
|
76
|
-
|
|
77
|
-
**What goes wrong with a bare connection**, all met while building real pages:
|
|
78
|
-
|
|
79
|
-
- The first export after a change is often a stale render, so the assistant "sees" a defect that is not there, or misses one that is.
|
|
80
|
-
- A token binding appears seconds after the call, so a correct write reads back as "not bound", and applying the same token twice removes it.
|
|
81
|
-
- A request over about 110 KB is refused, a switched page takes effect only after the script ends, and a sleeping browser tab raises an error even though the write already landed.
|
|
82
|
-
- Every new session rediscovers these, and a plain write cannot tell "done" from "half done".
|
|
83
|
-
|
|
84
|
-
**What penpair adds:**
|
|
85
|
-
|
|
86
|
-
| | What you get | Why it matters for a full page |
|
|
9
|
+
| Companion | When to add it | What it helps with |
|
|
87
10
|
| --- | --- | --- |
|
|
88
|
-
|
|
|
89
|
-
|
|
|
90
|
-
| **Stable exports and an audit** | Exports that wait for a stable render; a check for unbound colours, spacing off your scale, overflow and blank text | The assistant can judge its own page and show you evidence |
|
|
91
|
-
| **One-command setup and `doctor`** | A connection that is checked, a key that never leaves your machine, an agent-readable `doctor --json` | A new teammate or a new agent is productive in minutes |
|
|
11
|
+
| [Marwes UI adapter](docs/adapters.md#bring-your-component-library-into-penpot) | Your application uses Marwes UI | Bring library/project tokens into Penpot, detect drift and compose library-aware recipes |
|
|
12
|
+
| [Reflection Check adapter](docs/adapters.md#check-the-frontend-against-the-design) | You implement a frontend from Penpot and want repeatable visual checks | Connect approved design cases to real browser captures and comparison evidence |
|
|
92
13
|
|
|
93
|
-
**
|
|
14
|
+
**Reflection Check is the recommended companion for design-to-frontend verification.** Install it explicitly alongside your command package. It needs approved references and a project browser provider; the [adapter guide](docs/adapters.md) shows installation, registration and readiness steps.
|
|
94
15
|
|
|
95
|
-
|
|
16
|
+
## Choose your path
|
|
96
17
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
18
|
+
| You want to… | Start here |
|
|
19
|
+
| --- | --- |
|
|
20
|
+
| Set up your first project | [Getting started](docs/getting-started.md) |
|
|
21
|
+
| Let an agent guide setup | [Setup guide skill](skills/penpair-setup-guide/SKILL.md) |
|
|
22
|
+
| Join a shared file | [Team guide](docs/team.md) |
|
|
23
|
+
| Build and review a page | [Design workflow](docs/design-workflow.md) |
|
|
24
|
+
| Choose adapters or check the frontend | [Companion adapters](docs/adapters.md) |
|
|
25
|
+
| Resolve a failure | [Troubleshooting](docs/troubleshooting.md) |
|
|
26
|
+
| Extend the framework | [Guide and reference map](docs/guide.md) |
|
|
100
27
|
|
|
101
28
|
## Quick start
|
|
102
29
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
You need [Node.js](https://nodejs.org) 22 or later and a terminal. In your project's folder:
|
|
106
|
-
|
|
107
|
-
```bash
|
|
108
|
-
npx @penpair/web setup
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
(`@penpair/web` is the package for Penpot on the web; the command it installs is called `penpair`. A shorter `npx penpair` is coming once npm allows the name. For Penpot in Docker on your computer, see [Web or Docker](#web-or-docker).)
|
|
112
|
-
|
|
113
|
-
It asks where your Penpot is and does the rest, saying in plain words what it is doing and what it is waiting for:
|
|
114
|
-
|
|
115
|
-
1. writes a small config you can commit (`penpair.config.json`, no secrets),
|
|
116
|
-
2. takes your personal key **without showing it** and keeps it in a git-ignored `.env.local`,
|
|
117
|
-
3. waits while you connect the plugin in your browser (**File, MCP Server, Connect**),
|
|
118
|
-
4. reads your file once to prove it works,
|
|
119
|
-
5. installs the rules your AI assistant follows.
|
|
120
|
-
|
|
121
|
-
Run it again any time; it continues where it stopped. `npx @penpair/web doctor` tells you what works, what does not and what to do about it.
|
|
122
|
-
|
|
123
|
-
Then commit what it made (never `.env.local`; it is already git-ignored):
|
|
124
|
-
|
|
125
|
-
```bash
|
|
126
|
-
git add penpair.config.json .gitignore .skills .agents .claude
|
|
127
|
-
git commit -m "Add penpair"
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
Each teammate runs their own `npx @penpair/web connect`: the key belongs to a person, not to the repo. To pin penpair for the team, add it as a dev dependency (`npm i -D @penpair/web`, or `@penpair/docker`; one of the two, not both); the command is then `npx penpair …`. To write your own Penpot operations, use the library from the same package: `import { defineSnippet } from "@penpair/web"`.
|
|
131
|
-
|
|
132
|
-
## Web or Docker
|
|
30
|
+
Use Node 22 or newer, your project folder and a visible Penpot editor. Enter the personal MCP address only in the private connection prompt.
|
|
133
31
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
| Backup | Penpot's version history and its `.penpot` export | `penpair backup`, `backup verify`, `restore` |
|
|
142
|
-
| Set it up | `npx @penpair/web setup --web` | `npx @penpair/docker setup --docker` (or `npm i -D @penpair/docker`, then `npx penpair setup --docker`) |
|
|
143
|
-
|
|
144
|
-
The full comparison, what is checked and how to switch: **[Web or Docker →](https://github.com/niklas-westman/penpair/blob/main/packages/core/skills/penpair-setup/references/web-or-docker.md)**
|
|
145
|
-
|
|
146
|
-
## Packages
|
|
147
|
-
|
|
148
|
-
| Package | What it is | Status |
|
|
149
|
-
| --- | --- | --- |
|
|
150
|
-
| [`@penpair/web`](https://www.npmjs.com/package/@penpair/web) | The `penpair` command for Penpot on the web. Includes everything in the core | Published |
|
|
151
|
-
| [`@penpair/docker`](https://www.npmjs.com/package/@penpair/docker) | The same command, plus Penpot in Docker on your computer: `up`, `down`, `backup`, `restore`. Includes everything in the core | Published |
|
|
152
|
-
| [`@penpair/core`](https://www.npmjs.com/package/@penpair/core) | The library and engine, with the skills. No command of its own; the two above are built on it | Published |
|
|
153
|
-
| `penpair` | The short name for `@penpair/web`, so that `npx penpair setup` works | Waiting for npm to allow the name (it is blocked as too close to an unrelated package). Until then use `npx @penpair/web`. |
|
|
154
|
-
| [`@penpair/marwes-ui`](https://www.npmjs.com/package/@penpair/marwes-ui) | The adapter for the Marwes UI component library: Marwes tokens (and your theme) in Penpot, with drift checks | Published: tokens now, components planned. See below |
|
|
155
|
-
| `@penpair/reflection-check` | The link to Reflection's `reflection-check`, as its own package (today `penpair baselines` does it) | Planned |
|
|
156
|
-
|
|
157
|
-
You install **one** command package, `@penpair/web` or `@penpair/docker`; the core comes with it.
|
|
158
|
-
|
|
159
|
-
## Use it with Marwes
|
|
160
|
-
|
|
161
|
-
Using [Marwes UI](https://marwes.io), the themeable component library for React, Vue and Svelte? Connecting Marwes is the recommended setup: your Penpot file then speaks the same tokens as your code, so what is designed is what gets built.
|
|
162
|
-
|
|
163
|
-
```bash
|
|
164
|
-
npm i -D @penpair/marwes-ui
|
|
165
|
-
npx penpair marwes tokens snapshot --write # the expected tokens, from the installed Marwes and your own theme
|
|
166
|
-
npx penpair marwes tokens push --apply # Penpot gets them: Marwes sets, plus a small overlay of what your theme changes
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
The part that keeps it solid is drift: a Marwes upgrade, a theme edit or a hand edit in Penpot is found, not discovered later. `penpair marwes tokens check` runs offline in CI and fails when the committed snapshot no longer matches the installed Marwes; `diff` shows what Penpot lacks and how many shapes each changed token reaches. How it works and how to put it in CI: [Marwes tokens in Penpot, and keeping them true](https://github.com/niklas-westman/penpair/blob/main/docs/marwes-tokens.md). Marwes components in Penpot are not covered yet; they are built as your pages need them.
|
|
170
|
-
|
|
171
|
-
## Check each page with Reflection
|
|
172
|
-
|
|
173
|
-
Designing a page is half the job; the other half is knowing the assistant built what the design says. We recommend pairing penpair with [Reflection](https://github.com/niklas-westman/reflection) (`reflection-check` on npm), which renders your real UI in a browser and compares it with an approved image, state by state, and shows you the difference.
|
|
174
|
-
|
|
175
|
-
```
|
|
176
|
-
prompt ──▶ the assistant designs the page in Penpot ──▶ penpair export ──▶ an approved image per page and state
|
|
177
|
-
│
|
|
178
|
-
you review ◀── Reflection: the rendered page against that image, with a diff ◀── the assistant builds the page in code
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
Why this pairing helps:
|
|
182
|
-
|
|
183
|
-
- **The design is the reference, not the assistant's memory.** The exported frame is what the delivery is measured against, so a misreading of the design shows up as a visible difference, not as a surprise in review.
|
|
184
|
-
- **Each page and state is one piece of evidence.** You look at a diff for the list, the open card, the empty state, the phone variant, instead of re-reading the whole change.
|
|
185
|
-
- **Nothing passes on a promise.** Reflection is review-first: a mismatch is shown to you, and an approved image only changes when you say so.
|
|
186
|
-
|
|
187
|
-
**The hand-off is one config block and one command.** List the frames of a page that are the design of a route, in `penpair.config.json`:
|
|
188
|
-
|
|
189
|
-
```json
|
|
190
|
-
"baselines": {
|
|
191
|
-
"page": "Candidate",
|
|
192
|
-
"root": "tests/baselines",
|
|
193
|
-
"frames": [
|
|
194
|
-
{ "frame": "F / candidates", "id": "candidates-desktop", "route": "candidates" },
|
|
195
|
-
{ "frame": "F tablet / candidates", "id": "candidates-tablet", "route": "candidates" }
|
|
196
|
-
]
|
|
197
|
-
}
|
|
32
|
+
```sh
|
|
33
|
+
pnpm add -D @penpair/web
|
|
34
|
+
pnpm exec penpair init --external https://design.penpot.app --gitignore
|
|
35
|
+
pnpm exec penpair connect
|
|
36
|
+
pnpm exec penpair connect --pin-file
|
|
37
|
+
pnpm exec penpair doctor --json
|
|
38
|
+
pnpm exec penpair skills install --dry-run
|
|
198
39
|
```
|
|
199
40
|
|
|
200
|
-
|
|
201
|
-
npx @penpair/web baselines # look: which images are new, the same, or changed in the design
|
|
202
|
-
npx @penpair/web baselines --apply # write the new images, a manifest and reflection-cases.json
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
penpair exports each frame at a stable render, writes `tests/baselines/<id>.png`, and generates the Reflection cases for you: each frame's exact size becomes the viewport, so the capture and the reference have the same dimensions, and each check carries `ref: "penpair:<id>"` to join it back to the frame. In your `reflection.config.ts` you add the generated viewports to the route and spread the generated `visualSmoke` into the browser contract (a working example is in the [guide](https://github.com/niklas-westman/penpair/blob/main/docs/guide.md#baselines-for-a-check)), then run `npx reflection run --config reflection.config.ts --mode smoke`.
|
|
206
|
-
|
|
207
|
-
A changed design is never silently approved: when a frame no longer matches its image, `penpair baselines` says `changed` and leaves the image alone until you run `--apply --update`, which is the act of approving the new design. We ran this chain end to end (Penpot frame, `penpair baselines`, Reflection, browser, diff) and the check, its diff image and its `ref` all came out right.
|
|
208
|
-
|
|
209
|
-
One thing to know before you rely on it: the percentage is not a verdict. A correct implementation already differs from a Penpot render by about 1 to 2% on text alone (fonts, anti-aliasing), and a faint colour shift or a one-line copy change can sit below that. Read the diff image and Reflection's diagnostics; they point at the likely cause. What is still planned is the richer link, where each page's states are read from Penpot and shown in Reflection's own viewer (through `reflection-projection`, already tried on a real page of 30 states).
|
|
210
|
-
|
|
211
|
-
## For an AI agent
|
|
41
|
+
Confirm the owner-authorized file ID, then follow the [skill installation preview](docs/skill-installation.md). Each teammate uses their own key. Prefer a team/web Penpot; [Docker is an alternative](packages/core/skills/penpair-setup/references/web-or-docker.md).
|
|
212
42
|
|
|
213
|
-
|
|
43
|
+
Use the installed version's `--help` to confirm available commands. For an unreleased source trial, install the complete matching package set described in the [trial runbook](docs/trials.md). Live/human acceptance gates remain explicit.
|
|
214
44
|
|
|
215
|
-
|
|
216
|
-
- Web is the default; Docker only when the person asks for offline work or local data.
|
|
217
|
-
- **The personal MCP key never goes through you.** The person pastes it into `npx @penpair/web connect` (a hidden prompt), or pipes it from their clipboard.
|
|
218
|
-
- Done means `doctor` reports `ok: true` and "editor and plugin" connected. Then `skills install` gives you the rules for working in Penpot (`penpair-design`) and for judging a screen (`design-judgment`).
|
|
45
|
+
## Packages and workflows
|
|
219
46
|
|
|
220
|
-
|
|
47
|
+
Install one command package: `@penpair/web`, or `@penpair/docker` for a local instance. Both use the neutral `@penpair/core` library. Add the [companion adapters](docs/adapters.md) your workflow needs. Keep their versions aligned with the command package. The unscoped `penpair` wrapper currently has a publishing exception; use the scoped command package. Every repository package is versioned together; publishing belongs to the owner.
|
|
221
48
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
| Command | What it does |
|
|
49
|
+
| Shipped skill | Use |
|
|
225
50
|
| --- | --- |
|
|
226
|
-
|
|
|
227
|
-
|
|
|
228
|
-
|
|
|
229
|
-
|
|
|
230
|
-
|
|
|
231
|
-
| `baselines [--apply] [--update]` | Export a page's frames as approved images, with ready-made Reflection cases |
|
|
232
|
-
| `skills install` | The agent's rules, into `.skills/`, visible to Codex and Claude Code |
|
|
233
|
-
| `up`, `down`, `backup`, `restore` | Docker only (they come with `@penpair/docker`) |
|
|
234
|
-
|
|
235
|
-
## Good to know
|
|
236
|
-
|
|
237
|
-
- Penpot's plugin needs the **editor tab open and visible** while the assistant works, so penpair cannot run unattended overnight. It acts on one Penpot at a time, on the page you have open.
|
|
238
|
-
- Checked against Penpot 2.18.3 (Docker) and the hosted Penpot 2.18.4: the same tools and limits, and a full deep check on both ([compatibility](https://github.com/niklas-westman/penpair/blob/main/docs/compatibility.md)). Not proven yet: a large file with a shared library on the hosted service, paid plans, two editors in one file, and a full `.penpot` export and import round trip.
|
|
239
|
-
- penpair is early (0.1.x). Expect rough edges and quick fixes. The plan and the open questions are in [PLAN.md](https://github.com/niklas-westman/penpair/blob/main/PLAN.md).
|
|
240
|
-
|
|
241
|
-
## Documentation
|
|
242
|
-
|
|
243
|
-
- [Setup guide skill](https://github.com/niklas-westman/penpair/blob/main/skills/penpair-setup-guide/SKILL.md): your assistant walks you through the whole setup
|
|
244
|
-
- [Getting started](https://github.com/niklas-westman/penpair/blob/main/docs/getting-started.md): step by step by hand, for designers and for whoever sets it up
|
|
245
|
-
- [Guide](https://github.com/niklas-westman/penpair/blob/main/docs/guide.md): extension points, instances, commands
|
|
246
|
-
- [Marwes tokens](https://github.com/niklas-westman/penpair/blob/main/docs/marwes-tokens.md): Marwes tokens in Penpot and drift checks
|
|
247
|
-
- [Compatibility](https://github.com/niklas-westman/penpair/blob/main/docs/compatibility.md): what was checked on which Penpot
|
|
248
|
-
- [Releasing](https://github.com/niklas-westman/penpair/blob/main/docs/releasing.md), [Changelog](https://github.com/niklas-westman/penpair/blob/main/CHANGELOG.md)
|
|
249
|
-
|
|
250
|
-
penpair is the other half of [Reflection](https://github.com/niklas-westman/reflection): Reflection checks that an implementation matches its design; penpair holds and drives the design that everything is measured against.
|
|
251
|
-
|
|
252
|
-
## Contributing and security
|
|
253
|
-
|
|
254
|
-
Issues and small pull requests are welcome: see [CONTRIBUTING](https://github.com/niklas-westman/penpair/blob/main/CONTRIBUTING.md). Your Penpot MCP key is a password; read [SECURITY](https://github.com/niklas-westman/penpair/blob/main/SECURITY.md) before you report a problem.
|
|
51
|
+
| [penpair-setup](packages/core/skills/penpair-setup/SKILL.md) | Connect or repair project setup |
|
|
52
|
+
| [penpair-design](packages/core/skills/penpair-design/SKILL.md) | Inspect and operate on a design file |
|
|
53
|
+
| [penpair-recipes](packages/core/skills/penpair-recipes/SKILL.md) | Compose a page with reviewed recipes |
|
|
54
|
+
| [penpair-handoff](packages/core/skills/penpair-handoff/SKILL.md) | Implement from design evidence and compare |
|
|
55
|
+
| [design-judgment](packages/core/skills/design-judgment/SKILL.md) | Assess page structure and hierarchy |
|
|
255
56
|
|
|
256
|
-
|
|
57
|
+
[Cookbook](docs/cookbook.md) · [MCP tools](docs/mcp.md) · [Format contracts](docs/formats.md) · [Compatibility](docs/compatibility.md) · [Recovery](docs/recovery.md) · [Living checklist](docs/improvements.md)
|
|
257
58
|
|
|
258
|
-
[
|
|
59
|
+
See [CONTRIBUTING](CONTRIBUTING.md), [SECURITY](SECURITY.md), [release steps](docs/releasing.md), [CHANGELOG](CHANGELOG.md) and the [MIT licence](LICENSE). Comparison metrics supply evidence for review; they do not approve a design.
|
package/docs/adapters.md
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Companion adapters
|
|
2
|
+
|
|
3
|
+
Penpair connects the design workflow to the libraries and implementation tools a project already uses. Choose the command package for your Penpot connection, then add companions for your intended workflow.
|
|
4
|
+
|
|
5
|
+
| Your workflow | Recommendation | Required project inputs |
|
|
6
|
+
| --- | --- | --- |
|
|
7
|
+
| Inspect, build and export Penpot designs | One of `@penpair/web` or `@penpair/docker` | A configured connection and pinned design file |
|
|
8
|
+
| Use Marwes UI in the frontend and Penpot | Add `@penpair/marwes-ui` | Installed library, project theme and reviewed token declarations |
|
|
9
|
+
| Implement frontend code and compare it with Penpot | Add `@penpair/reflection-check` | Approved design baselines, explicit cases and a real browser provider |
|
|
10
|
+
|
|
11
|
+
Adapters are installed and registered explicitly. Both companions can be used together; a comparison workflow does not require the library adapter. Keep the command package, its resolved core and directly installed adapters at the same reviewed version. Do not install both command packages.
|
|
12
|
+
|
|
13
|
+
## Bring your component library into Penpot
|
|
14
|
+
|
|
15
|
+
`@penpair/marwes-ui` connects the installed Marwes library and project theme to token snapshots, ownership-aware drift checks and reviewed token operations. It also provides compositional recipes and a measured-component pilot. Native component generation remains gated on actual override-preservation proof.
|
|
16
|
+
|
|
17
|
+
Use it when your application uses Marwes UI. Follow the [adapter overview](marwes.md), [token configuration](marwes-tokens.md) and [build-kit guide](build-kit.md). Other libraries need their own adapters or explicit project declarations; the core contains no library defaults.
|
|
18
|
+
|
|
19
|
+
## Check the frontend against the design
|
|
20
|
+
|
|
21
|
+
**Recommend `@penpair/reflection-check` whenever frontend implementation and visual verification are part of the task.** It connects an approved Penpot design case to the corresponding running application case:
|
|
22
|
+
|
|
23
|
+
1. Inspect the design and create a [handoff](handoff.md).
|
|
24
|
+
2. Capture and review [baseline cases](coverage.md), including viewport, theme, state, fixture and fonts.
|
|
25
|
+
3. Implement the frontend using the project's actual components and behavior.
|
|
26
|
+
4. Map each approved design case to explicit application setup.
|
|
27
|
+
5. Run a project provider to open that state, read it back, capture the browser and compare the image.
|
|
28
|
+
6. Review the screenshots and differences; record human approval separately.
|
|
29
|
+
|
|
30
|
+
The adapter checks that the returned evidence identifies the requested case and expected state, references the correct unchanged baseline, and has matching PNG dimensions/scale and font evidence. A complete result within the configured difference threshold is technical evidence, not visual approval or an accessibility assessment.
|
|
31
|
+
|
|
32
|
+
The provider is project code with an `async runCase(test)` export. It supplies actual route/theme/state/fixture setup, browser readback, screenshot capture and image comparison through the project's pinned tools. It can integrate the project's existing Reflection/browser checker. The adapter itself does not install a browser or execute a particular Reflection engine automatically.
|
|
33
|
+
|
|
34
|
+
### Install and register
|
|
35
|
+
|
|
36
|
+
First check your installed command version:
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
pnpm exec penpair --version
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
For a project already on **0.2.0**, install the matching companion:
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
pnpm add -D -E @penpair/reflection-check@0.2.0
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Use the version printed above when it differs. In a pnpm workspace, use the existing dependency location (`-w` when installing at the workspace root). Upgrade directly installed Penpair packages together rather than mixing releases.
|
|
49
|
+
|
|
50
|
+
Append the adapter to the existing `adapters` array in `penpair.config.json`, preserving other fields and already configured adapters:
|
|
51
|
+
|
|
52
|
+
```json
|
|
53
|
+
{
|
|
54
|
+
"adapters": ["@penpair/reflection-check"]
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
That JSON is a fragment to merge, not a replacement project config. The library companion is installed the same way at the matching version and registered as `@penpair/marwes-ui`; only register packages you have installed.
|
|
59
|
+
|
|
60
|
+
### Progress from installed to working
|
|
61
|
+
|
|
62
|
+
- [ ] **Installed and registered:** the matching adapter dependency and config entry exist. `penpair --help` can identify configured extensions without executing them.
|
|
63
|
+
- [ ] **References ready:** configured file pin and baseline frames have current exact approved provenance and explicit case metadata.
|
|
64
|
+
- [ ] **Mapping ready:** `design/implementation-cases.json` maps each baseline case ID to its project setup name.
|
|
65
|
+
- [ ] **Provider ready:** `design/reflection-provider.mjs` exports `runCase` and uses actual browser/checker work; requested inputs are not copied into observed results.
|
|
66
|
+
- [ ] **Verified in the browser:** the plan has no pending cases, the provider executes the intended cases and the owner looks at the resulting images.
|
|
67
|
+
|
|
68
|
+
```sh
|
|
69
|
+
pnpm exec penpair reflection plan --map design/implementation-cases.json
|
|
70
|
+
pnpm exec penpair reflection check --map design/implementation-cases.json --provider design/reflection-provider.mjs
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Use the [package reference](https://github.com/niklas-westman/penpair/blob/main/packages/reflection-check/README.md) for mapping/provider examples. Exit **0** means complete evidence within threshold, **2** means measured drift and **3** means missing/incomplete evidence. An install, a passing setup check or a stub provider is not a completed frontend comparison.
|
|
74
|
+
|
|
75
|
+
The shared browser-provider starter is planned work. Until it ships, configure a real project provider or explicitly report that integration as pending. For simple legacy route/viewport checks, the existing generated `reflection-cases.json` and `visualSmoke` configuration remain available; richer cases require explicit setup and readback.
|
|
76
|
+
|
|
77
|
+
## Why explicit companions?
|
|
78
|
+
|
|
79
|
+
The design-only workflow can start with one command package. Frontend projects should be guided toward the comparison companion during setup and handoff. Keeping installation explicit lets each project choose its browser/checker and supply meaningful setup instead of treating an added dependency as a finished integration.
|
|
80
|
+
|
|
81
|
+
The shipped setup/handoff skills should recommend the appropriate companion, preserve existing adapter configuration and report readiness at each stage. They must keep missing references or provider work visible and never invent owner approval.
|
|
82
|
+
|
|
83
|
+
Use the shipped [real-browser provider starter](../examples/reflection-browser/README.md) to supply capture plumbing while keeping route/theme/state/fixture hooks project-owned. It includes measured font, pointer, scroll and crop evidence; a browser dependency is not added to the core.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Owner approval records
|
|
2
|
+
|
|
3
|
+
```sh
|
|
4
|
+
penpair approve --page Dashboard --frame FRAME_ID
|
|
5
|
+
# After exporting, looking twice and obtaining the owner's exact words:
|
|
6
|
+
penpair approve --page Dashboard --frame FRAME_ID --write \
|
|
7
|
+
--note 'EXACT_OWNER_WORDS' --by 'OWNER_IDENTITY'
|
|
8
|
+
# Include --case CONFIGURED_BASELINE_ID for a rich theme/state/fixture case.
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Preview captures stable evidence and records nothing. Recording captures again and appends a schema-1 owner-words record to `design/approvals.json`, with file/page/frame IDs, revision, scale, actual theme/render context, optional declared case, PNG SHA-256, date, identity, exact note and record hash. The immutable PNG lives under `design/approvals/SHA256.png`. A local exclusive append lock prevents lost records; a stale lock requires inspection. The file is atomically replaced after image bytes exist. Prior records are retained.
|
|
12
|
+
|
|
13
|
+
The command records supplied words; it cannot authenticate a person or establish consent. An agent needs the owner's actual approval for the exact reviewed artifact and must never invent words or run this as a routine automatic success step. No approvals were recorded by this implementation task. Content hashes detect changes, not identity. An empty note/identity, unstable capture, mismatched case, altered approved bytes or credential redaction refuses publication.
|
|
14
|
+
|
|
15
|
+
`baselines --apply --update` now requires a record matching the changed artifact's exact image and capture/case fingerprint. An unrelated revision, file, page, frame, scale, active theme context or case cannot reuse it. Preview/capture inspection remains available without approval. First-reference capture retains its existing explicit `--apply` behavior; historical and initial references are not retroactively attributed to owner words.
|
|
16
|
+
|
|
17
|
+
An exceptional `--apply --update --force-reason 'EXPLICIT_REASON'` may save a reference without a matching owner record. Its provenance says `forced-reference`; the reason persists. Rich case coverage and the implementation-case adapter refuse to count that waiver as owner-approved evidence. A waived reference is useful for an experiment, but cannot silently satisfy the design acceptance gate. Empty reasons and reasons without apply/update refuse.
|
|
18
|
+
|
|
19
|
+
The latest revision is a conservative invalidation boundary: an unrelated design edit may require fresh approval even if pixels stay equal. A PNG alone does not approve structure, behavior or accessibility. Approval records remain local/project artifacts until reviewed; no publish, client configuration or consumer-repository edit occurs automatically.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Capture and approval provenance
|
|
2
|
+
|
|
3
|
+
Baseline manifests use schema 2. `capturedRevision` identifies the coherent capture run, while each frame has separate `captured` and `approved` records. Those records identify the file, page and frame by immutable ID, revision, PNG hash, scale, active theme names, capture time, penpair version, reported Penpot API version and browser user agent when available. A missing environment value is recorded as unknown; the record does not establish that fonts loaded correctly or identify every rendering dependency.
|
|
4
|
+
|
|
5
|
+
An unchanged reference retains its original approval record. A changed image recaptured without `--update` retains its approved bytes, path, revision and hash, while `captured` describes the new candidate. Legacy images without trustworthy provenance are marked `legacy`; a current revision is never invented for them. Changing a baseline still requires the owner's `--apply --update`. Schema 2 does not claim a separate human review record; that is tracked in D2.
|
|
6
|
+
|
|
7
|
+
All configured frames must be present and stable. File/page/revision evidence is checked inside exports and across consecutive exports; the complete frame listing is checked again after capture. Intervening changes, failures or cancellation do not publish a new complete manifest. There is no partial-publication mode.
|
|
8
|
+
|
|
9
|
+
PNG captures live in immutable `captures/<capture-id>/<baseline-id>.png` generations instead of replacing `<baseline-id>.png`. Read approved image paths from manifest frame `file` fields. Generated Reflection cases already use those paths. `penpair-baselines.json` is the authoritative commit point and is published last with a same-directory atomic rename. Its `casesFile` points to the exact immutable case file for that generation. The root `reflection-cases.json` remains a convenience for existing config imports; when reading it together with a manifest, require matching `captureId`, or follow `casesFile` from the manifest. Independent root files cannot be replaced as one filesystem transaction.
|
|
10
|
+
|
|
11
|
+
A process interrupted during output may leave an unreferenced capture generation. Previous manifest references remain usable; inspect before cleaning generations. Staging directories are removed on handled errors. This is filesystem publication safety, not a power-loss-proof multi-file transaction or a remote backup.
|
|
12
|
+
|
|
13
|
+
Standalone PNG export and full-file archive candidates also stage complete bytes before publication. Archives use exclusive creation and never replace an existing file. PNG exports atomically replace the requested output only after a stable result. The export report includes target provenance. Archive restore verification remains a separate scratch import/readback task.
|
package/docs/audits.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Configured advisory audits
|
|
2
|
+
|
|
3
|
+
Configure an optional `audit` block with boolean `contrast`, `library`, `touchTargets`, `names`, `blankText`; explicit `interactiveIds`, `allowBlank`; optional `nameSegments` (default 3); and reasoned exact-node `suppressions: [{rule,nodeId,reason}]`. Unknown settings refuse before connecting. The configured audit uses a complete page-root inspection; legacy filters remain available when configured rules are absent.
|
|
4
|
+
|
|
5
|
+
Run `audit --page PAGE`, or offline `audit --from INSPECTION --token-source TOKENS`. The offline token catalog must share exact file/revision and contain actual resolved values in active set order. Missing, foreign, mixed, transparent, gradient/image, unbound or mismatched paint evidence remains unknown. Contrast measures an opaque sRGB subset and checks that observed paint matches the resolved binding. It does not infer compositing, overlapping paints or browser font/rendering behavior.
|
|
6
|
+
|
|
7
|
+
The review thresholds follow [WCAG contrast guidance](https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum.html): 4.5 ordinarily, 3 for the explicitly assumed large text size/weight. Ratios are compared without rounding. Design units are assumed to correspond to CSS pixels; exceptions and actual implementation behavior still require review. This tool does not establish accessibility compliance.
|
|
8
|
+
|
|
9
|
+
Touch-size signals apply only to explicit interactive IDs. Below 24 units is a warning; below 44 is a preference signal. The [minimum target guidance](https://www.w3.org/WAI/WCAG22/Understanding/target-size-minimum.html) includes spacing and other exceptions; [enhanced targets](https://www.w3.org/WAI/WCAG22/Understanding/target-size-enhanced.html) use a larger threshold. Size alone does not prove clickability, CSS scale, spacing, keyboard support or conformance.
|
|
10
|
+
|
|
11
|
+
Library coverage reports native copy instances among known nodes, unknown component fields and the largest observed primitive groups. It is a composition signal, not a component quality score. Naming checks slash-separated frame segments/default names. Blank/placeholder text can be allowed by exact node ID; suppressions retain the finding and reason visibly.
|
|
12
|
+
|
|
13
|
+
Findings are advisory and never mutate the file. Complete findings return exit 0 even with warnings; partial source/refused inspection or bounded output truncation remains incomplete (3). The report retains exact total counts, suppressions, source identity and assumptions. A successful traversal does not convert unobserved fields into known values.
|
package/docs/backup.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Hosted-file backup and restore
|
|
2
|
+
|
|
3
|
+
An exported archive is a candidate backup. It becomes a proven recovery path after a successful import and independent content/render comparison. Named Penpot versions and structural JSON snapshots help with recovery/review, but neither is an independent full-file backup.
|
|
4
|
+
|
|
5
|
+
## Export
|
|
6
|
+
|
|
7
|
+
1. Confirm the intended source file's name and ID (`penpair doctor --json`). Pin its ID with `penpair connect --pin-file`.
|
|
8
|
+
2. In Penpot, export the file as `.penpot` through the workspace File menu or dashboard. Include shared library assets according to the recovery you need: retaining external references still depends on those libraries being available. Keep the original archive outside public Git and record its hash, source file ID, export date, Penpot version and library export choice.
|
|
9
|
+
3. Save a new dated archive; retain prior proven backups until the new one has passed the restore check. Keep a separate copy in storage the owner controls.
|
|
10
|
+
|
|
11
|
+
An optional command tries the documented full-file API: `penpair backup file <new.penpot>`. It requests `currentFile.export("penpot", "all")`, checks target/revision stability, validates received byte length, and prints the SHA-256. It never replaces an existing archive. The default raw archive budget is 512 KiB to stay within the tested response envelope; larger files and unsupported/failing APIs point to the manual route. The library's `exportFileArchive` accepts an explicit budget up to 16 MiB, whose transport compatibility must be tested before relying on it.
|
|
12
|
+
|
|
13
|
+
Receiving bytes does not validate the archive's internal format or prove restoration. The command reports `restoreVerified: false`. The previously observed “No matching clause” error is still an unverified live compatibility issue; supplying the documented library-export argument is a candidate to test, not a claimed fix.
|
|
14
|
+
|
|
15
|
+
## Prove the restore on scratch
|
|
16
|
+
|
|
17
|
+
- [ ] Export the source using the chosen library mode and record the provenance/hash.
|
|
18
|
+
- [ ] Import it into a disposable project/file on the intended target Penpot version. Keep the source and its previous proven backup untouched.
|
|
19
|
+
- [ ] Connect from a separate scratch project configuration and pin the imported file ID. Import may change IDs; compare logical names, content, component relationships and token bindings rather than requiring identical imported IDs.
|
|
20
|
+
- [ ] Compare pages and frames, node counts, texts, geometry, library components/instances/overrides, images and fonts, token sets, aliases, set order, themes and effective values. Check an instance's relationship to its main component rather than just its appearance.
|
|
21
|
+
- [ ] Export representative frames in light/dark and intended viewport/state combinations. Wait for stable exports and look twice; compare visually with the source references.
|
|
22
|
+
- [ ] Record the target version, imported file ID, checks, differences and owner review. Mark the candidate proven only when every required check passes.
|
|
23
|
+
|
|
24
|
+
If export/import fails or content differs, preserve both observations and the previous backup. Use the manual route and investigate the exact version/library mode. Never restore over the live shared file as a test. A successful UI import alone does not establish full fidelity.
|
|
25
|
+
|
|
26
|
+
[Penpot's export/import documentation](https://help.penpot.app/user-guide/export-import/export-import-files/) describes the manual routes and library choices. Current API documentation may be newer than the pinned runtime; see [compatibility](compatibility.md).
|
|
27
|
+
|
|
28
|
+
## Optional advisory reminder
|
|
29
|
+
|
|
30
|
+
Reminders are disabled by default. Opt in through `penpair.config.json`:
|
|
31
|
+
|
|
32
|
+
```json
|
|
33
|
+
"backup": { "noteFile": "design/backup-note.json", "remindAfterDays": 7 }
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Keep an owner-maintained note containing:
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"schemaVersion": 1,
|
|
41
|
+
"fileId": "<pinned source file id>",
|
|
42
|
+
"recordedAt": "<ISO timestamp when the backup evidence was recorded>",
|
|
43
|
+
"archiveSha256": "<64 hexadecimal characters>",
|
|
44
|
+
"restoreVerified": false
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Set `restoreVerified` to true only after the owner completes the scratch comparison. The note can include links to the owner's evidence, but keep credentials and private storage access URLs out of Git. Doctor warns non-blockingly about missing, malformed, mismatched, old or unverified notes. A recent note records an owner's assertion, not independent proof that a backup is current or restorable. The engine never upgrades it after merely receiving archive bytes.
|
|
49
|
+
|
|
50
|
+
## Current verification limits
|
|
51
|
+
|
|
52
|
+
The bounded exporter, target/revision guards, refusal to overwrite, error/budget handling and reminder behavior are tested with fake clients and local files. The first live archive export/import round trip on hosted Penpot 2.18.4 remains outstanding. Structural snapshots (D3) will provide review evidence and remain distinct from archives. G3 stays open until its required live restore evidence is recorded.
|
|
53
|
+
|
|
54
|
+
[Structural snapshots and diffs](snapshots.md) provide bounded review evidence alongside archives; they cannot replace an export/import restore trial.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Improvement branch review
|
|
2
|
+
|
|
3
|
+
Branch: `codex/penpair-improvements`. Review before merging. No push, merge, version bump, tag, publish, deployment, real Penpot mutation or upstream message was performed.
|
|
4
|
+
|
|
5
|
+
The [living checkbox document](improvements.md) contains the priority order and per-item **Resolved / Changed / Validated / Risks / Next** reports. It mirrors the owner's external brief. At handoff, 37 of 40 top-level items are implemented; the three live acceptance items below stay unchecked. Preparation substeps are checked separately.
|
|
6
|
+
|
|
7
|
+
## Review in this order
|
|
8
|
+
|
|
9
|
+
| Area | Main entry points and evidence |
|
|
10
|
+
| --- | --- |
|
|
11
|
+
| Target safety, execution and recovery | Config/file guards; one-shot ambiguous writes; positive readback; [journals/recovery](recovery.md); [team coordination](team.md) |
|
|
12
|
+
| Bounded inspection and artifact trust | [Inspection](inspection.md), [formats](formats.md), [snapshots](snapshots.md), [artifacts](artifacts.md), [approvals](approvals.md) |
|
|
13
|
+
| Page construction and token ownership | [Reviewed file scripts](run-file.md), [kit](build-kit.md), [token editing](token-editing.md), [adapter](marwes.md), [mode trials](mode-verification.md) |
|
|
14
|
+
| Implementation evidence | [Handoff](handoff.md), [case coverage](coverage.md), [explicit provider adapter](../packages/reflection-check/README.md) |
|
|
15
|
+
| Agent and operator paths | Five shipped skills; [MCP](mcp.md), [credentials](credentials.md), [status/open](status.md), [advisory audits](audits.md), [troubleshooting](troubleshooting.md) |
|
|
16
|
+
| Release/consumer/upstream preparation | [Release gates](releasing.md), [consumer proposal](tradient-followups.md), [unsent upstream requests](upstream/marwes-requests.md) |
|
|
17
|
+
|
|
18
|
+
Commits are grouped by backlog item. Inspect one item/report and its commit before moving to another. Tests use actual generated plugin bodies where possible, fake transports/servers, recorded structures and temporary consumers. The package smoke installs all six tarballs in clean consumers; it does not publish them.
|
|
19
|
+
|
|
20
|
+
## Intentionally open acceptance gates
|
|
21
|
+
|
|
22
|
+
- [ ] **G3:** Owner-authorized hosted `.penpot` export/import and full token/component/asset/render restore comparison. Archive candidates and structural review data do not prove restore fidelity.
|
|
23
|
+
- [ ] **I12:** Two real people complete onboarding, wrong-file prevention, writer conflict, recovery and one real design-to-code route. Use the [runbook/template](trials.md); no synthetic people or timings are recorded as results.
|
|
24
|
+
- [ ] **C1:** Real Button/Card/StatTile fixture measurements and pinned-native-API proof that instance text/style overrides survive updates. Measurement/drift tooling is built; native library generation deliberately refuses until that proof exists. Measured project constants are not fabricated.
|
|
25
|
+
|
|
26
|
+
The owner requested finishing branch code and leaving live trials pending. Those unresolved gates remain visible rather than being counted as delivered behavior. Native generation depends on that live proof and is the material remaining implementation gate.
|
|
27
|
+
|
|
28
|
+
## Decisions to assess before adoption
|
|
29
|
+
|
|
30
|
+
- Read declarations and trusted project modules are contracts, not execution sandboxes. Default built-in inspection avoids extension imports; explicit adapter/provider/registered-script paths execute trusted code.
|
|
31
|
+
- Shared writer markers are advisory across machines. Journals preserve uncertainty and support explicit reconciliation; they are not transactions, rollback or exactly-once execution.
|
|
32
|
+
- Typed handoff/mapping hints preserve literal design data. They do not infer application state, component semantics, responsive behavior or accessibility from pixels.
|
|
33
|
+
- Rich comparison cases need actual project setup and independent browser readback. Pixel ratios, size signals and heuristic hue findings remain evidence for review.
|
|
34
|
+
- Changed baseline references require exact owner-word evidence or a visible forced-reference waiver; waived references do not satisfy approved rich coverage.
|
|
35
|
+
- The project MCP server has an immutable explicit root/target, strict file guards and bounded responses. Registered writes require server opt-in and call-level apply. Cancellation remains cooperative for trusted code.
|
|
36
|
+
- Private file/Keychain providers are implemented, but no real personal store was exercised. General credential commands remain deferred.
|
|
37
|
+
- The release workflow requires owner activation, protected-environment policy and npm publisher settings. No remote policy or actual OIDC/provenance result has been established. All packages remain 0.1.3; the branch is unreleased.
|
|
38
|
+
- Consumer changes and upstream sends remain owner actions. Existing optional trend/Card composition and the consumer SidebarNav corrected parts of the original brief; historical measurements remain version/context-scoped.
|
|
39
|
+
|
|
40
|
+
## Release automation follow-up
|
|
41
|
+
|
|
42
|
+
R1 adds Changesets version PRs with one fixed group for all six packages and an
|
|
43
|
+
API-verified exact merged-PR gate before publishing. Ordinary feature merges do
|
|
44
|
+
not publish. The PR token has no npm role; publishing uses OIDC and retains the
|
|
45
|
+
existing release guards. Both paths start disabled. Review the [activation
|
|
46
|
+
checklist](releasing.md#one-time-owner-activation) and [local PR draft](pr-improvements.md).
|
|
47
|
+
The pending minor note proposes 0.2.0; actual package versions remain 0.1.3.
|
|
48
|
+
|
|
49
|
+
R2 adds the owner-requested temporary `PENPAIR_RELEASE_EXCLUDE_PENPAIR=true`
|
|
50
|
+
publishing exception for the short-name wrapper. All six versions still move
|
|
51
|
+
together; five required packages must verify and the omission is explicitly
|
|
52
|
+
reported. Remove the variable to restore full-family publishing and use explicit
|
|
53
|
+
continuation to catch up the current missing wrapper. See [release exception](releasing.md#temporary-exception-for-the-short-name).
|
|
54
|
+
|
|
55
|
+
## Validation and handoff
|
|
56
|
+
|
|
57
|
+
Final verification covers `pnpm check`, `pnpm smoke:package`, docs/anchor and generated-remedy checks, targeted skill-entrypoint validation, release helper syntax and workflow YAML boundaries. The final recorded suite has 583 tests across core, adapter, implementation bridge and Docker. The final full branch check and six-package smoke both passed before handoff. Live/editor/browser/human acceptance remains pending as listed above.
|
|
58
|
+
|
|
59
|
+
Review this branch locally against main. External authorization is needed before any push, merge, release activation, publishing, version bump, consumer write or non-scratch Penpot change. No new confirmation is needed for the already authorized local implementation work.
|