Skip to content

fix: finish Prime feedback follow-ups (Korean wrap, heading margins, asset/theme/variant evidence) - #121

Draft
devfive-relay-c70423[bot] wants to merge 7 commits into
mainfrom
devfive/3099154426bffbeef8b62999b80bb038/prime-feedback-followups
Draft

devfive-relay-c70423[bot] wants to merge 7 commits into
mainfrom
devfive/3099154426bffbeef8b62999b80bb038/prime-feedback-followups

Conversation

@devfive-relay-c70423

Copy link
Copy Markdown
Contributor

Follow-up to #119. Implements the remaining MCP-scope Prime feedback items (002, 006, 007, 008, 011, 014, 016, 032) plus today's axe-core 4.14 lesson. The audit is in reports/prime-feedback-2026-11.md → "Follow-up (2026-11-10)".

Changes per item

016 Korean wrapping (user decision: keep word boundaries, avoid large trailing gaps)

  • Korean text keeps wordBreak="keep-all" + overflowWrap="break-word" and now also emits textWrap="pretty".
  • Text with whiteSpace pre/nowrap gets no textWrap: CSS text-wrap is a shorthand that resets text-wrap-mode to wrap, so it would turn soft wrapping back on. An explicit local or theme textWrap is kept.
  • The textWrap evidence cites characters/textAutoResize/maxLines/width instead of a full copy of styledTextSegments. This keeps the real wquw-118 inline response under the 1 MiB limit.
  • delivery-quality.md reverses fix: preserve Prime layout contracts and require Figma-backed completion #119's "Do not apply keep-all solely because text is Korean". A diff caused only by Figma's mid-word Korean break is now a documented policy difference, and the native Figma reference is never overwritten to make it pass. The korean-word-boundary validate rule's next action now matches this.

002 Heading margins: semantic h1–h6 emits my="0px" unless the node already has m/my/mt/mb. It comes with a verified semantic-stage property derivation.

