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:
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",