implement derive(Configurable) macro#228
Open
cooper (czxtm) wants to merge 3 commits into
Open
Conversation
… (PoC)
Introduces a proc-macro that eliminates the 6-file boilerplate currently
required for every store-backed setting. A new knob today touches:
storage/store.rs (getter+setter), shared_types/prefs.rs (UiPrefs +
UiPrefsUpdate fields), commands/ui_prefs.rs (read+write branches), TS
bindings, and UI forms — ~25 LOC across 6 files. With this derive, a new
knob is one struct field.
PoC scope — EvolutionLimits only:
#[derive(Configurable)]
#[config(store_path = "settings.json")]
pub struct EvolutionLimits {
#[config(default = 25, key = "maxIterations")]
pub max_iterations: usize,
#[config(default = 5, key = "maxBuildAttempts")]
pub max_build_attempts: usize,
}
The derive generates `EvolutionLimits::load(app) -> Result<Self>` that
reads each field from tauri-plugin-store with the per-field default
fallback. Reads happen on every call, so edits via dev settings take
effect on next agent run (hot-reload).
Two new workspace crates:
- configurable/ — runtime trait + read_field() helper
- configurable-derive/ — proc-macro
Bug fix included: evolve/mod.rs:1467 was logging
DEFAULT_MAX_BUILD_ATTEMPTS (the const) instead of the configured value
— exactly the drift this derive is designed to prevent. Threaded
max_build_attempts into process_tool_result().
UiPrefs / UiPrefsUpdate / ui_set_prefs left untouched on purpose — full
migration is tracked under nixmac-e53 with one sub-issue per category.
Closes: nixmac-8ka
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Member
Author
This stack of pull requests is managed by Graphite. Learn more about stacking. |
This was referenced May 28, 2026
Closed
Closed
Contributor
📋 PR Overview
🔬 Coverage
|
Contributor
There was a problem hiding this comment.
Pull request overview
Introduces a configurable proc-macro crate (PoC for issue nixmac-8ka) that derives a load(app) method reading typed fields from tauri-plugin-store, and migrates the evolution loop's max_iterations / max_build_attempts knobs to use it. This is the first step toward dissolving the centralized UiPrefs god-struct into co-located, per-module config structs.
Changes:
- New workspace crates
configurable(runtime helperread_field) andconfigurable-derive(proc-macro emittingload). - New
evolve/config.rsdefiningEvolutionLimitsvia#[derive(Configurable)], replacing the localDEFAULT_MAX_BUILD_ATTEMPTSconstant andstore::get_max_iterations/store::get_max_build_attemptscalls ingenerate_evolution. - Wired
max_build_attemptsthrough toprocess_tool_resultso the build-attempt log message uses the configured limit instead of a constant.
Reviewed changes
Copilot reviewed 9 out of 10 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| Cargo.toml | Adds the two new crates to the workspace. |
| Cargo.lock | Lock entries for configurable and configurable-derive. |
| apps/native/src-tauri/Cargo.toml | Depends on the new configurable crate. |
| apps/native/src-tauri/configurable/Cargo.toml | Manifest for the runtime crate. |
| apps/native/src-tauri/configurable/src/lib.rs | Re-exports the derive and defines read_field. |
| apps/native/src-tauri/configurable-derive/Cargo.toml | Proc-macro crate manifest. |
| apps/native/src-tauri/configurable-derive/src/lib.rs | Implements #[derive(Configurable)] parsing store_path, per-field default / key. |
| apps/native/src-tauri/src/evolve/config.rs | Declares EvolutionLimits using the new derive. |
| apps/native/src-tauri/src/evolve/mod.rs | Replaces store getter + constant with EvolutionLimits::load; threads max_build_attempts into process_tool_result. |
| .beads/issues.jsonl | Adds the PoC bead and follow-up migration beads. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+654
to
+660
| } = config::EvolutionLimits::load(app).unwrap_or_else(|e| { | ||
| warn!("EvolutionLimits::load failed ({e}); using defaults"); | ||
| config::EvolutionLimits { | ||
| max_iterations: 25, | ||
| max_build_attempts: 5, | ||
| } | ||
| }); |
Comment on lines
+39
to
+42
| let store = app.store(store_path)?; | ||
| Ok(store | ||
| .get(key) | ||
| .and_then(|value| serde_json::from_value(value.clone()).ok())) |
Comment on lines
+53
to
+58
| Ok(quote! { | ||
| #ident: ::configurable::read_field::<R, #ty>(app, #store_path, #key)? | ||
| .unwrap_or_else(|| #default), | ||
| }) | ||
| }) | ||
| .collect::<syn::Result<Vec<_>>>()?; |
This was referenced May 29, 2026
Adds a #[cfg(test)] module exercising the Configurable-derived load(): defaults on empty store, stored-value override, and graceful fallback on schema drift. Enables the tauri 'test' feature in dev-dependencies for mock_builder. Satisfies the danger 'new Rust module without tests' gate.
…rive # Conflicts: # apps/native/src-tauri/Cargo.toml
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.

Summary
Introduces a
#[derive(Configurable)]macro (configurable+configurable-derivecrates) that generates a store-backedload(app)for dev settings, and applies it to a newEvolutionLimitsstruct (maxIterations,maxBuildAttempts) read fresh on every evolution run so edits in the dev-settings UI hot-reload. Defaults are unchanged (25 iterations / 5 build attempts).Test Plan
cargo test --manifest-path apps/native/src-tauri/Cargo.toml evolve::config— runs the newEvolutionLimits::loadunit tests against a Tauri mock app:maxIterations/maxBuildAttemptsoverride the defaultsbun -F native desktop:test(runscargo test+ TS unit) passes.Docs