Skip to content

feat(state): add scoped slice persistence#246

Merged
cooper (czxtm) merged 7 commits into
developfrom
05-29-feat_state_scoped_slice_persistence
Jun 2, 2026
Merged

feat(state): add scoped slice persistence#246
cooper (czxtm) merged 7 commits into
developfrom
05-29-feat_state_scoped_slice_persistence

Conversation

@czxtm
Copy link
Copy Markdown
Member

Summary

Test Plan

Docs

  • Docs updated (companion PR in darkmatter/nixmac-web: #___)
  • No docs update needed

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 29, 2026

Warnings
⚠️

Your ## Test Plan section is empty or only contains placeholder text. Describe the steps a reviewer should take to verify this change, or check No test plan needed.

⚠️ ❗ Big PR (4224 lines changed). Consider splitting it into smaller, focused changes.
⚠️

New Rust modules were added without tests. Consider adding a #[cfg(test)] mod tests { ... } block or a file under apps/native/src-tauri/tests/:

  • apps/native/src-tauri/src/db/pool.rs
  • apps/native/src-tauri/src/db/tables.rs
  • apps/native/src-tauri/src/state/slice/json_io.rs
  • apps/native/src-tauri/src/state/slice/registry.rs
⚠️

This PR touches behavior-sensitive code that is documented in darkmatter/nixmac-web. Please either:

  • Open a companion docs PR and check Docs updated in the PR description, or
  • Check No docs update needed if the change doesn't affect user-facing behavior.

📋 PR Overview

Lines changed 4224 (+3621 / -603)
Files 24 added, 21 modified, 0 deleted
Draft / WIP no
Has Test Plan no
No Test Plan Needed no
New UI components yes (2)
New Storybook stories yes (2)
New Rust modules yes (11)
New TS source files yes (2)
New tests no
package.json touched no
Cargo.toml touched yes
Infra / CI touched no

🔬 Coverage

Report Lines Statements Functions Branches
apps/native/coverage/coverage-summary.json 18.5% 18.5% 33.4% 54.4%

Generated by 🚫 dangerJS against 4c93f58

@czxtm cooper (czxtm) force-pushed the 05-29-refactor_configurable_derive_codegen_ui branch from adc1ab6 to 79e6688 Compare May 29, 2026 22:20
@czxtm cooper (czxtm) force-pushed the 05-29-feat_state_scoped_slice_persistence branch from b3d73e2 to 34dd607 Compare May 29, 2026 22:20
@czxtm cooper (czxtm) force-pushed the 05-29-refactor_configurable_derive_codegen_ui branch from 79e6688 to 300911a Compare June 2, 2026 10:19
@czxtm cooper (czxtm) force-pushed the 05-29-feat_state_scoped_slice_persistence branch from 34dd607 to 12769b3 Compare June 2, 2026 10:19
@czxtm cooper (czxtm) force-pushed the 05-29-refactor_configurable_derive_codegen_ui branch from 300911a to 3571eba Compare June 2, 2026 10:26
@czxtm cooper (czxtm) force-pushed the 05-29-feat_state_scoped_slice_persistence branch from 12769b3 to 6781e96 Compare June 2, 2026 10:26
@czxtm cooper (czxtm) force-pushed the 05-29-refactor_configurable_derive_codegen_ui branch from 3571eba to 97359cf Compare June 2, 2026 10:34
@czxtm cooper (czxtm) force-pushed the 05-29-feat_state_scoped_slice_persistence branch from 6781e96 to 064cee2 Compare June 2, 2026 10:34
Base automatically changed from 05-29-refactor_configurable_derive_codegen_ui to develop June 2, 2026 10:41
feat(db): add Diesel pool and table models
Copilot AI review requested due to automatic review settings June 2, 2026 10:41
Comment thread dangerfile.ts
Comment on lines +79 to +80
return section
.replace(/<!--[\s\S]*?-->/g, "")
@czxtm cooper (czxtm) merged commit 5805a7b into develop Jun 2, 2026
10 of 12 checks passed
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR advances the state-management migration by introducing a generic, typed Slice<T> backend primitive with pluggable JSON persistence (app-data vs repo-scoped), plus a slice registry that enables an auto-generated “tuning” UI driven by #[derive(Configurable)]. In parallel, it begins Phase 2 groundwork by adding a Diesel SQLite r2d2 pool and pool-backed helpers, and it updates PR hygiene checks (Danger + template) and planning docs.

Changes:

  • Add state::slice infrastructure (Slice<T>, persistence backends, registry) and initial slice-backed state (GlobalPreferences, EvolveState, repo-scoped EvolutionLimits).
  • Add developer settings auto-UI plumbing: configurable schema types, derive macro expansion, registry commands, and new React settings components + stories.
  • Introduce Diesel pool scaffolding and pool-backed DB helpers (starting with commits), and adjust schema initialization strategy.

Reviewed changes

Copilot reviewed 44 out of 45 changed files in this pull request and generated 14 comments.

Show a summary per file
File Description
docs/2026-05-29-state-management-migration-plan.md New migration plan doc describing phased rollout of slices, scoped prefs, Diesel, and frontend split.
dangerfile.ts Makes several Danger checks advisory; adds smarter Test Plan section parsing and reporting.
Cargo.lock Updates Rust dependency graph (Diesel/r2d2 additions; lockfile churn).
apps/native/src/components/widget/settings/auto-tuning-section.tsx New settings section that renders all backend-registered Configurable schemas.
apps/native/src/components/widget/settings/auto-tuning-section.stories.tsx Storybook coverage for AutoTuningSection (happy path + error state).
apps/native/src/components/widget/settings/auto-config-field.tsx New field renderer that maps ConfigField.ty.kind → UI controls and writes via devConfigs.set.
apps/native/src/components/widget/settings/auto-config-field.stories.tsx Storybook coverage for AutoConfigField control variants.
apps/native/src/components/widget/settings/snapshots/auto-tuning-section.stories.tsx.snap Snapshot baselines for new AutoTuningSection stories.
apps/native/src/components/widget/settings/snapshots/auto-config-field.stories.tsx.snap Snapshot baseline for AutoConfigField story.
apps/native/src-tauri/src/storage/store.rs Moves EvolutionLimits to repo-scoped store path and prefers managed slices when present; simplifies credential store usage.
apps/native/src-tauri/src/storage/mod.rs Exposes configurable_scope module.
apps/native/src-tauri/src/storage/configurable_scope.rs Adds .nixmac/settings.json repo-scoped path resolver + README bootstrap.
apps/native/src-tauri/src/state/watcher.rs Changes watcher event model to slice-scoped events (and currently drops legacy git:status-changed).
apps/native/src-tauri/src/state/slice/registry.rs New runtime registry of slice-backed configurable shims (schema + set_field).
apps/native/src-tauri/src/state/slice/persistence.rs New persistence backends (AppDataJson, RepoScopedJson) behind a Persistence trait.
apps/native/src-tauri/src/state/slice/mod.rs New Slice<T> + write-guard that emits events and flushes JSON on drop.
apps/native/src-tauri/src/state/slice/json_io.rs Shared JSON read/write helpers used by persistence backends.
apps/native/src-tauri/src/state/preferences.rs Introduces GlobalPreferences slice + VolatileJson fallback persistence.
apps/native/src-tauri/src/state/mod.rs Documents new state module responsibilities; adds preferences + slice modules.
apps/native/src-tauri/src/state/evolve_state.rs Migrates evolve routing state to slice-backed persistence + event emission.
apps/native/src-tauri/src/shared_types/settings_io.rs Adds shared types for settings export/import result payloads.
apps/native/src-tauri/src/shared_types.rs Re-exports new shared settings IO types.
apps/native/src-tauri/src/main.rs Wires up managed slices/registry and new commands in GUI; adds slice setup in CLI path.
apps/native/src-tauri/src/evolve/config.rs Converts EvolutionLimits into a repo-scoped, slice-backed configurable with registry registration.
apps/native/src-tauri/src/db/tables.rs Adds Diesel table! definitions (starting with commits).
apps/native/src-tauri/src/db/schema.rs Reworks schema init to recreate DB on version mismatch (no rusqlite_migration).
apps/native/src-tauri/src/db/pool.rs Adds Diesel SQLite pool builder (DbPool).
apps/native/src-tauri/src/db/mod.rs Initializes and manages the Diesel pool in Tauri state; adds pool init helper + test.
apps/native/src-tauri/src/db/commits.rs Adds Diesel pool-backed commit upsert/query helpers alongside rusqlite path.
apps/native/src-tauri/src/commands/settings_io.rs Adds export/import commands for slice-backed settings with secret filtering.
apps/native/src-tauri/src/commands/mod.rs Registers new command modules (dev_configs, settings_io).
apps/native/src-tauri/src/commands/dev_configs.rs Adds commands to enumerate schemas + set fields via slice registry.
apps/native/src-tauri/src/commands/config.rs Removes legacy host-attr fallback read from ~/.config/darwin/host.
apps/native/src-tauri/examples/specta_gen_ts.rs Updates specta registrations (GitState, settings IO, configurable schema types).
apps/native/src-tauri/configurable/src/lib.rs Expands runtime crate to include configurable schema types (specta-exportable).
apps/native/src-tauri/configurable/Cargo.toml Adds specta derive; still includes now-unused tauri/store deps (see comments).
apps/native/src-tauri/configurable-derive/src/types.rs New derive helper mapping Rust types/attrs to UI schema field types.
apps/native/src-tauri/configurable-derive/src/strings.rs New string helpers (snake→camel + humanize).
apps/native/src-tauri/configurable-derive/src/lib.rs Refactors derive entrypoint to delegate to new codegen pipeline.
apps/native/src-tauri/configurable-derive/src/fields.rs New per-field codegen/validation building blocks.
apps/native/src-tauri/configurable-derive/src/codegen.rs New derive codegen pipeline generating load/schema/setters + Wry shims.
apps/native/src-tauri/configurable-derive/src/attrs.rs New struct/field attribute parsing with scope + UI metadata.
apps/native/src-tauri/Cargo.toml Adds Diesel/r2d2 deps; removes git2 (currently breaks compilation—see comments).
.github/PULL_REQUEST_TEMPLATE.md Adds “No test plan needed” checkbox.
.beads/issues.json Adds/updates Beads issue tracking entries for migration phases.

Comment on lines 325 to +336
let app = match tauri::Builder::default()
// Ensure store plugin (and its managed state) is initialized so we can load settings
.plugin(tauri_plugin_store::Builder::default().build())
.plugin(tauri_plugin_keyring::init())
.invoke_handler(tauri::generate_handler![])
.setup(|_app| Ok(()))
.setup(|app| {
app.manage(state::preferences::load_global_slice(app.handle())?);
app.manage(evolve::config::load_slice(app.handle())?);
evolve::config::register_slice_config(
&app.state::<state::slice::SliceRegistry>(),
)?;
app.manage(state::evolve_state::load_slice(app.handle())?);
Comment on lines +114 to +126
if let Ok(es) = evolve_state::get(&app_handle) {
// fire-and-forget: cache update in polling loop.
let _ = evolve_state::set(&app_handle, es, &status.changes);
}
// fire-and-forget: frontend event delivery; window may not be connected.
let _ = app_handle.emit(
"git:status-changed",
WatcherEvent {
"git_state_changed",
GitState {
git_status: Some(status.clone()),
change_map: Some(change_map),
evolve_state: evolve_state_updated,
error: None,
external_build_detected,
},
);
let _ = app_handle.emit("change_map_changed", change_map);
Comment on lines 131 to 134
Err(e) => {
// fire-and-forget: error event delivery to frontend.
let _ = app_handle.emit(
"git:status-changed",
WatcherEvent {
git_status: None,
change_map: None,
evolve_state: None,
error: Some(e.to_string()),
external_build_detected: false,
},
);
let _ = app_handle.emit("git_state_error", e.to_string());
}
Comment on lines +7 to +13
const SCHEMA_VERSION: i32 = 1;
const CURRENT_SCHEMA_SQL: &str = concat!(
include_str!("../../migrations/01-initial/up.sql"),
"\n",
include_str!("../../migrations/02-restore-commits/up.sql"),
"\nPRAGMA user_version = 1;\n",
);
Comment on lines +58 to +68
conn.execute_batch(
r#"
CREATE TABLE evolutions (
id INTEGER PRIMARY KEY,
branch TEXT NOT NULL,
merged INTEGER NOT NULL DEFAULT 0,
builds INTEGER NOT NULL DEFAULT 0
);
INSERT INTO evolutions (id, branch, merged, builds) VALUES (1, 'main', 0, 0);
PRAGMA user_version = 3;
"#,
Comment on lines +70 to 77
rnix = "0.14.0"
serde_yaml = "0.9"
rowan = "0.16.1"
fuzzy-matcher = "0.3.7"
tauri-plugin-webdriver-automation = "0.1.3"
tiktoken-rs = "0.6"
configurable = { path = "configurable" }

Comment on lines +1 to +3
import { tauriAPI } from "@/ipc/api";
import type { ConfigurableSchema } from "@/ipc/types";
import { SlidersHorizontal } from "lucide-react";
Comment on lines +12 to +15
import { tauriAPI } from "@/ipc/api";
import type { ConfigField } from "@/ipc/types";
import { Info } from "lucide-react";
import { useState } from "react";
Comment on lines +4 to +7
import { AutoTuningSection } from "@/components/widget/settings/auto-tuning-section";
import { tauriAPI } from "@/ipc/api";
import type { ConfigurableSchema } from "@/ipc/types";
import { waitFor, within } from "storybook/test";
Comment on lines +4 to +7
import { AutoConfigField } from "@/components/widget/settings/auto-config-field";
import { tauriAPI } from "@/ipc/api";
import type { ConfigField } from "@/ipc/types";

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.

4 participants