app

Local-first trade for farms and co-ops
git clone https://radroots.dev/git/app.git
Log | Files | Refs | README | LICENSE

commit 41786d95eb66d4a283fe57fcf4c77233e0170f02
parent cec59ee494dabaa51e489d213bc30fd3a1790e4b
Author: triesap <tyson@radroots.org>
Date:   Thu, 13 Aug 2026 17:35:36 +0000

policy: adopt the complete Studio visual baseline

- bind provenance to the verified 102-file source snapshot
- classify the complete dashboard as a visual reference
- expose corrective golden evidence as explicitly pending
- admit only the exact owned shell color and text adapters

Diffstat:
Mapp/design_system/src/commonMain/kotlin/org/harvestcircle/designsystem/shell/HarvestCircleShellControls.kt | 8++++----
Mapp/design_system/src/commonMain/kotlin/org/harvestcircle/designsystem/shell/HarvestCircleShellVisuals.kt | 12++++++++++++
Mconfig/design/source_baseline_v1.toml | 12++++++------
Mtools/xtask/src/lib.rs | 43++++++++++++++++++++++++++++---------------
4 files changed, 50 insertions(+), 25 deletions(-)

diff --git a/app/design_system/src/commonMain/kotlin/org/harvestcircle/designsystem/shell/HarvestCircleShellControls.kt b/app/design_system/src/commonMain/kotlin/org/harvestcircle/designsystem/shell/HarvestCircleShellControls.kt @@ -112,9 +112,9 @@ public fun HarvestCircleShellButton( val sources = rememberHarvestCircleShellInteractionSources(text) val interaction = sources.collectHarvestCircleShellInteractions(enabled) val filled = primary || destructive - val active = if (destructive) Color(0xFF982018) else colors.accent - val activeHover = if (destructive) Color(0xFFB42318) else colors.accentHover - val activePressed = if (destructive) Color(0xFF7A1A14) else colors.accentPressed + val active = if (destructive) colors.destructive else colors.accent + val activeHover = if (destructive) colors.destructiveHover else colors.accentHover + val activePressed = if (destructive) colors.destructivePressed else colors.accentPressed val background = when { !enabled -> colors.input @@ -129,7 +129,7 @@ public fun HarvestCircleShellButton( if (!enabled) { colors.contentDisabled } else if (filled) { - colors.onAccent + if (destructive) colors.onDestructive else colors.onAccent } else { colors.contentPrimary } diff --git a/app/design_system/src/commonMain/kotlin/org/harvestcircle/designsystem/shell/HarvestCircleShellVisuals.kt b/app/design_system/src/commonMain/kotlin/org/harvestcircle/designsystem/shell/HarvestCircleShellVisuals.kt @@ -32,6 +32,10 @@ public data class HarvestCircleShellColors( public val accentPressed: Color, public val accentSubtle: Color, public val onAccent: Color, + public val destructive: Color, + public val destructiveHover: Color, + public val destructivePressed: Color, + public val onDestructive: Color, public val shadow: Color, ) @@ -58,6 +62,10 @@ private val HarvestCircleShellLightColors = accentPressed = Color(0xFF10432F), accentSubtle = Color(0xFFE6EFEA), onAccent = Color.White, + destructive = Color(0xFF982018), + destructiveHover = Color(0xFFB42318), + destructivePressed = Color(0xFF7A1A14), + onDestructive = Color.White, shadow = Color(0x2E000000), ) @@ -84,6 +92,10 @@ private val HarvestCircleShellDarkColors = accentPressed = Color(0xFF10432F), accentSubtle = Color(0xFF173126), onAccent = Color.White, + destructive = Color(0xFFB42318), + destructiveHover = Color(0xFFD92D20), + destructivePressed = Color(0xFF982018), + onDestructive = Color.White, shadow = Color(0x66000000), ) diff --git a/config/design/source_baseline_v1.toml b/config/design/source_baseline_v1.toml @@ -1,13 +1,13 @@ schema = "harvestcircle.design_source_baseline.v1" source_product = "Studio" source_repository = "https://github.com/radrootslabs/studio_app" -source_head = "768279b16a1256a4432a692b4f74582ab22eb2f4" +source_head = "8ae5d8a0377c5673038a20b82b87c314370f0395" source_state = "clean" -snapshot_sha256 = "914c5d3b81c95bded19e36044cece8cff93e74cce0d4089324bb2effa4eebb93" -snapshot_file_count = 91 +snapshot_sha256 = "c2fe49f3c3ea43105cb2fff4a67c7cd9c21561c71825440a91654a0c1b12e3b8" +snapshot_file_count = 102 source_license = "GPL-3.0-only" golden_host = "macos-aarch64" -golden_status = "verified" +golden_status = "corrective-pending" golden_source_snapshot_sha256 = "914c5d3b81c95bded19e36044cece8cff93e74cce0d4089324bb2effa4eebb93" golden_light_sha256 = "844a42a37d05671a9665a75214ee40f9c23dafd90c8a5e199d831daede3faf20" golden_dark_sha256 = "ce06a1ae820005adddebd8f627b5402279d3365762305f8dd64004612322eae7" @@ -54,8 +54,8 @@ disposition = "visual-reference" [[mapping]] source = "shared/src/commonMain/kotlin/com/radroots/studio/ui/dashboard" -destination = "audit-only/dashboard-visual-inputs" -disposition = "audit-only" +destination = "app/shared/src/commonMain/kotlin/org/harvestcircle/ui/shell" +disposition = "visual-reference" [[mapping]] source = "shared/src/commonMain/composeResources/values/strings.xml" diff --git a/tools/xtask/src/lib.rs b/tools/xtask/src/lib.rs @@ -733,20 +733,28 @@ fn product_shell_audit(root: &Path, inventory: &Inventory, findings: &mut Vec<St "{path}: interactive control defaults to a hidden keyboard focus ring" )); } + let approved_color_adapter = path.starts_with( + "app/design_system/src/commonMain/kotlin/org/harvestcircle/designsystem/theme/color/", + ) || path + == "app/design_system/src/commonMain/kotlin/org/harvestcircle/designsystem/shell/HarvestCircleShellVisuals.kt"; if is_production_compose(path, &source) - && !path.starts_with( - "app/design_system/src/commonMain/kotlin/org/harvestcircle/designsystem/theme/color/", - ) + && !approved_color_adapter && contains_direct_call(&compact, "Color(") { findings.push(format!( "{path}: hard-coded Compose color outside the theme adapter" )); } - let approved_text_primitive = path - == "app/design_system/src/commonMain/kotlin/org/harvestcircle/designsystem/primitive/HarvestCircleText.kt"; - let approved_input_primitive = path - == "app/design_system/src/commonMain/kotlin/org/harvestcircle/designsystem/component/input/HarvestCircleTextField.kt"; + let approved_text_primitive = matches!( + path.as_str(), + "app/design_system/src/commonMain/kotlin/org/harvestcircle/designsystem/primitive/HarvestCircleText.kt" + | "app/design_system/src/commonMain/kotlin/org/harvestcircle/designsystem/shell/HarvestCircleShellText.kt" + ); + let approved_input_primitive = matches!( + path.as_str(), + "app/design_system/src/commonMain/kotlin/org/harvestcircle/designsystem/component/input/HarvestCircleTextField.kt" + | "app/design_system/src/commonMain/kotlin/org/harvestcircle/designsystem/shell/HarvestCircleShellControls.kt" + ); if is_production_compose(path, &source) { if !approved_text_primitive && contains_direct_call(&compact, "BasicText(") { findings.push(format!( @@ -899,25 +907,30 @@ fn design_source_audit(root: &Path, inventory: &Inventory, findings: &mut Vec<St return; } let source = read_text(root, PATH); - let expected_snapshot = "914c5d3b81c95bded19e36044cece8cff93e74cce0d4089324bb2effa4eebb93"; + let expected_snapshot = "c2fe49f3c3ea43105cb2fff4a67c7cd9c21561c71825440a91654a0c1b12e3b8"; + let pending_golden_snapshot = + "914c5d3b81c95bded19e36044cece8cff93e74cce0d4089324bb2effa4eebb93"; let required_scalars = [ "schema = \"harvestcircle.design_source_baseline.v1\"", "source_product = \"Studio\"", "source_repository = \"https://github.com/radrootslabs/studio_app\"", - "source_head = \"768279b16a1256a4432a692b4f74582ab22eb2f4\"", + "source_head = \"8ae5d8a0377c5673038a20b82b87c314370f0395\"", "source_state = \"clean\"", - "snapshot_file_count = 91", + "snapshot_file_count = 102", "source_license = \"GPL-3.0-only\"", "golden_host = \"macos-aarch64\"", - "golden_status = \"verified\"", + "golden_status = \"corrective-pending\"", ]; for scalar in required_scalars { if source.lines().filter(|line| line.trim() == scalar).count() != 1 { findings.push(format!("{PATH}: missing or duplicate authority: {scalar}")); } } - for key in ["snapshot_sha256", "golden_source_snapshot_sha256"] { - let expected = format!("{key} = \"{expected_snapshot}\""); + for (key, digest) in [ + ("snapshot_sha256", expected_snapshot), + ("golden_source_snapshot_sha256", pending_golden_snapshot), + ] { + let expected = format!("{key} = \"{digest}\""); if source .lines() .filter(|line| line.trim() == expected) @@ -998,8 +1011,8 @@ fn design_source_audit(root: &Path, inventory: &Inventory, findings: &mut Vec<St ), ( "shared/src/commonMain/kotlin/com/radroots/studio/ui/dashboard", - "audit-only/dashboard-visual-inputs", - "audit-only", + "app/shared/src/commonMain/kotlin/org/harvestcircle/ui/shell", + "visual-reference", ), ( "shared/src/commonMain/composeResources/values/strings.xml",