fix(workspace): unblock CI — host visual_ref_enabled + radial-gradient clippy allow + fmt catch-up

Three independent CI-unblockers grouped to keep history clean:

1. op-host-desktop/chat_orchestrator.rs — add `visual_ref_enabled: false`
   to the DesignRequest literal so the workspace builds after S4 added
   the field. Same stub-plumbing pattern as the S3b-2 `concurrency`,
   S3b-4 `append_context`, S3c `validation_enabled` additions. Real
   intent-gate routing is task #27.

2. op-editor-core/render_backend.rs::fill_round_rect_radial_gradient —
   #[allow(clippy::too_many_arguments)] on the trait default. The
   radial-gradient hook carries (rect, radius, stops, cx_frac, cy_frac,
   radius_frac, opacity) per the TS pen-renderer contract; that's the
   data shape, not refactorable without splitting the trait.

3. cargo fmt --all catch-up on 6 other files (op-editor-core /
   op-editor-ui / op-host-native) that pre-dated this branch and were
   never run through rustfmt. Pure whitespace, no semantic change. Lets
   `cargo fmt --all -- --check` pass workspace-wide.

`cargo clippy --workspace --all-targets -- -D warnings` + `cargo build
--workspace` + `cargo fmt --all -- --check` all clean. Tests across
op-orchestrator (574+1) / op-design-lint (149) / op-mcp (144) /
op-editor-core (273) / op-host-desktop (96) all green.
This commit is contained in:
Fini 2026-05-23 20:43:39 +08:00
parent 84241b7ea2
commit 23c0f2e4d1
10 changed files with 21 additions and 28 deletions

View file

@ -294,10 +294,7 @@ fn scalar_as_hex(s: &jian_ops_schema::variable::VariableScalar) -> Option<String
/// `None` when the first fill isn't a gradient or `index` is out of
/// range — the same gating `set_primary_gradient_stop_hex` applies
/// on the write path.
fn gradient_stop_hex(
node: &jian_ops_schema::node::PenNode,
index: usize,
) -> Option<String> {
fn gradient_stop_hex(node: &jian_ops_schema::node::PenNode, index: usize) -> Option<String> {
use jian_ops_schema::style::PenFill;
let fills = crate::fills::node_fills(node)?;
let first = fills.first()?;

View file

@ -465,11 +465,7 @@ impl EditorState {
}
PropertyFocus::GradientStopOffset(index) => {
// Percent → fraction. Clamp happens inside the setter.
let _ = crate::fills::set_primary_gradient_stop_offset(
node,
index,
value / 100.0,
);
let _ = crate::fills::set_primary_gradient_stop_offset(node, index, value / 100.0);
}
// Hex focuses route through the dedicated colour setters
// (a typed-in hex is parsed by the host before commit), so

View file

@ -370,6 +370,7 @@ pub trait RenderBackend {
///
/// Default impl falls back to a solid first-stop fill, same as
/// the linear variant.
#[allow(clippy::too_many_arguments)]
fn fill_round_rect_radial_gradient(
&mut self,
rect: Rect,

View file

@ -60,9 +60,7 @@ impl PropertyFocus {
pub fn is_hex(self) -> bool {
matches!(
self,
PropertyFocus::FillHex
| PropertyFocus::StrokeHex
| PropertyFocus::GradientStopHex(_)
PropertyFocus::FillHex | PropertyFocus::StrokeHex | PropertyFocus::GradientStopHex(_)
)
}

View file

@ -307,9 +307,7 @@ impl NodeSnapshot {
/// fills — the Fill section uses that to hide the angle row.
fn gradient_angle_of(node: &PenNode) -> Option<f32> {
use jian_ops_schema::style::PenFill;
match op_editor_core::fills::node_fills(node)
.and_then(|f| f.first())?
{
match op_editor_core::fills::node_fills(node).and_then(|f| f.first())? {
PenFill::LinearGradient(body) => Some(body.angle.unwrap_or(0.0)),
_ => None,
}

View file

@ -523,8 +523,10 @@ fn paint_fill_gradient_body(
Point2D::new(0.0, 0.0),
);
let hex_text_x = hex_rect.origin.x + 30.0;
cx.backend
.draw_text(&hex_layout, Point2D::new(hex_text_x, hex_rect.origin.y + 19.0));
cx.backend.draw_text(
&hex_layout,
Point2D::new(hex_text_x, hex_rect.origin.y + 19.0),
);
if let Some(pos) = edit.caret_at(hex_focus) {
let w = cx
.backend

View file

@ -186,11 +186,12 @@ pub async fn run_design_request(
model,
provider: provider_id,
design_md: state.doc.design_md.clone(),
// S3b-2 / S3b-4 / S3c additions — host 暂无路由,统一保守值。
// S3b-2 / S3b-4 / S3c / S4 additions — host 暂无路由,统一保守值。
// 真实接线在 task #27 走 chat_runtime intent gate 时定。
append_context: None,
concurrency: 1,
validation_enabled: false,
visual_ref_enabled: false,
};
let mut sink = DesktopDocSink::new(state);
// Stub validation providers — production-visible, no-op. Host can

View file

@ -172,9 +172,7 @@ pub(in crate::widget_host) fn property_focus_initial(
.get(i)
// Strip alpha so the input pill matches what paint shows.
// Per-stop transparency rides through commit invisibly.
.map(|s| {
op_editor_ui::widgets::property_panel_fill::stop_hex_rgb_only(&s.hex)
})
.map(|s| op_editor_ui::widgets::property_panel_fill::stop_hex_rgb_only(&s.hex))
.unwrap_or_else(|| "#000000".to_string()),
F::GradientStopOffset(i) => panel
.snapshot

View file

@ -329,9 +329,7 @@ fn radial_gradient_payload_uses_authored_centre_and_radius() {
let n = &r.payload.pages[0].children[0];
let gradient = n.gradient.as_ref().expect("gradient must populate");
match gradient {
crate::payload::GradientPayload::Radial {
cx, cy, radius, ..
} => {
crate::payload::GradientPayload::Radial { cx, cy, radius, .. } => {
assert!((cx - 0.25).abs() < 0.01);
assert!((cy - 0.75).abs() < 0.01);
assert!((radius - 0.6).abs() < 0.01);
@ -350,7 +348,10 @@ fn solid_fill_leaves_gradient_payload_unset() {
}"##;
let r = load(src);
let n = &r.payload.pages[0].children[0];
assert!(n.gradient.is_none(), "solid fill must not populate gradient");
assert!(
n.gradient.is_none(),
"solid fill must not populate gradient"
);
}
#[test]

View file

@ -23,14 +23,15 @@
use op_editor_ui::layout_scene::NodeKind;
use op_editor_ui::layout_scene::{
LayoutScene, SceneFillType, SceneGradient, SceneGradientStop, SceneNode, ScenePage,
SceneStroke,
LayoutScene, SceneFillType, SceneGradient, SceneGradientStop, SceneNode, ScenePage, SceneStroke,
};
use op_editor_ui::scene_vars::VariableTable;
use op_editor_ui::Color;
use crate::editor_state_var_table;
use crate::payload::{DocPayload, GradientPayload, GradientStopPayload, NodePayload, StrokePayload};
use crate::payload::{
DocPayload, GradientPayload, GradientStopPayload, NodePayload, StrokePayload,
};
/// Build a paint-only [`LayoutScene`] from an editor state.
///