本文へ移動
cccskills
無料GitHub で公開

rust-embed-rebuild-invalidation

Force `rust-embed` to re-embed assets from `$GRAFEMA_UI_DIST` (or any env-driven path) when cargo's incremental compilation skips the macro re-expansion. Use when: (1) you rebuilt the GUI bundle but the rust-server binary still serves the OLD bundle, (2) `cargo build --release` finishes in seconds (incremental hit) and `strings target/release/binary | grep <new-hash>` finds nothing, (3) any rust-embed pipeline where assets live outside the cargo source tree and are picked up via env var or symlink. Cargo only re-runs the proc macro when the rust file declaring `#[derive(RustEmbed)]` changes — env var changes alone don't trigger it.

インストール方法を見る

含まれるファイル(1)

  • SKILL.md3.9 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Rust-Embed Rebuild Invalidation

Problem

rfdb-server embeds the GUI bundle via rust-embed:

#[derive(RustEmbed)]
#[folder = "$GRAFEMA_UI_DIST"]
pub struct UiAssets;

You rebuild the GUI:

pnpm --filter @grafema/gui build       # produces dist/assets/HexAtlas-NEW.js
GRAFEMA_UI_DIST=$(pwd)/packages/gui/dist cargo build --release -p rfdb

Cargo says "Finished in 6 seconds" — way too fast for a full re-embed. You start the server, hit the URL, and curl http://localhost:51833/ui/default | grep HexAtlas returns the OLD hash. Re-running the build doesn't help.

Why this happens

rust-embed is a proc_macro evaluated at compile time. Cargo decides whether to re-run a proc-macro by hashing the source file that contains the #[derive(RustEmbed)]. Changes to environment variables (like GRAFEMA_UI_DIST) or to the contents of the asset folder do not invalidate the proc-macro. Cargo treats it as cache-hit, the previously expanded include-bytes! tree stays embedded, and your new asset never makes it into the binary.

Fix — touch the host file

touch packages/rfdb-server/src/static_ui.rs
GRAFEMA_UI_DIST=$(pwd)/packages/gui/dist cargo build --release -p rfdb

touch updates the file's mtime, which forces cargo to re-run the proc-macro, which re-reads the env var, which re-embeds the new assets. Build will take longer (full rust-embed re-expansion).

Verify:

strings target/release/rfdb-server | grep -E "HexAtlas-[A-Za-z0-9]+\.js" | head -3
# Should print the NEW hash (matches dist/assets/HexAtlas-NEW.js)

Why not cargo clean?

Works, but overkill — clears the entire target/, ~5 minute full rebuild. Touching one file is ~30 seconds and surgical.

Detection — how to know you've been bitten

If after cargo build --release:

  1. ls -la target/release/<binary> — is the mtime older than your last pnpm build?
  2. strings target/release/<binary> | grep <known-new-hash> — empty? You hit this bug.

Always verify embed freshness before debugging "the server returns old data". It's the second-most-common false-trail (after stale process on the port — see zombie-process-port-hunt).

Project script

For the Grafema build pipeline, the canonical recipe (from scripts/build-gui-for-rfdb.sh) should be:

pnpm --filter @grafema/gui build
touch packages/rfdb-server/src/static_ui.rs    # ← invalidate macro
GRAFEMA_UI_DIST=$(pwd)/packages/gui/dist \
  cargo build --release -p rfdb

Without the touch, the script's "rebuild rfdb-server with new bundle baked in" promise is silently broken on incremental builds.

Generalization

This pattern applies to any cargo proc-macro that reads files or env vars at expansion time:

  • include_bytes! / include_str! — same problem if the included path is outside cargo's tracked tree
  • serde_json::from_str(include_str!(...)) — same
  • Custom build.rs that reads from $ENV and writes a generated source — usually OK if cargo:rerun-if-env-changed=ENV is declared, but easy to forget

If you see "fast cargo rebuild + stale embedded data" for any of these — the workaround (touch the host file) generalizes.

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Fix Elixir/Erlang AST processing bugs in Grafema beam-analyzer. Use when: (1) Elixir parser returns MODULE node but 0 functions/calls — body nesting issue, (2) Erlang parser crashes with "cannot convert list to string" on OTP 26+ — location format changed from integer to keyword list, (3) pipe operator |> creates spurious CALL nodes instead of desugared function calls — clause ordering bug, (4) multi-module .ex files return only the first module — missing __block__ handler, (5) installing Erlang/Elixir on macOS with outdated Xcode/Clang.

日本語の概要は準備中です。原文の説明を表示しています。

Disentinel/grafema362026年8月24日 更新

Fires after fixing any non-trivial bug or regression. Asks: could the graph have caught this as a guarantee? Pairs with reflection-in-and-on-action — picks up after "earliest catchable signal" and asks the next question: was that signal expressible in graph? Triggers: (1) after any non-trivial bug fix is verified working, (2) after a regression report (something used to work, broke), (3) during step 6 (knowledge extraction) of the workflow, (4) when reflection-on-action surfaces a "would have been catchable" signal. Outcome is a triage decision (graph-reachable? rule expressible? rule sound?) and either a draft Linear issue + guarantee proposal, or a recorded "graph capability gap" note. Never auto-creates guarantees.

日本語の概要は準備中です。原文の説明を表示しています。

Disentinel/grafema362026年8月24日 更新

Fix Playwright automation failures against code-server (VS Code in browser). Use when: (1) trust dialog blocks all clicks — "monaco-dialog-modal-block intercepts pointer events", (2) button:has-text() finds wrong buttons behind modal dialog, (3) keyboard shortcuts don't work — Meta vs Control inconsistency, (4) VS Code extension activity bar icon not found by aria-label, (5) panels show placeholder text despite extension being "Connected". Covers trust dialog dismissal, keyboard shortcut hybrid mode, extension panel selectors, and database connection verification for Grafema extension.

日本語の概要は準備中です。原文の説明を表示しています。

Disentinel/grafema362026年8月24日 更新

Systematic methodology for achieving 100% backward dataflow reachability in a new language. Create gauntlet fixture, write trace, diagnose gaps, fix analyzer/algorithm, iterate to 100%. Language-agnostic process. Use when: (1) adding a new language to Grafema, (2) auditing dataflow coverage for existing language, (3) user says "/dataflow-gauntlet".

日本語の概要は準備中です。原文の説明を表示しています。

Disentinel/grafema362026年8月24日 更新

Fix docker exec hanging when starting background processes (servers, daemons) inside containers. Use when: (1) docker exec never returns despite using & or nohup, (2) background server started in container causes docker exec to hang indefinitely, (3) env_startup_command in SWE-bench or similar frameworks times out, (4) setsid/disown needed for proper process detachment in Docker. Root cause: docker exec tracks ALL processes in the exec session, not just the top-level PID.

日本語の概要は準備中です。原文の説明を表示しています。

Disentinel/grafema362026年8月24日 更新

Fix Node.js CLI tools crashing inside Docker containers when host-installed node_modules require a newer Node version than the container provides. Use when: (1) "SyntaxError: Invalid regular expression flags" with /v flag in string-width or similar packages, (2) node_modules installed on host with Node 20+ but container has Node 18, (3) `npm install` with file: protocol creates symlinks that break inside Docker, (4) pnpm workspace packages become broken symlinks in containers. Covers version detection, Node binary mounting, and npm install strategies for cross-version compatibility.

日本語の概要は準備中です。原文の説明を表示しています。

Disentinel/grafema362026年8月24日 更新

Disentinel のスキルをすべて見る

このスキルの問題を報告する