006 Asset placeholder collisions

  • Extra fills were {stem}-{index}, so fill 2 of hero and a second hero asset (deduped to hero-2) were both hero-2.png. They are now {stem}--fill-{index}, with the 0-based index from {nodeId}:fills:{index}. Stems are kebab-case with collapsed hyphens, so -- can't appear in any other asset's stem.
  • The "one placeholder identifies different pictures" refusal now lists the conflicting assetId/nodeId/imageHash/canonicalPath. It recommends assetNamesPerNode:true only when the image hashes differ. Shared-hash naming is deliberate and unchanged (that flag can't split those names), so in that case the error points to separate exports or binding each element's src through sourceMap nodeId/assetId.
  • Behavior change: extra-fill file names change from x-1.png to x--fill-1.png. Existing collision guards and the shared-hash naming test are unchanged.

007 missing-only theme: every devupJson response now carries devupJsonScope (complete-theme / used-tokens / additions-only). Missing-only also adds devupJsonMerge (target, deep-merge strategy, instruction). A missing-only devupJson outputPath named devup.json is refused before any Figma call, because writing the fragment there would replace the theme.

008 Hidden masters: componentSetVariants reports per-variant visible and allVariantsHidden. When every variant of a COMPONENT_SET or master export is hidden, the response adds a DEVUP_HIDDEN_MASTER_EXPORT warning. It lists the hidden variant ids and any visible instances in the snapshot, and says to export the visible page INSTANCE instead.

011 Asset per-outputPath state

  • Rows now carry fileFacts (exists/bytes/sha256 read from disk) and outputPathRedirected.
  • Every not-written row has a fileStateReason: blocked or rolled-back write, different bytes kept by the collision guard, quarantine, failed transaction, not acquired, or duplicate. These rows also carry requestedPathFacts.
  • Grayscale reuse of a colour original is reported as written and redirected, not as not-written. A test covers this.

014 / 032 / axe-core 4.14 (guidance only, delivery-quality.md; manifest bytes/sha updated)

  • 014: validation messages must not collapse the input's width. E2E asserts input bounds, visibility, focus and the message in the error state.
  • 032: report CI failures by the stage that failed, with the original message. Local pass, remote CI pass, push rejection and transient HTTP errors are separate evidence. When a push is rejected, finish independent work and leave a patch.
  • axe-core 4.14: label-content-name-mismatch is now in wcag21a. Drop redundant aria-labels, make labels contain the visible text verbatim, use sr-only text for hints, and never disable the rule.

Test evidence

  • cargo fmt --all -- --check: pass.
  • cargo clippy --locked --workspace --all-targets --all-features -- -D warnings: pass.
  • cargo insta test --workspace --all-features --check: 2260 passed / 1 failed / 2 ignored locally on Windows. The failure is r3_cancelled_client_recovers_retained_asset_job, which uses virtual time and is load-dependent. It also failed in the full run before any asset_jobs change in this branch, and it passed 4/4 when its own test binary ran alone. It was left unchanged.
  • Snapshots: 13 wquw_151 snapshots add only textWrap="pretty" lines and their property evidence. Seven pinned plugin goldens add exactly 15 textWrap="pretty" lines (applied with DEVUP_FIXTURE_UPDATE); their checksums are synced and the change is recorded in the fixtures README.
  • node --test crates/devup-mcp-figma/tests/explore_script_behavior.mjs plugin/tests/withdraw.test.mjs harness/runtime-audit/test/checks.test.mjs: 83 tests, 82 pass, 0 fail.
  • Harness browser suite (harness/runtime-audit, npm test): 96 tests, 95 pass, 1 skipped (CI-only gate), 0 fail.
    • New check: generated code compiles with the installed Devup UI.
    • Computed styles: word-break: keep-all, text-wrap-style: pretty, text-wrap-mode: nowrap for intrinsic-width pre text, and every line break on a word boundary.
    • With no reset stylesheet, the generated h2 has 0px top and bottom margins.

Out of scope (unchanged)

  • 005: blend/backdrop compositor.
  • 009: Devup UI compiler transform of polymorphic Link.
  • 013: Vite watcher/HMR.
  • 029: the application's own destructive postprocessor.

Note: pushing to devfive-relay-c70423/prime-feedback-followups was declined by the pre-receive hook. The branch was pushed under the repository's usual devfive/<id>/… prefix instead.

🤖 Generated with Claude Code


Submitted via Devfive hub. Employee: ; device: 3099154426bffbeef8b62999b80bb038

leader and others added 7 commits November 10, 2026 00:02
…set heading margins

Korean text keeps wordBreak keep-all and overflowWrap break-word and now
also emits textWrap pretty so keep-all no longer leaves large trailing
gaps. textWrap is a shorthand that resets text-wrap-mode to wrap, so it is
never added to whiteSpace pre/nowrap text. Semantic h1-h6 conversion
resets user-agent block margins with my=0px unless a margin exists.

Shipped delivery guidance now states the Korean wrapping policy (a diff
caused only by Figma's mid-word Korean break is a documented policy
difference; never overwrite the native reference), the validation-error
input width contract, CI stage reporting and the axe-core 4.14
label-content-name-mismatch lesson.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…ceholder a workable recovery

Extra image fills were named {stem}-{index} while a different asset with
the same base name was deduplicated to {stem}-2, so fill 2 of one asset and
a second asset both became stem-2.png. Extra fills are now
{stem}--fill-{index} (0-based, as in {nodeId}:fills:{index}); stems never
contain a double hyphen, so they cannot collide with any asset stem.

The refusal for one code placeholder resolving to two pictures always
recommended assetNamesPerNode:true, which cannot help when the nodes share
one imageHash (naming deliberately follows the shared image). The error now
lists the conflicting assets/nodes/paths, recommends the per-node flag only
when the hashes differ, and otherwise points to separate exports or
sourceMap nodeId/assetId binding.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
A missing-only devupJson holds only tokens absent from the project's
devup.json, yet nothing on the response said so and themeCompleteness
still read used-tokens. Every devupJson response now carries
devupJsonScope (complete-theme, used-tokens or additions-only); missing-only
adds devupJsonMerge with the target file, a deep-merge/add-missing-keys
strategy and an explicit instruction. A missing-only devupJson outputPath
named devup.json is refused before any Figma call, since saving the
fragment there would replace the project theme.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
A COMPONENT_SET or master export whose every variant is hidden generates
display=none code that renders nothing and carries none of the page's
overrides. componentSetVariants now reports per-variant visibility and
allVariantsHidden, and such exports add a DEVUP_HIDDEN_MASTER_EXPORT
warning listing the hidden variants and any visible instances in the
snapshot, telling the agent to export the visible page INSTANCE instead.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…utput path

Asset job rows only explained pending files. Each projected output path now
carries fileFacts (exists, bytes, sha256 read from disk) and
outputPathRedirected when the canonical file lives elsewhere than the
requested path (shared identical bytes, derived grayscale reuse). A
not-written row states why: missing after a blocked/rolled-back write,
different bytes kept by the collision guard, quarantine for naming review,
a failed projection transaction, no acquisition, or a duplicate delivered
at another asset's path, with requestedPathFacts for the requested path.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Only textWrap="pretty" lines and their property-evidence entries are added;
the seven pinned plugin snapshots change by fifteen textWrap lines and their
LF-normalized checksums are synchronized with a README entry.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…d follow-up

The harness compiles generated code with the installed Devup UI and checks
computed keep-all, text-wrap-style pretty, nowrap for intrinsic-width text,
word-boundary line ends and a 0px h2 margin without a reset stylesheet.
The Prime feedback report maps 002/006/007/008/011/014/016/032 and the
axe-core 4.14 lesson to this follow-up and names what stays out of scope.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants