From e5dd31d95b3fff8696993a51d14689a6f6d2d20b Mon Sep 17 00:00:00 2001 From: changepacks Date: Sun, 13 Sep 2026 19:23:05 +0000 Subject: [PATCH] Update Versions --- .changepacks/changepack_log_bridge_asset_delivery.json | 8 -------- .changepacks/changepack_log_build_identity_race.json | 7 ------- .../changepack_log_cropped_export_background.json | 7 ------- .changepacks/changepack_log_devfive_lifecycle.json | 9 --------- .changepacks/changepack_log_fidelity_and_exactness.json | 8 -------- .changepacks/changepack_log_figma_bridge.json | 8 -------- .changepacks/changepack_log_hard_break_whitespace.json | 5 ----- .changepacks/changepack_log_integration_0_4_6.json | 9 --------- .changepacks/changepack_log_line_box_displacement.json | 8 -------- .changepacks/changepack_log_lone_child_alignment.json | 8 -------- .changepacks/changepack_log_notice_layout.json | 7 ------- .changepacks/changepack_log_original_image_bytes.json | 5 ----- .changepacks/changepack_log_resolved_text_weights.json | 8 -------- .changepacks/changepack_log_self_description.json | 7 ------- .changepacks/changepack_log_single_outside_edge.json | 5 ----- .changepacks/changepack_log_wave_24.json | 8 -------- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- 18 files changed, 5 insertions(+), 122 deletions(-) delete mode 100644 .changepacks/changepack_log_bridge_asset_delivery.json delete mode 100644 .changepacks/changepack_log_build_identity_race.json delete mode 100644 .changepacks/changepack_log_cropped_export_background.json delete mode 100644 .changepacks/changepack_log_devfive_lifecycle.json delete mode 100644 .changepacks/changepack_log_fidelity_and_exactness.json delete mode 100644 .changepacks/changepack_log_figma_bridge.json delete mode 100644 .changepacks/changepack_log_hard_break_whitespace.json delete mode 100644 .changepacks/changepack_log_integration_0_4_6.json delete mode 100644 .changepacks/changepack_log_line_box_displacement.json delete mode 100644 .changepacks/changepack_log_lone_child_alignment.json delete mode 100644 .changepacks/changepack_log_notice_layout.json delete mode 100644 .changepacks/changepack_log_original_image_bytes.json delete mode 100644 .changepacks/changepack_log_resolved_text_weights.json delete mode 100644 .changepacks/changepack_log_self_description.json delete mode 100644 .changepacks/changepack_log_single_outside_edge.json delete mode 100644 .changepacks/changepack_log_wave_24.json diff --git a/.changepacks/changepack_log_bridge_asset_delivery.json b/.changepacks/changepack_log_bridge_asset_delivery.json deleted file mode 100644 index 7edf42a4..00000000 --- a/.changepacks/changepack_log_bridge_asset_delivery.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "changes": { - "crates/devup-mcp-figma/Cargo.toml": "Patch", - "crates/devup-mcp/Cargo.toml": "Patch" - }, - "note": "Return native bridge asset bytes without the remote MCP file writer. The native Plugin API has no figma.io, so successful small PNG and SVG exports were converted to DEVUP_ASSET_EXPORT_FAILED when the script tried to write an attachment. The script now carries bounded binary bytes and MIME directly in the bridge JSON response, while preserving remote attachment and fragment limits and existing hash validation. The plugin bundle is rebuilt from the same source. This fixes delivery, not whole-node versus isolated-fill composition; the about hero contract and the outstanding live-pixel validation are documented separately, and no visual improvement or eleven-second latency improvement is claimed.", - "date": "2026-09-14T01:13:00+09:00" -} diff --git a/.changepacks/changepack_log_build_identity_race.json b/.changepacks/changepack_log_build_identity_race.json deleted file mode 100644 index bdee90ad..00000000 --- a/.changepacks/changepack_log_build_identity_race.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "changes": { - "crates/devup-mcp/Cargo.toml": "Patch" - }, - "note": "Stop failing a build-identity test for something that is not a defect. The test compared the -dirty suffix baked into the binary at compile time against a git status it ran itself at test time, which are two observations of the working tree taken at two different moments; an untracked file appearing in between, a probe script or a scratch log, made a correctly behaving binary report clean while the test's own git call reported dirty, and the assertion failed with no bug to find. It failed that way during the line-box investigation. The build script now publishes what it actually observed, DEVUP_MCP_GIT_DIRTY as true, false or unknown when git could not be asked, together with DEVUP_MCP_BUILD_ID_SOURCE recording whether the identity came from git or from an injected DEVUP_MCP_BUILD_ID, and the test asserts against those build-time facts instead. What stays under test is the chain that can actually break: the git observation, the suffix git_identity derives from it, and --version printing the baked value faithfully; an injected identity carries whatever suffix its caller chose and an unknown observation says nothing about this plumbing, so neither is asserted. The run-time comparison remains as a note on stderr, because a tree that moved between building and running is information about the run rather than a fault in the binary.", - "date": "2026-09-12T21:40:00+09:00" -} diff --git a/.changepacks/changepack_log_cropped_export_background.json b/.changepacks/changepack_log_cropped_export_background.json deleted file mode 100644 index 4616bda6..00000000 --- a/.changepacks/changepack_log_cropped_export_background.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "changes": { - "crates/devup-mcp-devup-ui/Cargo.toml": "Minor" - }, - "note": "Stop cropping a photograph twice. A CROP image fill carries its framing as a matrix over the image's own coordinate space, and the generator read that matrix and turned it into a CSS background position and size. That would be right if the file being positioned were the original image, but it is not: the emitted file is a node export, and Figma has already applied the crop when producing those pixels. Applying the matrix again framed an already-framed picture, which is why the about page's photographs came out zoomed and offset against Figma's own render of the same frame - and why the earlier attempt to honour the crop appeared to help while measuring worse. A cropped fill now maps its exported frame once onto the layout box, and the matrix reader is deleted rather than left for someone to reach for again; FIT, FILL and TILE are unchanged. Measured against Figma's reference PNG, the three about screens improve from 7.46, 4.06 and 2.41 percent to 5.51, 3.01 and 1.77, with page heights unchanged and every other screen byte-identical. All 268 plugin byte-parity goldens are unchanged, and the responsive-screen expectation that asserted the old doubled crop is corrected to state why the export is mapped once.", - "date": "2026-09-13T14:15:00+09:00" -} diff --git a/.changepacks/changepack_log_devfive_lifecycle.json b/.changepacks/changepack_log_devfive_lifecycle.json deleted file mode 100644 index 43374d96..00000000 --- a/.changepacks/changepack_log_devfive_lifecycle.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "changes": { - "crates/devup-mcp-devup-ui/Cargo.toml": "Minor", - "crates/devup-mcp-visual/Cargo.toml": "Minor", - "crates/devup-mcp/Cargo.toml": "Minor" - }, - "note": "Extend the server past design projection into the rest of the DevFive lifecycle. Expose the existing pure-Rust PNG comparison as devup_visual_compare, where an unattested or invalid renderer environment makes the verdict inconclusive rather than a pass. Add devup_feature_trace, which turns caller-supplied anchors into a screen-to-API-to-route-to-model-to-column slice and refuses to read requirement prose as an anchor. Map route columns by parsing schema_type! pick and omit declarations instead of matching substrings, recognise the remaining devup-api call forms, and attach source ownership so a drift never proposes editing a generated artifact. Validate DevFive client-boundary, file-placement, export-shape, query-state and inline-style conventions from a bounded in-memory file bundle. Return ranked component reuse evidence under a project context ui scope that stays out of all. Fingerprint each design node over the fields the converter reads so a re-export can name what changed. Emit a preview-first page scaffold file set whose writes are opt-in and refuse collisions atomically through the existing rollback.", - "date": "2026-09-12T13:36:58+09:00" -} diff --git a/.changepacks/changepack_log_fidelity_and_exactness.json b/.changepacks/changepack_log_fidelity_and_exactness.json deleted file mode 100644 index bec79755..00000000 --- a/.changepacks/changepack_log_fidelity_and_exactness.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "changes": { - "crates/devup-mcp-devup-ui/Cargo.toml": "Patch", - "crates/devup-mcp/Cargo.toml": "Minor" - }, - "note": "Stop painting words the design does not contain, parse route declarations instead of scanning for quotes, and let a re-export name what went stale. The text emitter no longer lets JSX insert a space where the design has none and no longer turns a design line break into a space; a 466-text sweep now round-trips every text node against a browser whitespace model, Unicode and non-breaking spaces survive, and the CSS collapse that no emission can avoid is reported as an explicit finding rather than silently painted. Vespera route attributes are parsed as Rust rather than matched with a quote scan, so a path inside a comment, a doc comment or an unrelated macro is no longer mistaken for a route, raw strings and multi-line attributes resolve, and a cfg-gated handler is reported conditionally instead of being claimed as present; unresolved files keep the old check under a separate lower-confidence kind and no finding is promoted above medium, because a successful parse is not proof of complete scanning. Design fingerprints can now be written as a guarded versioned sidecar and compared on a later export, returning unchanged, changed, added and removed nodes together with an explicit statement that a change means a converter input moved, not that the rendered screen changed and not that the code on disk still matches.", - "date": "2026-09-12T18:20:00+09:00" -} diff --git a/.changepacks/changepack_log_figma_bridge.json b/.changepacks/changepack_log_figma_bridge.json deleted file mode 100644 index 9128a4c4..00000000 --- a/.changepacks/changepack_log_figma_bridge.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "changes": { - "crates/devup-mcp-figma/Cargo.toml": "Minor", - "crates/devup-mcp/Cargo.toml": "Minor" - }, - "note": "Read a design without spending the quota. Collection runs through the official MCP's use_figma, and that is the call Figma meters, so a handful of screens exhausts the allowance; every script devup-mcp sends uses only the standard Plugin API, so a plugin of our own can serve them. A plugin cannot accept connections, so devup-mcp listens on 127.0.0.1 and the plugin dials in, and a read is routed before the call by asking whether the bridge can serve it rather than by catching a failure, because CapabilityUnavailable and a transport fault arrive as the same error code and a failure cannot tell them apart. No code crosses the socket: the twelve scripts are wrapped into the plugin at build time from the same sources the remote path uses, the build fails on an unsubstituted placeholder, and devup-mcp sends only the name of the script to run. With no plugin attached every call falls through to the remote path unchanged, and DEVUP_FIGMA_BRIDGE_PORT=off closes the door entirely. Three things only a real install revealed are now handled: ws://127.0.0.1 invalidates the whole manifest so the address must be localhost, a plugin that reports no file key registers and serves any key while it is the only one attached rather than leaving the window claiming a connection it never uses, and a fileKey permission entry stops the plugin loading at all. Speed followed: pagination sized for a 20,480-byte truncation collapses to one page over a local socket, the transport now says how many resources one question carries instead of a constant, and a used-resource call that took 21.4 seconds regardless of load turned out to be waiting out a fixed timeout on every individual variable lookup and returning null, which named every bound token after the tail of its id; the file's own variables are read once and indexed, leaving individual lookups only for genuine library ids, and that call now answers in 24 milliseconds with nothing unresolved. Asset export still fails with the same fixed-delay signature and is not fixed here.", - "date": "2026-09-13T23:40:00+09:00" -} diff --git a/.changepacks/changepack_log_hard_break_whitespace.json b/.changepacks/changepack_log_hard_break_whitespace.json deleted file mode 100644 index 3ea847f5..00000000 --- a/.changepacks/changepack_log_hard_break_whitespace.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "changes": { "crates/devup-mcp-devup-ui/Cargo.toml": "Minor" }, - "note": "The painted text is the text again, in one more place. A space the designer typed before an explicit line break is collapsed away by CSS, so a paragraph that reads one way in Figma read another way on screen. W8 established that painted text must equal characters and reported the remaining collapse as an explicit finding because no emission it had could avoid it; pre-wrap avoids it for a bounded case, so that case moves from reported to fixed and the diagnostic stays for everything still unavoidable. The condition is narrow on purpose: TEXT whose inline width Figma fixes while the height grows, with no positive maxLines, no list options, no tabs, and a space actually adjacent to a break. HUG text is excluded because pre-wrap counts trailing spaces in max-content width and would change intrinsic sizing, and clamped text keeps its existing projection. Korean word breaking is untouched. Four plugin goldens gain six whiteSpace attributes, each reviewed against its collected fixture, because the plugin drops a space the design contains - the opposite of the keep-all case, where matching Figma would have produced worse Korean and the compensation was deliberately kept. The source map gains derived-hard-break-whitespace, whose description states that it preserves source whitespace without claiming intrinsic HUG sizing, glyph parity or identical wrapping, and one lossy fidelity impact is retired rather than left double-counted alongside the diagnostic. Measured against Figma's reference PNG, about mobile improves from 5.51 to 5.43 percent, about tablet from 3.01 to 2.93, landing mobile from 4.99 to 4.78 and notice mobile from 3.84 to 3.74, with the other eleven screens unchanged.", - "date": "2026-09-13T22:10:00+09:00" -} diff --git a/.changepacks/changepack_log_integration_0_4_6.json b/.changepacks/changepack_log_integration_0_4_6.json deleted file mode 100644 index 905f7ed7..00000000 --- a/.changepacks/changepack_log_integration_0_4_6.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "changes": { - "crates/devup-mcp-devup-ui/Cargo.toml": "Minor", - "crates/devup-mcp-figma/Cargo.toml": "Minor", - "crates/devup-mcp/Cargo.toml": "Minor" - }, - "note": "The 0.4.6 line, landed on main at last. R20 audits what still stands between the generator and a browser-measured claim, naming each remaining approximation rather than leaving the gap implicit. F1-F5 and F7 carry the responsive and project-context corrections: prevalidating a responsive export before it is projected, discovering breakpoint widths from the frames rather than assuming them, reconciling exported tokens against the theme a project already has, categorising token suggestions so an unmatched value is not advised toward a token that does not exist, budgeting a Section preview so a large selection cannot exhaust the projection, covering FILL layout where it was previously approximated, and reporting a typography token the validator had never been checking. F8 teaches devup-ui semantics to the caller and delivers skills through the CLI. The branch had never passed CI: ten rustfmt violations rode along with it, and they are fixed here rather than carried further. The bridge plugin's committed bundle is rebuilt because explore.js and section_index.js changed, and those scripts are compiled into the plugin - which is precisely the drift the new bundle gate exists to catch, and did.", - "date": "2026-09-14T00:30:00+09:00" -} diff --git a/.changepacks/changepack_log_line_box_displacement.json b/.changepacks/changepack_log_line_box_displacement.json deleted file mode 100644 index 15892c06..00000000 --- a/.changepacks/changepack_log_line_box_displacement.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "changes": { - "crates/devup-mcp-devup-ui/Cargo.toml": "Minor", - "crates/devup-mcp/Cargo.toml": "Minor" - }, - "note": "Make the generated screen stand where Figma draws it. Figma advances each line by round(fontSize * ratio) and the browser accumulates the fraction instead, so a percentage line height drifted a little on every line and compounded through hugging parents; the emitted advance is now the whole-pixel length rather than a ratio, and all seven measured text blocks match their design height exactly. Because a pixel advance is only valid for the size it was computed from, the resolved font size now travels with it, and a percentage line height whose font size is missing or bound to a mode-dependent variable is refused with a typed error naming the node or text style rather than emitted as a number that would be wrong at another size. The second half of the divergence was an inside stroke: Figma's inside stroke consumes no layout space, and the existing padding compensation cannot absorb a CSS border when the design's own padding is narrower than the stroke, so every bordered auto-layout container grew by twice its stroke weight and pushed the sections below it down. That case now paints inward with an outline at a negative offset, taking no layout space at all, and the padding compensation stands down for it; the choice keys on stroke alignment, layout mode, and stroke weight against padding, never on a viewport width, so it survives a design redrawn at another size. Source map and provenance follow the new emission: outline and outlineOffset carry their stroke provenance, and a rich-text wrapper's own advance is attributed to the segment whose text follows it. Twenty-four plugin goldens change, each enumerated with its reason in docs/line-box-displacement.md; the corpus consistency test and the manifest checksums are unchanged in force. Measured on the landing screen against Figma's own PNG, the three widths move from 11.41 / 3.10 / 1.84 percent to 4.99 / 2.47 / 1.50 percent, and the rendered height now equals the design height at all three.", - "date": "2026-09-12T23:55:00+09:00" -} diff --git a/.changepacks/changepack_log_lone_child_alignment.json b/.changepacks/changepack_log_lone_child_alignment.json deleted file mode 100644 index 5207090d..00000000 --- a/.changepacks/changepack_log_lone_child_alignment.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "changes": { - "crates/devup-mcp-devup-ui/Cargo.toml": "Minor" - }, - "note": "A single child is not distributed. Figma centers the only in-flow child of a SPACE_BETWEEN auto-layout; CSS flexbox has nothing to space between and parks that child at the start, so every such node was generated in the wrong place. The keyframes screen made it visible because it is 64 pixels across and built from single-dot wrappers: a 2px dot that Figma draws at x=5 inside a 12px box was drawn at x=0, and the same wrappers recur on the notice desktop frame. The emitter now reads the distribution as center when the layout is horizontal or vertical, the alignment is SPACE_BETWEEN, and exactly one child is both visible and not absolutely positioned, because hidden and absolute children take no part in distribution and must not be counted. The source map gains derived-lone-child-center rather than reusing an existing label, and its published description states which fields decide the count and that the mapping is a layout-semantics correspondence rather than a claim of pixel parity. Measured against Figma's reference PNG, keyframes falls from 6.71 to 2.69 percent and notice desktop from 2.20 to 1.88, with every other screen byte-identical and all 268 plugin byte-parity goldens unchanged. The investigation also retired a standing theory with evidence: the harness disables animations, so this screen's divergence was never the animation being caught mid-flight. The 110 pixels that remain are circle edges, and the report names fractional paint origins and edge coverage as the next lead rather than guessing at a cause." -, - "date": "2026-09-13T16:20:00+09:00" -} diff --git a/.changepacks/changepack_log_notice_layout.json b/.changepacks/changepack_log_notice_layout.json deleted file mode 100644 index 97306162..00000000 --- a/.changepacks/changepack_log_notice_layout.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "changes": { - "crates/devup-mcp-devup-ui/Cargo.toml": "Minor" - }, - "note": "Two layout defects on the notice screens, found the week the harness stopped hiding them. A horizontal row can overflow collectively even when every child fits on its own, and CSS min-width:auto then refuses to let a FILL sibling shrink to its share: a navigation item Figma draws at 95px expanded to 316px, pushed an address block onto three extra lines, and made the tablet page 72px taller than the design. The existing minW=0 rule already covered the case where a single child is wider than its parent; it now also covers the row that only overflows once its children are added together, still measured from the snapshot rather than assumed, still skipped when the design states its own minWidth, and applied only to non-wrapping horizontal rows because a wrapping row distributes that content over more lines instead. Separately, an SVG mask with an export offset was refused a folded layout size outright, so a social icon the design gives 82x32 was generated at zero width and everything below it shifted. The refusal exists because a FILL axis would scale the layout box while the pixel mask offsets stay where they are, and because a positioned or free-layout asset is placed from its export box; none of that applies to an in-flow HUG or FIXED axis, which keeps its measured box while maskSize and maskPos go on describing the larger painted bounds. Both conditions read node fields only - layout mode, wrap, sizing, positioning, and measured widths - so neither carries a viewport, a breakpoint, a node id, or a constant fitted to the current capture. Measured against Figma's own PNG, the three notice screens improve from 5.54 / 3.35 / 2.22 to 5.25 / 3.22 / 2.20 percent, the tablet page height falls from 72 pixels over the design to 3, and the other twelve screens are byte-identical. All 268 plugin byte-parity goldens are unchanged.", - "date": "2026-09-13T13:05:00+09:00" -} diff --git a/.changepacks/changepack_log_original_image_bytes.json b/.changepacks/changepack_log_original_image_bytes.json deleted file mode 100644 index 922cec9b..00000000 --- a/.changepacks/changepack_log_original_image_bytes.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "changes": { "crates/devup-mcp-figma/Cargo.toml": "Minor" }, - "note": "Original image bytes can now be read, and two screens are explained rather than improved. A CROP fill names its source by hash, but nothing could fetch the pixels behind that name: the official MCP returns text only, so the bytes had no transport, and the connector tool that would supply them answers UNAUTHORIZED and belongs to the metered path in any case. The bridge has no such limit - it is a local socket where nothing is truncated - so a read-only getImageByHash route now retrieves the selected fill's original bytes with their intrinsic codec, never a whole-node rendition, and decodes and verifies them against the declared hash. The remote path refuses the request outright with a named reason rather than returning a node PNG that looks like an answer; that refusal is the more valuable half, because a silently wrong image is worse than a missing one. No document is mutated: the temporary-rectangle technique that would have produced an isolated rendition creates and removes nodes and was rejected for that reason. The isolated-fill renderer that would consume these bytes is not implemented and no pixel improvement is claimed, because capturing live source bytes requires re-importing the rebuilt plugin in Figma, which is a desktop menu action; the report names the exact capture - file, node, fill index, hash and call - so it needs no rederiving. Separately, the landing mobile residual is quantified rather than fixed: with identical DOM geometry, a Chromium probe with LCD subpixel antialiasing disabled measures 2.91 percent where the harness measures 4.78, which attributes a large part of that screen's divergence to font rasterization rather than to generated layout, and leaves residual glyph advances needing separate evidence.", - "date": "2026-09-14T06:00:00+09:00" -} diff --git a/.changepacks/changepack_log_resolved_text_weights.json b/.changepacks/changepack_log_resolved_text_weights.json deleted file mode 100644 index 9706649b..00000000 --- a/.changepacks/changepack_log_resolved_text_weights.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "changes": { - "crates/devup-mcp-devup-ui/Cargo.toml": "Minor", - "crates/devup-mcp/Cargo.toml": "Minor" - }, - "note": "Stop losing bold. A text node whose segments share a typography token can still override the weight per run, and both text emitters suppressed fontWeight whenever a token was present, so alternating 400/700 runs came out uniform. The token name carries no resolved metrics, so nothing downstream could recover them. Missing bold changes glyph advances and therefore wrapping, which is how a lost weight became a layout defect: on the about screens one 36px line wrapped that the design does not wrap, and every section below inherited the displacement. Emitting the resolved weight alongside the token brings the rendered page height to within one pixel of the design at both wider widths, from 37 pixels over, and the measured divergence from Figma's own PNG falls from 6.90 to 4.06 percent at 992 and from 4.19 to 2.41 percent at 1920, paid for by 0.02 percent at 360. Segment-sourced weights are attributed to styledTextSegments in the source map while explicit node weights keep their node-property mapping, so the provenance says which one actually supplied the number. Korean keeps word-break: keep-all. Removing it was implemented and measured because Figma breaks Korean within words and matching that narrows the pixel gap, but it narrows it by 0.21 percent on one screen while chopping every Korean word in every generated screen and breaking 38 attributes across 17 plugin byte-parity goldens; the pixel metric is a proxy for correctness and this is where the two disagree. Figma's Korean line breaking is a limitation to compensate for rather than a specification to reproduce, which is the same call the plugin makes in its own text renderer, and a test now locks the behaviour so a later fidelity pass cannot quietly reverse it. One golden changes, for a segment that explicitly carries weight 400.", - "date": "2026-09-13T03:10:00+09:00" -} diff --git a/.changepacks/changepack_log_self_description.json b/.changepacks/changepack_log_self_description.json deleted file mode 100644 index 097b9954..00000000 --- a/.changepacks/changepack_log_self_description.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "changes": { - "crates/devup-mcp/Cargo.toml": "Minor" - }, - "note": "Stop charging every session for guidance most callers never read, and report build staleness on the identity every response already carries. The twelve numbered rules move out of the initialize instructions, which drop from about 3,500 bytes to 951, into a pulled devup://guide/usage resource; rule numbering is preserved and a test asserts no rule was lost in the move, and shipping the text inside the binary keeps it from drifting the way a README can. server.updateAvailable reports whether a newer release exists, distinguishing disabled, not-yet-run, ran-and-could-not-tell and known, and only the last ever claims staleness. The lookup runs in a background task on a daily interval and the response path reads a cache, so no tool call performs a network request and none can be delayed by one; doctor and --self-check stay network-free because the task starts from the initialize handler rather than from server construction. DEVUP_MCP_NO_UPDATE_CHECK disables it. The server never downloads or replaces its own binary, which it could not do anyway while the MCP host owns its stdio pipes.", - "date": "2026-09-12T16:05:00+09:00" -} diff --git a/.changepacks/changepack_log_single_outside_edge.json b/.changepacks/changepack_log_single_outside_edge.json deleted file mode 100644 index 287dc704..00000000 --- a/.changepacks/changepack_log_single_outside_edge.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "changes": { "crates/devup-mcp-devup-ui/Cargo.toml": "Minor" }, - "note": "A Figma outside stroke costs nothing; a CSS border always does. One straight OUTSIDE edge was emitted as a border, and a border either shrinks a fixed content box or grows a hugging one, so every node carrying a single top, right, bottom or left rule was generated at the wrong size and displaced whatever sat beside it. The narrow frames showed it worst because a divider rule repeats down a stacked mobile layout. Such an edge now paints as a zero-blur box shadow translated by its own weight, which occupies no space at all, and any real effects the node carries are composed after it so paint order survives. The projection is deliberately narrow: it applies only to an auto-layout node that is not an exported asset, whose stroke is OUTSIDE, solid, square-cornered, undashed, has no uniform strokeWeight, and has exactly one side with a positive weight. Rounded corners, dashes and multi-edge joins need a different construction and keep their existing emission rather than an approximation of one. The source map gains derived-single-edge-outside-stroke, whose published description states that this is a stroke projection and not an assertion that Figma supplied a shadow effect, not a claim about exported-asset composition, and not a claim of pixel parity. Measured against Figma's reference PNG the three notice screens improve from 5.25, 3.22 and 1.88 percent to 3.84, 2.12 and 1.16, with every other screen byte-identical and all 268 plugin byte-parity goldens unchanged.", - "date": "2026-09-13T19:55:00+09:00" -} diff --git a/.changepacks/changepack_log_wave_24.json b/.changepacks/changepack_log_wave_24.json deleted file mode 100644 index 65c65437..00000000 --- a/.changepacks/changepack_log_wave_24.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "changes": { - "crates/devup-mcp-devup-ui/Cargo.toml": "Patch", - "crates/devup-mcp-figma/Cargo.toml": "Minor" - }, - "note": "Three screens looked at in parallel; two produced a fix and one produced a boundary. A responsive module folds the same node across breakpoints into one tree, and where the widths supplied different images it wrote the source as a responsive array. An image source is not a responsive value in the way a length is: the element takes one URL, so the array made a source no width had asked for. Differing child images now emit scalar URLs and lean on the visibility merging that already exists for nodes present at only some widths. Separately, the bridge's asset export called a remote figma.io writer that does not exist on the plugin path, which is why every asset request failed at a fixed delay; the transport now delivers bridge assets without it, with the decoder tests written red first and the committed plugin bundle rebuilt because assets.js is compiled into it. The isolated-fill contract the about hero needs is now defined and its boundary validated - all eleven existing crops and all three flattened hero exports match their reference regions - but isolating the hero itself still requires authenticated source pixels and representation-aware export continuation, so it is specified rather than claimed. The grid screen is a documented negative: all 41,234 differing pixels sit in three photographs and source-coordinate placement reproduces every one of them, which rules out the grid track projection outright and leaves density-aware raster mapping as the named next lead. No Rust changed for it. Measured against Figma's reference PNG the three popup screens improve from 3.64, 2.06 and 0.85 percent to 3.58, 2.02 and 0.84, with every other screen byte-identical and all 268 plugin goldens unchanged.", - "date": "2026-09-14T02:30:00+09:00" -} diff --git a/Cargo.lock b/Cargo.lock index a1dc0be8..3ef97d0d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -693,7 +693,7 @@ checksum = "4583a4551df46e2792f82ceeac45e850d2e2d5debba0b91f102385cda5b11f06" [[package]] name = "devup-mcp" -version = "0.4.6" +version = "0.5.0" dependencies = [ "anyhow", "async-trait", @@ -722,7 +722,7 @@ dependencies = [ [[package]] name = "devup-mcp-devup-ui" -version = "0.4.6" +version = "0.5.0" dependencies = [ "devup-mcp-figma", "insta", @@ -739,7 +739,7 @@ dependencies = [ [[package]] name = "devup-mcp-figma" -version = "0.4.6" +version = "0.5.0" dependencies = [ "anyhow", "async-trait", @@ -766,7 +766,7 @@ dependencies = [ [[package]] name = "devup-mcp-visual" -version = "0.4.6" +version = "0.5.0" dependencies = [ "anyhow", "image", diff --git a/Cargo.toml b/Cargo.toml index faea5f32..e3df622c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ members = [ resolver = "3" [workspace.package] -version = "0.4.6" +version = "0.5.0" edition = "2024" rust-version = "1.98" license = "MIT"