Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions design/penpot/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Native exports live in versioned GitHub release assets.
*.penpot
*.zip
downloads/
__pycache__/
110 changes: 110 additions & 0 deletions design/penpot/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# Penpot design snapshots

Git tracks the exact SHA-256 checksums, file inventories, revisions, library
links and qualification notes of native, editable Penpot exports. Versioned
GitHub release assets are the proposed off-server storage, keeping hundreds of
megabytes out of every clone. No Git LFS or Python packages
are required. The checker requires Python 3.9 or newer.

**Publication pending:** the two native archives remain local; no archive has
been uploaded to GitHub. Explicit approval to upload their editable contents
is pending. The release URL in the receipts is a reserved destination, and the
download commands below become usable only after publication. See the
[publication record](snapshots/2026-10-03/publication.json) and
[migration status and remaining work](STATUS.md).

## Current recovery points

| Receipt | Native export | Coverage | Qualification |
| --- | --- | --- | --- |
| [complete.json](snapshots/2026-10-03/complete.json) | 2026-10-02; 300,739,780 bytes | 39 canonical modules + Starter; 1,854 component definitions | Historical complete backup. Native recovery/reopen was previously checked; later corrections are absent. |
| [partial.json](snapshots/2026-10-03/partial.json) | 2026-10-03; 68,988,603 bytes | 15 modules; 873 component definitions | Newer saved state for the listed files only. Combined archive has not undergone a native reimport/reopen test. |

These are two separate recovery points, not an automatically merged latest
backup. Importing the partial archive on top of the full one is **not** a proven
update procedure: native imports can create new IDs and library relationships.
Use separate recovery projects and check the complete dependency graph before
promoting any recovered copy.

The per-file `filePayloadSha256` is computed over sorted file-owned ZIP member
paths and their byte hashes. It stays stable across ZIP repacking/compression,
but changes when saved file content or metadata changes. The archive hash also
protects shared media and thumbnails. Counts exclude the synthetic page roots.
An inventory describes saved data; it is not a visual or runtime acceptance test.

## Download and verify

From the repository root (GitHub CLI required only for the download):

```sh
mkdir -p design/penpot/downloads/2026-10-03
gh release download penpot-snapshot-2026-10-03 --repo vllnt/ui \
--pattern '*.penpot' --dir design/penpot/downloads/2026-10-03
python3 scripts/penpot_snapshot.py verify \
design/penpot/snapshots/2026-10-03/complete.json \
design/penpot/snapshots/2026-10-03/partial.json \
--asset-dir design/penpot/downloads/2026-10-03
```

The checker reads every ZIP member to check CRC integrity and compares the
archive size, SHA-256, and full inventory with the committed receipt. It does not
extract archives, contact Penpot, or modify any design. A missing, corrupt or
mismatched archive fails with a nonzero exit code.

## Recover safely in Penpot

1. Verify the downloaded archive with the command above.
2. Create a separate recovery project in the `vllnt` team, then use Penpot's
dashboard file import for the native `.penpot` export.
3. Compare the imported file names/counts, library links and component catalog
with the receipt. Imports may assign different IDs. Open every imported file,
run native validation, and save/reopen it. Check media, fonts and layout.
4. Test a component from the recovered shared libraries in a separate consumer
file, including a source update and an instance override.
5. Promote only after those checks. Keep the original Pen source, current
canonical files and previous snapshots until recovery and consumers pass.

This is a file-level recovery mechanism, not a backup of the entire self-hosted
server. Accounts, permissions, history, comments, database and service
configuration require the server's own backup system.

## Save the next design batch

1. Confirm the exact file ID and that its content is saved. In Penpot, create a
named version before a risky edit. The public plugin API also supports
`await penpot.currentFile.saveVersion("Before <batch>")`; always verify the
expected file ID first. Versions are local to the server and do not replace
off-server exports.
2. Export native `.penpot` files with their linked libraries. Prefer a complete
canonical-project export plus the Starter. Clearly label any smaller export
as partial. Never assume the currently focused trial covers all 39 modules.
3. Use a new tag and receipt path, without replacing an earlier release asset:

```sh
python3 scripts/penpot_snapshot.py record /path/to/export.penpot \
--output design/penpot/snapshots/<date>/<scope>.json \
--exported-on <actual-export-date> \
--scope 'PARTIAL: list the included modules and exclusions' \
--release-tag penpot-snapshot-<date>-<batch> \
--note 'Saved archive; native reopen/visual/consumer checks: state actual results'
```

4. Review the inventory and its Git diff. Scope and export date are operator
declarations; the tool cannot establish that an export is current or complete.
5. Commit the receipt and qualification notes, then attach the native export to
a versioned GitHub release targeting that commit. Keep design snapshots out
of the software “Latest” release (`gh release create ... --latest=false`).
The repository is public: publish only reviewed design assets, never auth
state, environment files, server backups or raw browser diagnostics.
6. Download the uploaded assets into a fresh directory and run `verify` against
the committed receipts. Record native reimport/reopen separately. Never
describe hash verification alone as a successful native restore.

No scheduled exports are configured. Future saves require a native export and
a new receipt/release; the Git records do not continuously mirror live Penpot.

## Check the tracking tool

```sh
python3 -m unittest discover -s scripts -p 'test_penpot_snapshot.py' -v
```
94 changes: 94 additions & 0 deletions design/penpot/STATUS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Penpot migration status — 2026-10-03

The full design has been imported, but migration acceptance is still open.
Keep the original `design/vllnt-ui.pen`, legacy content and all previous recovery
points. A successful import or checksum is not proof that every component looks
and behaves correctly.

