Skip to content

Update Versions - #11

Merged
owjs3901 merged 1 commit into
mainfrom
changepacks/main
Sep 8, 2026
Merged

Update Versions#11
owjs3901 merged 1 commit into
mainfrom
changepacks/main

Conversation

@github-actions

@github-actions github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Changepacks

devup-mcp@0.2.1 → 0.3.0 - crates/devup-mcp/Cargo.toml

Minor

  • 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.

Patch

  • 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.
  • 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.

devup-mcp-devup-ui@0.2.1 → 0.3.0 - crates/devup-mcp-devup-ui/Cargo.toml

Minor

  • 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.
  • 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.

Patch

  • 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.

devup-mcp-figma@0.2.1 → 0.3.0 - crates/devup-mcp-figma/Cargo.toml

Minor

  • 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.

Patch

  • 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.

devup-mcp-visual@0.2.1 → 0.2.2 - crates/devup-mcp-visual/Cargo.toml

Patch

  • 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.

owjs3901 added a commit that referenced this pull request Sep 8, 2026
build.rs infers the build id from git HEAD plus 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 therefore reported \<sha>-dirty\ - precisely the
state \--version\ and \--self-check\ exist to tell apart from a
developer's working tree. Committing the lock fixed the instance; PR #11
bumps Cargo.toml to 0.3.0 without touching the lock, which brings it
straight back.

CI knows which commit it is building, so it says so. build.rs already
prefers DEVUP_MCP_BUILD_ID over its own inference. A local build still
infers, so a dirty working tree still reports itself as one.
owjs3901 added a commit that referenced this pull request Sep 8, 2026
…it (#12)

* fix: send the fidelity report when it disagrees with the grade above it

Keying it on quality.projection 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 the condition then took
the report away with it.

Measured on a real 50-node screen (3997:47884): fidelity.variables was
19 of 20 while quality.projection read exact. The missing one is a
\\\ binding on an ellipse whose parent is exported as an SVG, so
the theme colour is baked into the file and can never follow the theme.
Three play buttons on that screen are affected. Before this change the
response showed the shortfall; after the first attempt it hid it.

The condition is now strict_compatible, 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 with
neither a shortfall nor an approximation, which is what this is for.

* fix(devup-ui): stop expecting a token binding baked into a multi-colour asset

An asset drawn in one colour becomes a Box masked to its shape with \�g\
set from that colour, so a token binding inside it survives as a token.
An asset drawn in more than one has no such form: 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 asks the generator for
something no correct implementation could produce. On frame 3997:47884
two play buttons each hide a bound circle behind a white glyph, and that
alone put the whole fidelity report on the response with nothing in it
anyone could act on: variables read 19 of 20 and the report was sent.

Bindings inside a non-mask asset are now left out of the expectation.
That screen moves to 17 of 17 and the report is not sent. 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 this narrows what is expected rather
than silencing what was found.

* fix(ci): name the commit when building a release instead of inferring it

build.rs infers the build id from git HEAD plus 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 therefore reported \<sha>-dirty\ - precisely the
state \--version\ and \--self-check\ exist to tell apart from a
developer's working tree. Committing the lock fixed the instance; PR #11
bumps Cargo.toml to 0.3.0 without touching the lock, which brings it
straight back.

CI knows which commit it is building, so it says so. build.rs already
prefers DEVUP_MCP_BUILD_ID over its own inference. A local build still
infers, so a dirty working tree still reports itself as one.
@owjs3901
owjs3901 merged commit bb2f3c5 into main Sep 8, 2026
@owjs3901
owjs3901 deleted the changepacks/main branch September 8, 2026 10:19
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.

1 participant