feat(server): say what was actually checked, and keep the binary current - #70
Merged
Merged
Conversation
Four verdicts claimed work that had not been done, and one failure gave the caller nothing to do about it. `devup_ui_validate` reported `file-placement` against the Next.js files whose default export the framework requires. `app/layout.tsx` without one is a build error, so the advice could not be taken, and because the finding is a warning it failed `strict: true` on a correct application. The rule already knew `layout.tsx` was special one branch below; it now knows it in both, together with the rest of the segment and metadata conventions, and only inside the router directory that reserves those names. The page-name rule judged every component in a route file rather than the one the route renders, so a correct `export default function NoticePage` was reported for its own `PageContent` helper. `one-component-per-file` then asked for that helper to be moved somewhere the file-placement rule forbids, leaving `src/components/` as the only destination for a component used by one route. At a monorepo root the theme lookup took the first `devup.json` the sorted scan found. `apps/front` code was validated against `apps/admin`'s theme and its real tokens came back as `unknown-token` *errors*, suggesting the other package's token as the fix. It now refuses to choose and returns `candidateProjectRoots` naming the `projectRoot` that selects each - which is what `devup_project_context` already did for the same directory. A call with neither `tsx` nor `files` validated the empty string and answered `ok: true, okReason: "clean"` about code that was never sent. It is refused now, and `clean` is split so `clean-unverified-tokens` says a `$token` reference existed but no theme was resolved to check it against. Tokens inside `css()`/`globalCss()`/`keyframes()` were invisible to that check entirely, so an unknown one there passed in silence. A Section whose candidate menu exceeded the plugin transport was refused outright: nothing came back for a menu that was merely long, and retrying reproduced it because the ceiling follows the Section's size. It now surrenders text previews first, then shortens from the end under the same `projectionTruncated` the traversal and candidate caps already raise. `allScreens` still refuses a truncated index rather than pretending to be whole - silence was the thing forbidden, not truncation. Of the twenty-five codes the plugin scripts throw, two carry a JSON payload. The rest arrived as `pluginCode: null` with generic advice. The code is read from the message for all of them now, and the ones naming a caller-fixable condition are mapped: a missing node or page reached callers as `-32603 INTERNAL_ERROR`, while the README promises the JSON-RPC code alone separates "fix the arguments" from "stop and report". That promise failed on the most common mistake there is. The placement contract carries the collected parent's fill, because learning that the desktop frame behind an app screen was `#E6EDE6` otherwise took a second Figma acquisition for a colour the capture already held. Finally, `self_update` keeps the binary current with nobody tending it. The release check already reported a difference and deliberately never acted, for a reason about *this* process: a binary replaced under a running server cannot recover the stdio pipe the host already holds. That reason is untouched. Nothing here replaces the running image - the published asset is downloaded, proved by running `--self-check` on it, and renamed into place, which the running process cannot notice because its image was loaded at spawn. The next start is the one that differs. It stands down where it does not own its install (a package manager's directory, or one it cannot write), and `server.updateAvailable.autoUpdate` reports which mechanism is in force and which switch turned it off.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Four verdicts claimed work that had not been done, and one failure gave the caller nothing to do about it. Each section below is independent — say the word and I will split them.
devup_ui_validatereported violations a correct app cannot avoidapp/layout.tsxwithout a default export is a build error, sofile-placementagainst it was advice that could not be taken — and because the finding is a warning,strict: truefailed a correct Next.js application over it.not-found.tsxcollected two findings for the same reason. The rule already knewlayout.tsxwas special one branch below; it now knows it in both, along with the rest of the segment and metadata conventions, and only inside the router directory that reserves those names —src/components/error.tsxis still an ordinary module.The page-name rule judged every component in a route file rather than the one the route renders, so a correct
export default function NoticePagewas reported for its ownPageContenthelper.one-component-per-filethen asked for that helper to be moved somewhere the file-placement rule forbids, leavingsrc/components/as the only destination for a component used by exactly one route.The monorepo root validated one package against another's theme
theme_for_validationtook the firstdevup.jsonthe sorted scan found. Measured on a two-package fixture:$bgexists inapps/front. It now refuses to choose and returnscandidateProjectRootsnaming theprojectRoot,authorityandappliesToof each — which is whatdevup_project_contextalready did for the same directory.cleancovered things that were never checkedA call with neither
tsxnorfilesvalidated the empty string and answeredok: true, okReason: "clean"about code that was never sent; it is refused now.clean-unverified-tokensdistinguishes "no violation found" from "no violation found, and the$tokenreferences this code makes were never checked because no theme was resolved". Tokens insidecss()/globalCss()/keyframes()were invisible to the check entirely — only$-prefixed strings are inspected, so no call gains a new warning severity from this.A long Section menu returned nothing
Refused outright when it exceeded the plugin transport — for a menu that was merely long, and retrying reproduced it because the ceiling follows the Section's size. It now surrenders text previews first, then shortens from the end under the same
projectionTruncatedthe traversal and candidate caps already raise.allScreensstill refuses a truncated index rather than pretending to be whole; silence was the thing forbidden, not truncation.Of the twenty-five codes the plugin scripts throw, two carry a JSON payload — the rest arrived as
pluginCode: nullwith generic advice. The code is read from the message for all of them now, and the ones naming a caller-fixable condition are mapped:codeDEVUP_NODE_NOT_FOUND·DEVUP_PAGE_NOT_FOUNDDEVUP_FIGMA_NODE_NOT_FOUNDDEVUP_ENVELOPE_TOO_LARGE·DEVUP_EXPLORE_PROJECTION_TOO_LARGEDEVUP_FIGMA_RESPONSE_TOO_LARGEDEVUP_SNAPSHOT_UNSUPPORTEDA missing node is the most common mistake there is, and the README promises the JSON-RPC code alone separates "fix the arguments" from "stop and report".
The parent's background took a second acquisition
placementContractsnow carries the collected parent's fill, layout mode and name. Learning that the desktop frame behind an app screen was#E6EDE6otherwise meant exporting that parent separately — a second Figma call for a colour the capture already held. Reported, never emitted:parentIncludedInOutputstaysfalse.self_update— the binary follows the current releaserelease_checkreports a difference and deliberately never acts, for a reason about this process: a binary replaced under a running server cannot recover the stdio pipe the host already holds. That reason is untouched. Nothing here replaces the running image — the published asset is downloaded, proved by running--self-checkon it, and renamed into place, which the running process cannot notice because its image was loaded at spawn.Verified against the real 0.9.0 release with a binary built at 0.1.0:
It stands down where it does not own its install (a package manager's directory, or one it cannot write), so a launcher that resolves
@lateston every spawn is never fought.server.updateAvailable.autoUpdatereports which mechanism is in force, whether something is waiting for the next start, the asset for this platform, andinstalledPath— the file to replace when the automatic path is not available. Switching offDEVUP_MCP_NO_UPDATE_CHECKalso reportsdisabled, because with no check nothing is ever discovered to stage.Verification
cargo fmt --all -- --check,cargo clippy --workspace --all-targets --all-features -- -D warnings: cleancargo test --workspace --all-features: 116 suites, 0 failures (20 new tests)plugin/dist/code.jsregenerated withnpm run build; byte-stable on a second runsrc/components/Card.tsx,app/page.tsxnamedHome,src/components/error.tsx)One snapshot moved:
sourceParentBackground: nulladded besidesourceParentSize— purely additive.Not covered by these tests
The plugin error mapping is unit-tested against
upstream_error; the path from a real plugin throw is first exercised by the next release. Section truncation and the parent background are verified on synthetic scene graphs and fixtures, not against a live Figma file.self_update's download ran for real against the published 0.9.0 asset.