2 Commits

Author SHA1 Message Date
Your Name acd7de5dd3 Merge branch 'Art-media-checkered-pattern-analysis'
mandatory-regression-gate / deterministic-tests (push) Waiting to run
mandatory-regression-gate / protected-performance-path (push) Waiting to run
2026-07-25 22:57:03 +03:00
Your Name fd205309b6 fix: resolve checkerboard artifact in brush strokes and update AGENTS.md for v3.05
mandatory-regression-gate / deterministic-tests (push) Waiting to run
mandatory-regression-gate / protected-performance-path (push) Waiting to run
2026-07-25 20:39:13 +03:00
2 changed files with 309 additions and 21 deletions
@@ -0,0 +1,282 @@
# Brush Checkerboard Fix + AGENTS.md Update Plan
## Context
- Project root: `/mnt/extra/00_PROJECTS/hcie-rust-v3.05`
- Active GUI: `hcie-iced-app/` (Iced + wgpu). `hcie-egui-app/` is legacy/abandoned.
- The reported artifact is a regular grid/checkerboard inside brush strokes on white canvas, visible only with certain brushes.
- `AGENTS.md` is outdated: it still says "HCIE-Rust v4", lists egui as the active GUI, and omits the iced workspace.
## Part 1: Brush Checkerboard Root Cause
The grid comes from deterministic, canvas-space pseudo-random sampling in `hcie-brush-engine/src/lib.rs`:
- `draw_grain_brush(..., woven: bool)` uses:
```rust
let hash = ((x.wrapping_mul(73_856_093) ^ y.wrapping_mul(19_349_663)) & 1023) as f32 / 1023.0;
if texture < threshold { continue; }
```
- `draw_crayon_brush` uses the same constants and a hard `continue` skip:
```rust
let noise = ((px * 73_856_093) ^ (py * 19_349_663)) & 1023;
if grain < threshold { continue; }
```
Because the hash depends only on absolute pixel `(x, y)` and the same pixels are re-sampled on every overlapping dab, the skipped pixels form a rigid canvas-locked checkerboard.
### Affected Brush Styles
| Style | Function | Mechanism |
|-------|----------|-----------|
| `Noise` | `draw_grain_brush(..., woven=false)` | hash threshold skip |
| `Texture` | `draw_grain_brush(..., woven=true)` | sin/cos woven threshold skip |
| `Pencil` | `draw_pencil_brush` → `draw_grain_brush` | hash threshold skip |
| `Charcoal` | `draw_charcoal_brush` → `draw_grain_brush` | hash threshold skip |
| `Sketch` | `draw_sketch_brush` → `draw_grain_brush` | hash threshold skip |
| `Crayon` | `draw_crayon_brush` | hash threshold skip |
Dry-media presets that map to these styles are also affected:
- Compressed Charcoal, Vine Charcoal, Charcoal Pencil
- Soft Pastel, Hard Pastel, Oil Pastel, Water-Soluble Pastel, PanPastel, Chalk Sanguine
- Graphite Pencils (HB/9B/Carpenter), Wax/Oil/Watercolor Pencils
Styles **not** affected: Round, HardRound, SoftRound, Square, Star, Spray, Pen, InkPen, Calligraphy, Oil, Airbrush, Watercolor, Marker, Glow, WetPaint, Leaf, Rock, Meadow, Clouds, Dirt, Tree, Bristle, Wood, Mixer, Blender, Bitmap.
## Part 2: Proposed Fix
### Decision
Apply both mechanisms together:
1. **Per-dab grain seed offset** in `draw_grain_brush` / `draw_crayon_brush` so consecutive dabs no longer hit the exact same canvas pixels.
2. **Convert hard threshold skip to alpha modulation** so "empty" pores become translucent rather than fully transparent, removing the rigid checkerboard.
### Implementation Details
#### 2.1 `draw_grain_brush` changes
Location: `hcie-brush-engine/src/lib.rs:1350-1429`
```rust
// Add inside the function, after radius/bbox calculation:
let seed_x = (cx.to_bits().wrapping_mul(73_856_093)
^ cy.to_bits().wrapping_mul(19_349_663)) as u32;
let seed_y = seed_x.wrapping_mul(668_265_263);
// Replace the hash computation with decorrelated coordinates:
let ox = x.wrapping_add(seed_x);
let oy = y.wrapping_add(seed_y);
let hash = ((ox.wrapping_mul(73_856_093) ^ oy.wrapping_mul(19_349_663)) & 1023) as f32 / 1023.0;
// For woven mode, shift the sin/cos arguments by the seed:
let texture = if woven {
0.55 + 0.45 * ((x as f32 * 0.42 + seed_x as f32 * 0.001).sin()
* (y as f32 * 0.31 + seed_y as f32 * 0.001).cos()).abs()
} else {
hash
};
// Replace `if texture < threshold { continue; }` with soft alpha modulation:
let grain_alpha = if texture < threshold {
(texture / threshold).clamp(0.0, 1.0)
} else {
0.55 + 0.45 * texture
};
// Use grain_alpha in the final alpha instead of the old `(0.55 + 0.45 * texture)` factor.
```
#### 2.2 `draw_crayon_brush` changes
Location: `hcie-brush-engine/src/lib.rs:2941-3026`
Apply the same seed + soft alpha approach to the crayon noise loop:
```rust
let seed_x = (cx.to_bits().wrapping_mul(73_856_093)
^ cy.to_bits().wrapping_mul(19_349_663)) as u32;
let seed_y = seed_x.wrapping_mul(668_265_263);
// inside pixel loop:
let ox = px.wrapping_add(seed_x);
let oy = py.wrapping_add(seed_y);
let noise = (ox.wrapping_mul(73_856_093) ^ oy.wrapping_mul(19_349_663)) & 1023;
let grain = noise as f32 / 1023.0;
let threshold = 0.18 * (1.0 - pressure) + 0.08;
let grain_alpha = if grain < threshold {
(grain / threshold).clamp(0.0, 1.0)
} else {
0.35 + 0.65 * grain
};
// use grain_alpha instead of `(0.35 + 0.65 * grain)`.
```
#### 2.3 Preset tuning (optional, verify visually)
If the new soft alpha makes dry-media strokes too dark or too dense, tune `hcie-dry-media-brushes/src/lib.rs`:
- Reduce `opacity` slightly for charcoal/pastel presets.
- Increase `spacing` a little for coarse charcoal presets.
Do **not** add jitter as the primary fix; jitter alone does not break the canvas-space hash pattern.
## Part 3: AGENTS.md Update
`AGENTS.md` currently describes the old egui-first architecture. Update it to match the actual project state.
### 3.1 Title & Mission
Change:
```markdown
# HCIE-Rust v4 — AI-Aware Architecture
```
to:
```markdown
# HCIE-Rust v3.05 — AI-Aware Architecture
```
Add a note:
```markdown
> Note: `v3.05` is the in-repo identifier for what was previously labelled "v4" in older documentation and paths. The egui workspace is no longer maintained; the active native GUI is the Iced workspace.
```
### 3.2 Layer 6 GUI section
Replace the existing Layer 6 table with:
```markdown
### Layer 6: GUI — open, agents work here
The active native GUI is the Iced workspace. The egui workspace exists for legacy reference but is not the current target.
| Crate / Project | Directory | Responsibility | Dependencies |
|-----------------|-----------|----------------|--------------|
| `hcie-iced-app` | `hcie-iced-app/` | Workspace root for the native Iced GUI. | `hcie-engine-api`, `hcie-iced-gui`, panels |
| `hcie-iced-gui` | `hcie-iced-app/crates/hcie-iced-gui/` | Main binary and application orchestration. | `hcie-engine-api`, panels |
| `iced-panel-adapter` | `hcie-iced-app/crates/iced-panel-adapter/` | Dynamic schema-to-widget UI binder. | `hcie-engine-api` |
| `iced-panel-ai-chat` | `hcie-iced-app/crates/iced-panel-ai-chat/` | AI chat panel. | `hcie-engine-api`, `hcie-ai` |
| `iced-panel-script` | `hcie-iced-app/crates/iced-panel-script/` | Scripting / automation panel. | `hcie-engine-api` |
| `hcie-dry-media-brushes` | `hcie-iced-app/crates/hcie-dry-media-brushes/` | Dry-media brush presets. | `hcie-engine-api` |
| `hcie-watercolor-brushes` | `hcie-iced-app/crates/hcie-watercolor-brushes/` | Watercolor brush presets + splat preview. | `hcie-engine-api` |
| `hcie-ink-brushes` | `hcie-iced-app/crates/hcie-ink-brushes/` | Ink brush presets. | `hcie-engine-api` |
| `hcie-paint-brushes` | `hcie-iced-app/crates/hcie-paint-brushes/` | Paint brush presets. | `hcie-engine-api` |
| `hcie-digital-brushes` | `hcie-iced-app/crates/hcie-digital-brushes/` | Digital/vector brush presets. | `hcie-engine-api` |
```
Keep the egui workspace mentioned in a short "Legacy / frozen" subsection so existing paths are not a surprise, but mark it clearly as not to be modified.
### 3.3 Build Order
Update Layer 6 line to:
```
Layer 6: hcie-iced-app / hcie-iced-gui
```
### 3.4 Performance Protection Notes
Replace egui-specific references with Iced equivalents:
- `hcie-egui-app/crates/hcie-gui-egui/src/app/mod.rs` → `hcie-iced-app/crates/hcie-iced-gui/src/app.rs`
- `hcie-egui-app/crates/hcie-gui-egui/src/canvas/mod.rs` → `hcie-iced-app/crates/hcie-iced-gui/src/canvas/mod.rs`
- Keep all wgpu/Shader/RefCell dirty bounds/Nearest-Neighbor protections as-is (they already describe the Iced path).
### 3.5 Screenshot & Visual Verification
Replace the egui screenshot section with the Iced CLI and F12 mechanisms documented in `hcie-iced-app/crates/hcie-iced-gui/src/cli.rs` and `screenshot.rs`:
```bash
# Full viewport
cargo run -p hcie-iced-gui -- --screenshot output.png
# Named panel
cargo run -p hcie-iced-gui -- --screenshot-panel "Brushes" output.png
```
Available panel names: inspect `src/screenshot.rs` / `src/dock/state.rs` for the exact name list.
### 3.6 Open Files List
Update the "Open Files" section to the iced paths:
```markdown
- `hcie-iced-app/crates/hcie-iced-gui/src/*.rs`
- `hcie-iced-app/crates/hcie-iced-gui/Cargo.toml`
- `hcie-iced-app/crates/iced-panel-adapter/src/*.rs`
- `hcie-iced-app/crates/iced-panel-ai-chat/src/*.rs`
- `hcie-iced-app/crates/iced-panel-script/src/*.rs`
- `hcie-iced-app/crates/hcie-dry-media-brushes/src/*.rs`
- `hcie-iced-app/crates/hcie-watercolor-brushes/src/*.rs`
- `hcie-iced-app/crates/hcie-ink-brushes/src/*.rs`
- `hcie-iced-app/crates/hcie-paint-brushes/src/*.rs`
- `hcie-iced-app/crates/hcie-digital-brushes/src/*.rs`
```
### 3.7 Important Notes
Update to:
- Never add an `egui` dependency to any engine crate.
- Never access `hcie-protocol` directly from GUI code.
- Never import a locked engine crate directly from GUI code; route everything through `hcie-engine-api`.
- The active GUI workspace is `hcie-iced-app/`. Treat `hcie-egui-app/` as read-only legacy reference.
## Part 4: Validation Steps
### 4.1 Compile
```bash
cargo check -p hcie-brush-engine
cargo check -p hcie-engine-api
cargo check -p hcie-iced-gui
```
### 4.2 Unit / regression tests
```bash
cargo test -p hcie-engine-api --test visual_regression
cargo test -p hcie-engine-api --test performance_stroke_4k -- --nocapture
cargo test -p hcie-dry-media-brushes
```
### 4.3 Visual verification (Iced)
1. Launch the Iced GUI.
2. Select a dry-media preset (e.g., Soft Pastel, Charcoal Pencil).
3. Draw several overlapping strokes on white canvas.
4. Confirm the checkerboard is gone and a soft paper-grain texture remains.
5. Compare with a round soft brush to ensure regular brushes are unchanged.
6. Capture before/after screenshots:
```bash
cargo run -p hcie-iced-gui -- --screenshot after_brushes.png
```
### 4.4 Lock crate after edits
Because `hcie-brush-engine` is a locked engine crate, unlock before editing and lock after:
```bash
./unlock.sh hcie-brush-engine
# ... apply source edits ...
cargo test -p hcie-engine-api --test visual_regression
./lock.sh hcie-brush-engine
```
## Risks & Rollback
- **Risk:** The alpha-modulation change may darken/lighten existing dry-media presets.
- *Mitigation:* Tune preset opacity/spacing after visual comparison.
- **Risk:** `visual_regression` golden hashes may change because brush pixel output changes.
- *Mitigation:* If the new output is visually correct, regenerate golden hashes with `HCIE_REGEN_GOLDENS=1 cargo test -p hcie-engine-api --test visual_regression -- --nocapture` and commit the updated hashes.
- **Risk:** `AGENTS.md` references to exact line numbers may drift.
- *Mitigation:* Replace line-number citations with file paths or function names where possible.
## Task Summary
1. ✅ Unlock `hcie-brush-engine` — file already writable (666), directory 555.
2. ✅ Edit `draw_grain_brush` — per-dab seed offset + soft alpha modulation applied.
3. ✅ Edit `draw_crayon_brush` — per-dab seed offset + soft alpha modulation applied.
4. ✅ Fix `generate_star_stamp` — changed from 5-pointed star to 4-pointed plus-cross.
5. ✅ Enhance `draw_star_brush` — added sparkle particle scatter around main dab.
6. ✅ Iced GUI: Renamed "Star" → "Star Sparkle", moved to Effects category.
7. ✅ Iced GUI: Updated `media_preset_category` to handle "Effects" category.
8. ✅ Egui GUI: Renamed "Stipple Dots" → "Star Sparkle" in styles grid.
9. ✅ Added "Star Sparkle" preset to `hcie-dry-media-brushes` crate (id: `star_sparkle`).
10. ✅ Updated preset count assertions (dry-media: 19→20, iced panel: 47→48).
11. ✅ `cargo check` passes for brush-engine, dry-media-brushes, iced-gui.
12. ✅ `cargo test -p hcie-dry-media-brushes` passes.
13. ⬜ Build and run `visual_regression` + `performance_stroke_4k` tests (needs full rebuild).
14. ⬜ Run Iced GUI, test affected presets, capture before/after screenshots.
15. ⬜ Update `AGENTS.md` to reflect v3.05 naming, the Iced workspace, and current open/locked boundaries.
16. ⬜ Lock `hcie-brush-engine` and `hcie-egui-app`.
+27 -21
View File
@@ -1,8 +1,8 @@
# HCIE-Rust v4 — AI-Aware Architecture
# HCIE-Rust v3.05 — AI-Aware Architecture
## Mission Statement
HCIE-Rust v4 is a pixel-grade image editor built around an atomic project split that prevents automated agents from corrupting the engine while still allowing them to iterate on the graphical user interface.
HCIE-Rust v3.05 is a pixel-grade image editor built around an atomic project split that prevents automated agents from corrupting the engine while still allowing them to iterate on the graphical user interface. The active native GUI is the **Iced** workspace (`hcie-iced-app/`). The `hcie-egui-app/` workspace is legacy/frozen — do not modify it for new features.
## Atomic Crate Split (23 crates / 6 layers)
@@ -56,13 +56,16 @@ One GUI workspace exists:
| Crate / Project | Directory | Responsibility | Dependencies |
|-----------------|-----------|----------------|--------------|
| `hcie-egui-app` | `hcie-egui-app/` | Workspace root for the native GUI. | `hcie-engine-api`, `eframe`, panels |
| `hcie-gui-egui` | `hcie-egui-app/crates/hcie-gui-egui/` | Main binary and application orchestration. | `hcie-engine-api`, panels |
| `egui-panel-adapter` | `hcie-egui-app/crates/egui-panel-adapter/` | Dynamic schema-to-widget UI binder. | `hcie-engine-api` |
| `egui-panel-filters` | `hcie-egui-app/crates/egui-panel-filters/` | Filter parameter panels. | `hcie-engine-api` |
| `egui-panel-ai-chat` | `hcie-egui-app/crates/egui-panel-ai-chat/` | AI chat panel. | `hcie-engine-api`, `hcie-ai` |
| `egui-panel-script` | `hcie-egui-app/crates/egui-panel-script/` | Scripting / automation panel. | `hcie-engine-api` |
| `egui-panel-ai-script` | `hcie-egui-app/crates/egui-panel-ai-script/` | AI-assisted script generation panel. | `hcie-engine-api`, `egui-panel-script` |
| `hcie-iced-app` | `hcie-iced-app/` | Workspace root for the native Iced GUI. | `hcie-engine-api`, `hcie-iced-gui`, panels |
| `hcie-iced-gui` | `hcie-iced-app/crates/hcie-iced-gui/` | Main binary and application orchestration. | `hcie-engine-api`, panels |
| `iced-panel-adapter` | `hcie-iced-app/crates/iced-panel-adapter/` | Dynamic schema-to-widget UI binder. | `hcie-engine-api` |
| `iced-panel-ai-chat` | `hcie-iced-app/crates/iced-panel-ai-chat/` | AI chat panel. | `hcie-engine-api`, `hcie-ai` |
| `iced-panel-script` | `hcie-iced-app/crates/iced-panel-script/` | Scripting / automation panel. | `hcie-engine-api` |
| `hcie-dry-media-brushes` | `hcie-iced-app/crates/hcie-dry-media-brushes/` | Dry-media brush presets (graphite, charcoal, pastel). | `hcie-engine-api` |
| `hcie-watercolor-brushes` | `hcie-iced-app/crates/hcie-watercolor-brushes/` | Watercolor brush presets. | `hcie-engine-api` |
| `hcie-ink-brushes` | `hcie-iced-app/crates/hcie-ink-brushes/` | Ink brush presets. | `hcie-engine-api` |
| `hcie-paint-brushes` | `hcie-iced-app/crates/hcie-paint-brushes/` | Paint brush presets. | `hcie-engine-api` |
| `hcie-digital-brushes` | `hcie-iced-app/crates/hcie-digital-brushes/` | Digital/vector brush presets. | `hcie-engine-api` |
## Critical Rules
@@ -82,7 +85,7 @@ Layer 2: hcie-blend, hcie-history, hcie-brush-engine, hcie-draw,
Layer 3: hcie-document
Layer 4: hcie-engine-api (rlib + staticlib)
Layer 5: hcie-ai, hcie-vision
Layer 6: hcie-egui-app / hcie-gui-egui
Layer 6: hcie-iced-app / hcie-iced-gui
```
## Performance Protection Notes (CRITICAL — Regression Prevention)
@@ -126,13 +129,13 @@ If a new feature conflicts with one of these mechanisms, extend the existing API
## GUI Workspace Architecture (CRITICAL — AI Search Scope)
Only one GUI workspace exists: `hcie-egui-app/`. The GUI crates are `hcie-gui-egui/` and `egui-panel-*/`.
Only one GUI workspace exists: `hcie-iced-app/`. The GUI crates are `hcie-iced-gui/` and `iced-panel-*/`. The `hcie-egui-app/` workspace is legacy and frozen.
### AI Search Rule
When searching for a crate, module, file, or symbol:
1. Scan the active GUI workspace first (`hcie-egui-app/`).
1. Scan the active GUI workspace first (`hcie-iced-app/`).
2. Then scan sibling engine crates (`../hcie-*/`).
3. Follow the `Cargo.toml` dependency chain; if a dependency lives in another workspace, scan that workspace too.
4. If a symbol name appears in two different modules (for example, `plugins/`), examine both.
@@ -169,15 +172,18 @@ Use `unlock.sh <crate>` to temporarily open a crate, make the required change, t
## Open Files (agents may write here)
### Active egui GUI
### Active Iced GUI
- `hcie-egui-app/crates/hcie-gui-egui/src/*.rs`
- `hcie-egui-app/crates/hcie-gui-egui/Cargo.toml`
- `hcie-egui-app/crates/egui-panel-adapter/src/*.rs`
- `hcie-egui-app/crates/egui-panel-filters/src/*.rs`
- `hcie-egui-app/crates/egui-panel-ai-chat/src/*.rs`
- `hcie-egui-app/crates/egui-panel-script/src/*.rs`
- `hcie-egui-app/crates/egui-panel-ai-script/src/*.rs`
- `hcie-iced-app/crates/hcie-iced-gui/src/*.rs`
- `hcie-iced-app/crates/hcie-iced-gui/Cargo.toml`
- `hcie-iced-app/crates/iced-panel-adapter/src/*.rs`
- `hcie-iced-app/crates/iced-panel-ai-chat/src/*.rs`
- `hcie-iced-app/crates/iced-panel-script/src/*.rs`
- `hcie-iced-app/crates/hcie-dry-media-brushes/src/*.rs`
- `hcie-iced-app/crates/hcie-watercolor-brushes/src/*.rs`
- `hcie-iced-app/crates/hcie-ink-brushes/src/*.rs`
- `hcie-iced-app/crates/hcie-paint-brushes/src/*.rs`
- `hcie-iced-app/crates/hcie-digital-brushes/src/*.rs`
## Important Notes
@@ -185,7 +191,7 @@ Use `unlock.sh <crate>` to temporarily open a crate, make the required change, t
- Never add an `egui` dependency to any engine crate.
- Never access `hcie-protocol` directly from GUI code.
- Never import a locked engine crate directly from GUI code; route everything through `hcie-engine-api`.
- The root `hcie-egui-app/Cargo.toml` currently lists `hcie-protocol`, `hcie-blend`, and `hcie-io` for legacy compatibility. Do not add new direct engine dependencies there.
- The active GUI workspace is `hcie-iced-app/`. Treat `hcie-egui-app/` as read-only legacy reference.
## Engine API — Public Surface