## Destination and authority

- Team: `vllnt` (`922b72d2-2185-8146-8008-b95add9df3c4`).
- Canonical project: `503b8235-8be1-80bf-8008-ba5ff4e2d3b6`.
- Starter consumer: `503b8235-8be1-80bf-8008-ba83182b5131`.
- The 39 canonical file IDs/names are in [complete.json](snapshots/2026-10-03/complete.json), alongside the Starter.
- Files prefixed `[Validation]` or `[Recovery]` are trials or restore copies.
They must not be mistaken for canonical libraries.

## Verified evidence

- The historical complete archive contains 39 canonical modules plus Starter:
**210 source boards, 245,024 shapes, 1,854 component definitions, 159 library
relationships**. Source coverage checks found no missing boards, shapes,
components or token bindings. The strict 39-file checker flags the additional
Starter; the known 40-file scope was separately qualified and the original
finding is retained in [verification.json](snapshots/2026-10-03/verification.json).
- The newer partial export covers **15 modules, 129 source boards, 55,001 shapes,
873 component definitions and 45 relationships**. Within that scope, no source
objects/components/token bindings are missing. It is not a fresh full backup.
- The live catalog check found **29 canonical shared libraries and 1,844 visible
entries**. Atoms 02 groups 13 states into 3 variant families, explaining the
difference from 1,854 saved definitions. No canonical library is missing.
- Six connected libraries expose seven token sets, 1,439 token entries and four
themes. This proves availability; it does not prove propagation or appearance
in every consumer. Older saved archives contain earlier token states.
- Saved effect conservation matched 8,205 shapes, 9,236 shadows and 892 background
blurs. Media metadata and both JPEG payload hashes matched the source cache.
These checks do not establish every crop or visual rendering.
- Native MCP access worked during the audit. Its focused document was a private
glyph validation trial at revision 16, with zero native validation errors.
This says nothing about native validation of all 39 canonical files.

## Remaining work, in dependency order

1. **Baseline and recovery:** obtain a fresh full export of all canonical files
and current consumers; validate each file, reimport into a separate recovery
project, save/reopen, and compare dependency links. The latest combined
partial archive still needs this native restore test.
2. **Engine qualification:** qualify the consolidated Penpot fixes in the
optimized Linux build before deployment. Isolated lab checks passed, but
deployment, rollback and the complete optimized-bundle test matrix are not
proven. Ordinary MCP work does not require a new Docker deployment.
3. **Tokens and themes:** prove safe updates and all four theme contexts through
representative consumers, then cover every component family. Keep the
tokens → atoms → molecules → organisms → templates → pages dependency order.
4. **Fonts:** historical evidence minus accepted canonical fixes leaves **1,311
regular aliases, six italic aliases and one unavailable IBM Plex Mono 800
style**. The newer partial archive directly contains 1,263 regular aliases,
six italic aliases and that unavailable style; the other 48 are based on
older saved evidence. Re-audit before editing. Private trials are not fixes
to canonical files.
5. **Atoms and glyphs:** complete 182 glyph uses across nine modules, including
106 hidden uses. The 31-item private trial remains unreceived: its saved
geometry/order checks passed, but 148 reflected descendants remain. Preserve
it as a trial until rendering, replacement and consumer behavior pass.
6. **Paint fidelity:** resolve six angular-gradient cases (two fill, four
border). Review the queues of 675 cap/join, 271 per-side stroke, 96 arc and 79
gradient records; these are review candidates, not proven corrupt counts.
7. **Variants and molecules:** extend native variant/override/swap/update proof
beyond the three Selection families. Molecules 07 has a historical 3,773
outside-subtree difference set. Its private update trial lost 596 sizing
attributes; a workaround protects 536 and leaves 60 open. The engine
candidate passed 596/596 in isolation, not in canonical acceptance.
8. **Organisms and templates:** finish mixed-font/layout review. Molecules 01
has 58 source dimensions changed by up to 9 px in the lab; Organisms 01 has
a small geometry reservation; Templates 01's protected paragraph difference
remains unreceived. Then verify page composition and source propagation.
9. **Final acceptance:** visual review, complete shared-library consumer proof,
native full recovery/reopen, and a final off-server snapshot. Only then
update repository authority from Pen to Penpot and retire individual legacy
replacements whose consumers are proven. No bulk deletion.

The older design-system ledger (315 modules: 122 partial, 193 pending) measures
broader design acceptance, not 315 missing imports. Keyboard, touch, voice,
dynamic states, reduced motion and actual AR-runtime checks remain separate
implementation evidence; a Penpot canvas does not prove them.

## Snapshot policy

Use [the recovery workflow](README.md) after each accepted design batch. Keep
native named versions for quick rollback and native exports outside the server
for disaster recovery. The prepared snapshot set preserves the historical full and
newer partial archives locally, without claiming an automatic merge or
continuous sync. Native archive upload to GitHub awaits explicit approval;
only the tracking records and recovery tooling are being committed.
No scheduled automation has been restarted.
2 changes: 2 additions & 0 deletions design/penpot/snapshots/2026-10-03/SHA256SUMS
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
e2086dfe1b6f53be182ef83513115787833e4f86b27cad6b2a5ef6948c1b38b7 vllnt-ui-native-complete-with-starter-2026-10-02.penpot
854731617ba8df4294d3374d6096548103bd98d0a0a99b48e4ca2c9282c764c1 vllnt-ui-partial-native-refresh-2026-10-03.penpot
Loading
Loading