From 62081ecf990482e0201f7c1590a8fecebd9b82b8 Mon Sep 17 00:00:00 2001 From: changepacks Date: Tue, 8 Sep 2026 10:19:43 +0000 Subject: [PATCH] Update Versions --- .../changepack_log_boolean_logo_pagination.json | 9 --------- .changepacks/changepack_log_fidelity_visibility.json | 8 -------- .changepacks/changepack_log_narrow_the_surface.json | 10 ---------- .../changepack_log_section_selection_guidance.json | 8 -------- Cargo.toml | 2 +- 5 files changed, 1 insertion(+), 36 deletions(-) delete mode 100644 .changepacks/changepack_log_boolean_logo_pagination.json delete mode 100644 .changepacks/changepack_log_fidelity_visibility.json delete mode 100644 .changepacks/changepack_log_narrow_the_surface.json delete mode 100644 .changepacks/changepack_log_section_selection_guidance.json diff --git a/.changepacks/changepack_log_boolean_logo_pagination.json b/.changepacks/changepack_log_boolean_logo_pagination.json deleted file mode 100644 index 4e5de6f..0000000 --- a/.changepacks/changepack_log_boolean_logo_pagination.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "changes": { - "crates/devup-mcp-figma/Cargo.toml": "Patch", - "crates/devup-mcp-devup-ui/Cargo.toml": "Minor", - "crates/devup-mcp/Cargo.toml": "Patch" - }, - "note": "Keep the vector operands of a Section screen that does not fit one page. A multi-root snapshot answers with a cursor when it has more nodes to give, and the collector read the first page and stopped, so on the two Loading screens of section 4279:7810 the twelve operands of two Boolean logos never arrived and the logos came out as grey boxes. The continuation is now followed to the end with the same Section and the same root set, and the cursor is checked rather than trusted: the offset has to be the one that was asked for, the next offset has to be the requested offset plus the nodes that came back, it may not pass the total, the complete flag has to agree with it, and a cursor that does not advance is refused. A continuation can no longer fall back to a legacy restart either, because the pages already accepted would be mixed with a second capture, and a first page is never cached as a finished design while operands remain unread. BOOLEAN_OPERATION is recognised as a vector asset, in asset discovery and in the single-colour test that decides between a masked Box and an Image, so the logo is exported as SVG and the generated TSX refers to those bytes. Fidelity gains uncoveredNodeIds: a declared child absent from both the snapshot and any asset projection is a hole nothing represents, so it counts against node coverage and as a lossy impact, where an operand deliberately flattened into an SVG does not. Verified against file 85CgSws3o5XsLv7aAwWJyS with cache bypassed - status partial to complete, 18 nodes to 30, 16 of 28 formats collected to 28 of 28, twelve missing formats to none, and both logos exported as SVG whose manifest, file hash, source map and TSX reference agree.", - "date": "2026-09-08T18:40:00+09:00" -} diff --git a/.changepacks/changepack_log_fidelity_visibility.json b/.changepacks/changepack_log_fidelity_visibility.json deleted file mode 100644 index 6bd52d3..0000000 --- a/.changepacks/changepack_log_fidelity_visibility.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "changes": { - "crates/devup-mcp/Cargo.toml": "Patch", - "crates/devup-mcp-devup-ui/Cargo.toml": "Patch" - }, - "note": "Send the fidelity report whenever it disagrees with the grade above it, rather than whenever the grade is not exact. Keying it on quality.projection was wrong in a way that hid a real defect: projection_quality is computed from diagnostics alone, so a coverage shortfall that raises no diagnostic leaves the grade reading exact and took the report away with it. Measured on a real 50-node screen, fidelity.variables was 19 of 20 - a $primary binding on an ellipse whose parent was exported as an SVG, so the theme colour is frozen into the file and cannot follow the theme - while quality.projection read exact. Before this the response showed that shortfall; after the first attempt it hid it. The condition is now strict_compatible, which is the same predicate strict: true refuses on, so the two cannot disagree about whether anything was lost. On the ten real captured screens it stays silent for every screen that has neither a shortfall nor an approximation, which is what the change was for. And stop expecting a binding the platform cannot carry. An asset drawn in one colour becomes a Box masked to its shape with bg set, so a token inside it survives as a token; an asset drawn in more than one has no such form, because a CSS mask carries alpha only and an SVG loaded through img src renders in its own document where neither currentColor nor a CSS variable reaches it. It becomes an Image and every colour inside is baked into the file. Counting those bindings as expected-but-missing asked the generator for something no correct implementation could produce: on the measured screen two play buttons each hide a bound circle behind a white glyph, which alone put the whole report on the response with nothing in it anyone could act on. Bindings inside a non-mask asset are excluded from the variables expectation, which on that screen moves it from 19 of 20 to 17 of 17. Across the ten captured screens the expectation drops from 658 to 528 and is fully covered, while six of the ten still send the report for their absolute-layout approximations - so the exclusion narrows what is expected rather than silencing what was found. Also names the commit outright when CI builds a release, instead of letting build.rs infer it. It infers by asking git for HEAD and whether the tree is dirty, and on a release build the tree always is: changepacks update moves the version in Cargo.toml and leaves Cargo.lock behind, so the first cargo invocation rewrites the lock and dirties the checkout. Every published binary reported its build id as -dirty, which is exactly the state --version and --self-check exist to tell apart from a developer working tree. Committing the lock fixed that instance and the next Update Versions pull request brings it straight back, so the build job now passes DEVUP_MCP_BUILD_ID, which build.rs already prefers. A local build still infers, so a dirty working tree still says so.", - "date": "2026-09-08T17:20:00+09:00" -} diff --git a/.changepacks/changepack_log_narrow_the_surface.json b/.changepacks/changepack_log_narrow_the_surface.json deleted file mode 100644 index b65e95c..0000000 --- a/.changepacks/changepack_log_narrow_the_surface.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": { - "crates/devup-mcp/Cargo.toml": "Minor", - "crates/devup-mcp-figma/Cargo.toml": "Minor", - "crates/devup-mcp-devup-ui/Cargo.toml": "Minor", - "crates/devup-mcp-visual/Cargo.toml": "Patch" - }, - "note": "Narrow what devup-mcp asks for and what it sends back, and make a refusal say which of the two kinds it is. Nine tools become seven: devup_figma_to_ui and devup_figma_to_json were devup_figma_export with a single entry in outputs, so every client carried three schemas in its context and had to decide between them on every call, and the export tool's own description had to spend a sentence saying which to prefer. Use outputs: [tsx] and outputs: [devupJson] instead. sourcePolicy is gone from all of them: auto and direct both meant the direct connection and the parameter never branched, so it only ever offered a caller something to get wrong, and it was also part of the artifact cache key it could not affect. Every remaining closed-set input now publishes its accepted values in the JSON schema - action, scope, rootLayout, delivery, match, project context scope and stack diff layers - from one shared constant the parser reads too, so the schema cannot drift from what is accepted and a caller stops discovering the set one rejection at a time; outputs and the asset format were the only two that already did this. Errors are no longer all INTERNAL_ERROR. A mistake in the call itself - an unknown scope, a node that is not in the file, an expired artifactId - is now JSON-RPC INVALID_PARAMS, and everything behind the call stays INTERNAL_ERROR, so an agent can tell 'fix the arguments and retry' from 'stop and report' without parsing the message; the exact code and retryable are unchanged in data. Pure argument validation that had been reported as DEVUP_THEME_CONFLICT or DEVUP_SNAPSHOT_UNSUPPORTED is DEVUP_INVALID_INPUT, so a real theme conflict is no longer confused with a typo. The response is lighter for the same content. Measured on one export, a tsx-only call went from 2,411 to 1,405 bytes and the part every response carries regardless from 1,911 to 994. fidelity and completenessReport are the drill-down beneath quality and on a clean result restate it - 100% across six axes, six empty arrays - so they are sent when the result is not exact or complete, or when includeDiagnostics asks for them; on a Section export that was per screen. imports, usedTokens, componentImports, responsiveImports and responsiveComponents restated the tsx's own import line and its $tokens and are gone. deliverable stays: it was removed on the reasoning that the needs_figma handoff it guarded against is gone, and a consumer reported relying on it to know which value is the answer, which settles it. The server instructions were the larger cost and are corrected: they told every agent to take tsx, rawSnapshot and sourceMap together, which on the same measurement is about eight times the bytes of the code, and they now say to ask for an output only when it will be read. completeness and themeCompleteness stay - they grade how far token resolution reached, which quality does not say. Releases stop shipping devup-mcp-visual: the render harness builds it from source with cargo and nothing downloads it, so three of six assets were binaries no consumer used, built on every platform of every release. Cargo.lock is committed at the released version, which stops every release binary reporting its build id as -dirty and losing the ability to tell a release from a developer's working tree. Also removes two ErrorCode variants no production code ever constructed, whose only reference was a test pinning their wire strings - a test that would have passed forever whether or not they were reachable. A binding the resource catalog never named is now reported rather than quietly resolved. A fill bound to a variable, or a text carrying a style, is the design saying this is a token; the generator writes the token when the catalog carried that resource and the resolved value when it did not, and it has to write something because the module still has to compile. It said nothing when it did, so a hardcoded #7d7f83 could sit where the design says - identical today, no longer following the theme tomorrow - inside a response graded exact. Each such binding now raises DEVUP_CODEGEN_TOKEN_NAME_UNRESOLVED carrying the node, the property and the resource id, which also stops quality.projection reading exact. The check runs as a pass over the collected subtree rather than inside rendering, so it can name the node without threading an argument through the render functions, and the 268 plugin-parity goldens are unaffected because the generated bytes do not change.", - "date": "2026-09-08T15:40:00+09:00" -} diff --git a/.changepacks/changepack_log_section_selection_guidance.json b/.changepacks/changepack_log_section_selection_guidance.json deleted file mode 100644 index c6a4e52..0000000 --- a/.changepacks/changepack_log_section_selection_guidance.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "changes": { - "crates/devup-mcp-figma/Cargo.toml": "Patch", - "crates/devup-mcp/Cargo.toml": "Patch" - }, - "note": "Make a Section selection list something a caller can choose from. A Section link answers with candidates rather than screens, and the list gave a name, a type and a URL - which is not enough to tell two frames apart when a designer named them alike, so the choice was a guess and the wrong guess costs a full export. Each candidate now carries a preview of the visible text under it, bounded to 120 characters per candidate, 64 nodes walked and 2 KiB across the whole list, so the index stays compact; an empty or short preview means the walk found little text, not that the screen is empty. The list also says how complete it is: selection.status and selection.count, with truncated read from the index itself rather than inferred from a round count of 100, which called a Section holding exactly that many partial. And nextAction carries an example built from this call own artifactId and a candidate actually in the list, so the next step is a call to run rather than a shape to assemble.", - "date": "2026-09-08T16:00:00+09:00" -} diff --git a/Cargo.toml b/Cargo.toml index 0834c1e..9e48f67 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ members = [ resolver = "3" [workspace.package] -version = "0.2.1" +version = "0.3.0" edition = "2024" rust-version = "1.98" license = "MIT"