Implement the staged changeset store and the colour/typography primitives with unit tests #194
Closed
opened 2026-09-14 23:10:21 +00:00 by david
·
1 comment
No Branch/Tag specified
main
feature/issue-342/mssql-write-access-check-and-startup-warning-never
feature/issue-331/mssql-write-extensions-mssql-readme-md-setup-tools
feature/issue-330/mssql-register-extension-add-tests-to-root-test-sc
feature/issue-329/mssql-index-ts-wiring-load-env-refuse-on-invalid-l
feature/issue-328/mssql-mssql-table-schema-tool-parameterised
feature/issue-327/mssql-mssql-list-tables-tool
feature/issue-326/mssql-mssql-query-and-mssql-query-one-tools
feature/issue-325/mssql-stream-runner-with-row-cap-cancel-and-timeou
feature/issue-324/mssql-pool-config-builder-encrypt-on-certificate-s
feature/issue-323/mssql-audit-log-writer-pi-mssql-audit-log-mode-060
feature/issue-322/mssql-read-only-guard-module-validatesql-with-corp
feature/issue-321/mssql-certificate-trust-setting-and-limit-validati
feature/issue-320/mssql-loadenvfile-and-mssql-url-parsing
feature/issue-319/mssql-extension-skeleton-permanent-corpora-and-dep
feature/issue-318/mssql-spike-write-result-md-apply-the-gate-open-th
feature/issue-317/mssql-spike-scoring-runner-for-both-candidates
feature/issue-316/mssql-spike-candidate-b-guard-using-the-antlr4-t-s
feature/issue-315/mssql-spike-candidate-a-guard-using-node-sql-parse
feature/issue-314/mssql-spike-must-accept-corpus
feature/issue-313/mssql-spike-scaffold-spike-directory-and-must-reje
feature/issue-311/mssql-spike-check-dependencies-mssql-node-sql-pars
feature/issue-312/mssql-spike-check-whether-extension-tests-run-in-c
feature/issue-299/verify-the-ste-style-live-in-a-short-grill-session
feature/issue-298/bump-the-grillme-extension-to-0-4-0-and-add-the-ch
feature/issue-297/rewrite-extensions-grillme-design-md-in-ste-style
feature/issue-296/rewrite-extensions-grillme-readme-md-in-ste-style
feature/issue-295/rewrite-the-grill-me-command-output-and-read-only
feature/issue-294/rewrite-the-grill-me-tool-metadata-to-the-ste-rule
feature/issue-293/extract-buildgrillprompt-and-add-the-prompt-integr
feature/issue-292/add-ste-style-test-ts-checks-for-the-rule-text-and
feature/issue-291/add-the-pure-ste-style-ts-module-and-inject-the-st
feature/issue-264/verify-the-vision-tool-live-against-the-deepseek-a
feature/issue-263/list-the-vision-extension-in-the-repo-root-readme
feature/issue-262/write-extensions-vision-readme-md-the-10-section-p
feature/issue-261/wire-the-vision-extension-into-package-json-manife
feature/issue-260/implement-extensions-vision-index-ts-factory-regis
feature/issue-258/implement-extensions-vision-src-tool-ts-the-vision
feature/issue-257/implement-extensions-vision-src-client-ts-request
feature/issue-256/implement-extensions-vision-src-usage-ts-usage-map
feature/issue-255/implement-extensions-vision-src-images-ts-read-val
feature/issue-254/implement-extensions-vision-src-config-ts-env-reso
feature/issue-253/implement-extensions-vision-src-errors-ts-toolerro
feature/issue-252/penpot-add-text-stages-zero-area-auto-width-text-p
feature/issue-216/add-the-penpot-skill-and-extension-to-the-repo-roo
feature/issue-217/register-the-penpot-tests-in-npm-test-complete-the
feature/issue-215/write-the-penpot-skill-md-core-workflow-token-conv
feature/issue-214/implement-and-run-fetch-penpot-docs-mjs-and-commit
feature/issue-213/validate-screenshot-reconstruction-against-the-liv
feature/issue-212/add-the-image-to-design-workflow-to-skills-penpot
feature/issue-211/validate-svg-import-icon-and-illustration-against
feature/issue-210/implement-the-penpot-add-svg-tool-with-svg-raw-fal
feature/issue-209/implement-the-svg-to-shapes-converter-in-src-svg-t
feature/issue-208/validate-component-instancing-against-the-live-ins
feature/issue-207/implement-penpot-instance-component-with-id-remapp
feature/issue-206/author-and-commit-the-component-library-artifact-u
feature/issue-205/implement-file-library-linking-and-validate-the-ex
feature/issue-204/implement-penpot-export-library-sse-uri-plus-artif
feature/issue-203/implement-penpot-import-library-multipart-upload-p
feature/issue-202/implement-the-transit-decoder-and-sse-stream-parse
feature/issue-201/validate-a-full-composed-screen-one-commit-one-rev
feature/issue-200/implement-penpot-add-image-with-media-upload
feature/issue-199/implement-asset-reference-resolution-plus-penpot-a
feature/issue-198/implement-penpot-add-frame-with-auto-layout-props
feature/issue-197/validate-asset-creation-atomicity-and-write-safety
feature/issue-196/implement-the-designated-target-write-guard-with-a
feature/issue-195/implement-penpot-commit-with-revn-tracking-conflic
feature/issue-194/implement-the-staged-changeset-store-and-the-colou
feature/issue-193/validate-read-primitives-against-the-live-penpot-i
feature/issue-192/implement-the-penpot-list-library-tool-with-name-t
feature/issue-191/implement-the-penpot-get-file-tool-pages-objects-a
feature/issue-190/implement-the-penpot-list-projects-tool-teams-and
feature/issue-189/implement-the-penpot-whoami-tool-and-wire-the-exte
feature/issue-188/implement-the-rpc-client-and-error-decoding-in-src
feature/issue-187/implement-penpot-url-penpot-token-resolution-in-sr
feature/issue-186/scaffold-the-penpot-extension-directory-and-regist
feature/issue-172/add-end-to-end-main-tests-for-the-fj-rg-tool-state
feature/issue-171/make-reminder-report-dynamic-install-skip-counts-r
feature/issue-170/wire-settings-json-filter-rewrite-into-dedupeandre
feature/issue-169/implement-buildpackagefilters-with-exhaustive-unit
feature/issue-168/refactor-preflight-to-skip-warn-for-missing-fj-rg
feature/issue-167/add-fj-rg-tool-detection-helpers-rgavailable-detec
feature/issue-148/reconcile-design-md-and-implementation-plan-with-t
feature/issue-146/verify-extension-load-behavior-with-and-without-mo
feature/issue-145/write-extensions-mongodb-readme-md
feature/issue-144/write-tool-description-promptsnippet-guidance-for
feature/issue-143/implement-index-ts-async-factory-lifecycle-with-te
feature/issue-142/implement-the-mongo-list-collections-tool-with-uni
feature/issue-141/implement-the-mongo-count-tool-with-unit-tests
feature/issue-140/implement-the-mongo-find-tool-with-unit-tests
feature/issue-139/implement-src-errors-ts-with-unit-tests-toolerror
feature/issue-138/implement-src-serialize-ts-with-unit-tests-ejson-t
feature/issue-136/implement-src-env-ts-with-unit-tests-mongodb-uri-r
feature/issue-135/register-the-mongodb-extension-in-the-repo-root-pa
feature/issue-133/initialize-the-extensions-mongodb-package-package
feature/issue-116/src-actions-ts-downloadrunlogs-zip-guarded-unzip-c
feature/issue-115/src-actions-ts-downloadjoblog-cache-first-attempt
feature/issue-114/src-actions-ts-metadata-queries-listactionruns-get
feature/issue-113/src-actionscache-ts-cache-paths-cache-first-read-w
feature/issue-112/add-zip-extraction-dependency-adm-zip-vs-yauzl
feature/issue-111/tracking-forgejo-actions-tooling-read-only-runs-jo
feature/issue-93/add-unit-tests-for-scripts-local-install-mjs-node
feature/issue-92/validate-install-local-end-to-end-on-the-dev-machi
feature/issue-90/implement-pi-registration-with-url-dedupe-and-relo
feature/issue-89/validate-install-local-from-a-scratch-clone-fresh
feature/issue-88/implement-git-pull-and-npm-install-steps-in-script
feature/issue-74/write-victorialogs-readme-md-and-reconcile-design
feature/issue-73/wire-up-index-ts-extension-factory-and-register-al
feature/issue-72/implement-logs-facets-tool-src-tools-facets-ts
feature/issue-71/implement-logs-hits-tool-src-tools-hits-ts
feature/issue-70/implement-logs-search-tool-src-tools-search-ts
feature/issue-69/implement-parsejsonlines-helper-in-src-client-ts
feature/issue-68/implement-victorialogsrequest-in-src-client-ts
feature/issue-67/implement-resolvebaseurl-in-src-env-ts
feature/issue-66/implement-totoolerror-in-src-errors-ts
feature/issue-65/implement-src-defaults-ts-shared-constants-and-app
feature/issue-64/scaffold-the-victorialogs-pi-extension-project
feature/issue-53/skip-issue-creation-for-chore-documentation-commit
feature/issue-45/fix-local-install-preflight-env-var-requirements-s
feature/issue-41/add-npm-run-local-install-script-to-update-and-ins
feature/issue-26/cross-reference-forgejo-list-milestones-from-issue
feature/issue-25/add-forgejo-milestone-delete-tool
feature/issue-24/add-forgejo-milestone-close-and-forgejo-milestone
feature/issue-23/add-forgejo-milestone-edit-tool
feature/issue-22/add-forgejo-milestone-view-tool
feature/issue-21/add-forgejo-list-milestones-tool
feature/issue-20/add-forgejo-milestone-create-tool
feature/issue-18/add-forgejo-label-create-tool
feature/issue-29/bug-forgejo-issue-create-view-edit-close-etc-crash
No results found.
Labels
No labels
bug
chore
documentation
enhancement
feature
ready
Milestone
Clear milestone
No items
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".
No due date set.
Dependencies
No dependencies set
Reference
david/pi-extensions-and-skills#194
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Implement the staged-changeset store and the two design-token primitives,
penpot_create_colorandpenpot_create_typography. Primitives stage changes rather than writing them, so a whole design system (or a whole screen) can be applied as a singleupdate-filecall in a later step.Background
Depends on: #193
This is the first write-side step, and the architecture it establishes is deliberate: Penpot shape and asset ids are client-generated, so the extension can build a complete change list offline and apply it in one call.
update-fileapplies changes in order, so a parent and its children are created atomically, a rejected batch applies nothing, and the file's revision advances exactly once.Three pieces are needed:
changes[], and the baserevnobserved when staging began. Keyed by file id so two files can be staged independently.{ type: "add-color", color: { id, name, color: "#RRGGBB", opacity } }, which lands atdata.colors.<id>. Theidis a client-generated UUID.{ type: "add-typography", typography: { id, name, fontId, fontFamily, fontVariantId, fontSize, fontWeight, fontStyle, lineHeight, letterSpacing, textTransform } }— all fields are required, and the server does not validate the font against the team's font list. A typography naming a font the instance does not ship is accepted but will not render as intended, so the tool must resolve fonts deliberately and record substitutions (see below).Nothing here performs an HTTP write; the commit step does that. Keeping the payload construction pure is what makes the write path testable without a live instance.
Documentation Required
A separate process downloads these into the listed folders before this issue is implemented. Check the folders for the actual reference material before starting.
docs/reference/penpot-api/<PENPOT_URL>/api/main/doc/openapi.json— theupdate-filecommand and the change-type union; confirmadd-colorandadd-typographyparameter shapes on this instance.docs/reference/pi-coding-agent/anddocs/reference/typebox/Type.Object,Type.Optional,Type.Number,Type.String; how to express a hex-colour pattern and numeric ranges.Implementation Details
extensions/penpot/src/changeset.ts— pure, unit-testedcreateChangeset(fileId)/stageChange(state, change)/discardChangeset(fileId)/changesetStatus(fileId).{ fileId, revn, changes: Change[], createdAt }, held in a module-levelMap<fileId, Changeset>.newId()— client-side UUID generation usingcrypto.randomUUID()(Node built-in). Every staged asset/shape gets one at stage time.describeChanges(changes)— a human-readable, deterministic preview used by both this milestone's status reporting and the commit preview: one line per change (add-color "flip7-gold" #2BA8A2,add-typography "h2" Inter 24/600).changesetStatus()output: target file, baserevn, change count by type, and the preview lines.extensions/penpot/src/tools/tokens.ts— the two toolspenpot_create_color— paramsfile_id,name,color(hex#RRGGBB, or#RRGGBBAAsplit into hex + opacity),opacity(0–1, optional, default 1). Validate the hex format before staging and reject anything else with a clear message.penpot_create_typography— paramsfile_id,name,font_family(e.g.Inter),font_size(number),font_weight(e.g.400/600/700),font_style(normal/italic, defaultnormal),line_height(number, default 1.2),letter_spacing(number, default 0),text_transform(defaultnone).get-font-variantsfor the team and pick the closest available variant; fall back to a documented default when the requested family is absent. Never invent afontId."Inter requested → Source Sans Pro used (not installed on this instance)") so the agent can report it rather than silently producing a design that will not render as intended.file_idthat is not the current staged target (or a target with staged changes for a different file) with a clear message — the changeset is per file and mixing files would be a silent data-integrity bug.Do not add an HTTP write here. Do not add an
update-filecall.Acceptance Criteria
penpot_create_colorstages anadd-colorchange with a client-generated UUID and the exact payload shape{type, color: {id, name, color, opacity}}.penpot_create_typographystages anadd-typographychange with every required field present and a font id resolved from the instance's font variants.penpot_discard(or equivalent status/discard tool) clears them and reports what was discarded.revn, change counts and a deterministic preview.file_idin the same session is handled explicitly (either isolated per file or refused with a clear message) — never silently merged.update-filecall is made.Test Plan
Live sanity check of the read half (which fonts exist), requires
PENPOT_URL/PENPOT_TOKEN:get-font-variantsfor the team (via the client or a temporary debug path) and confirm the resolvedfontId/fontVariantIdvalues come from that list.revn(the actual commit is validated in the next step).pi-loop opened and merged a pull request for this issue: #227