diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..f1c41f2c --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,120 @@ +# PROJECT KNOWLEDGE BASE + +**Generated:** 2026-02-17 +**Commit:** 475c468 +**Branch:** master + +## OVERVIEW + +MakerPnP — cross-platform Pick-and-Place machine software for Makers. Pure Rust Cargo workspace (31 crates), using Crux core/shell architecture with egui GUI and CLI frontends. + +## STRUCTURE + +``` +makerpnp/ +├── common/ # 6 shared utility crates (see common/AGENTS.md) +├── eda/ # EDA tool integration (eda, eda_units) — DipTrace, KiCad, EasyEDAPro +├── gerber/ # Gerber file handling (gerber, gerber_viewer_egui) +├── pnp/ # Core PnP types (Part, Placement, Package, ObjectPath, LoadOut) +├── planning/ # Assembly planning — 10 crates, largest module (see planning/AGENTS.md) +├── assets/ # Logos, screenshots +├── .github/ # CI workflow (rust.yml) +├── Hacks.md # Documented hack patterns with identifiers +└── KnownIssues.md # Known limitations and workarounds +``` + +## WHERE TO LOOK + +| Task | Location | Notes | +|------|----------|-------| +| Add CLI subcommand | `planning/planner_cli/src/opts.rs` | Uses clap 4.5, add ValueEnum adapters in `common/cli/src/args.rs` | +| Add GUI tab/dialog | `planning/planner_gui_egui/src/` | See `planning/planner_gui_egui/AGENTS.md` | +| Add Crux Event | `planning/planner_app/src/lib.rs` | 70+ events in `Event` enum, handle in `update()` | +| Add EDA tool support | `eda/eda/src/` | Implement parser, add variant to `variantbuilder_cli` | +| Part/Placement types | `pnp/pnp/src/` | Core domain types shared across all crates | +| Planning domain logic | `planning/planning/src/` | Pure domain — no Crux, no I/O | +| Data loading (CSV/file) | `planning/stores/src/` | Aggregates assembly, part_mapper, package_mapper | +| Rule matching | `common/criteria/src/lib.rs` | `FieldCriterion` trait — exact/regex strategies | +| i18n translations | `common/i18n/` + GUI `.ftl` files | Based on egui-i18n + Fluent | +| Gerber rendering | `gerber/` | Uses forked gerber_viewer library | + +## ARCHITECTURE + +### Crux Core/Shell Pattern + +``` +User Input → Event → Core.update() → Effect → Shell → Render + ↑ ↓ + └──────── New Event ───────────────┘ +``` + +- **Core** (`planner_app`, `variantbuilder_app`): Implements `crux_core::App`. Pure functions, no I/O. +- **Shell CLI** (`planner_cli`, `variantbuilder_cli`): `crossbeam-channel` effect loop. Auto-saves on modify. +- **Shell GUI** (`planner_gui_egui`): `PlannerCoreService` wraps Core, converts Effect → PlannerAction for egui. + +### Dependency Flow (top → bottom, no cycles) + +``` +Shells (cli, gui) + → Crux Cores (planner_app, variantbuilder_app) + → Domain Support (stores, assembly, part_mapper, package_mapper) + → Domain Core (planning — pure logic, no I/O) + → Shared Types (pnp, eda, gerber, common/*) +``` + +### 4 Executables + +| Binary | Crate | Purpose | +|--------|-------|---------| +| `planner_gui_egui` | `planning/planner_gui_egui` | GUI planner (egui + eframe) | +| `planner_cli` | `planning/planner_cli` | CLI planner (same Crux core) | +| `variantbuilder_cli` | `planning/variantbuilder_cli` | EDA → normalized placements | +| `gerber_viewer_egui` | `gerber/gerber_viewer_egui` | Standalone Gerber viewer | + +## CONVENTIONS + +- **Formatting**: `cargo +nightly fmt` — max_width=120, chain_width=40, struct_lit_single_line=false, group_imports=StdExternalCrate +- **Workspace deps**: ALL versions centralized in root `Cargo.toml` `[workspace.dependencies]`. Crates reference via `{ workspace = true }`. +- **Fork deps**: egui, egui_taffy, egui_ltreeview, egui_deferred_table, gerber_viewer — all forked under MakerPnP GitHub org with specific revs. +- **Resolver v2**: Required due to `testing` feature flag on dev-dependencies. +- **CLI adapters**: Internal types → `*Arg` enums in `common/cli/src/args.rs` via `From/Into`. +- **Test frameworks**: `rstest` (parameterized), `assert_cmd` + `assert_fs` (CLI integration). +- **Test data builders**: Builder pattern in `tests/common/` — `TestProject`, CSV builders. +- **Hack documentation**: Document hacks in `Hacks.md` with identifier comment (e.g. `HACK: table-resize-hack`), not scattered TODOs. + +## ANTI-PATTERNS (THIS PROJECT) + +- **No `as any` / `@ts-ignore` equivalent**: Do not suppress type errors. +- **No scattered TODO/FIXME**: Use `Hacks.md` and `KnownIssues.md` for tracking. +- **GUI must run from source dir**: GUI executables require relative asset paths — run from crate directory. +- **Don't float data-table tabs in debug mode**: Causes panic (egui_dock bug #278). +- **Single task active**: Only one phase task should be started/incomplete at a time. +- **PCB changes require project reload**: Save project → close → edit PCB → reopen. + +## COMMANDS + +```bash +# Build +cargo build --release + +# Test +cargo test --verbose + +# Format (requires nightly) +cargo +nightly fmt + +# Run GUI (from crate dir) +cd planning/planner_gui_egui && ../../target/release/planner_gui_egui + +# Run CLI +./target/release/planner_cli --help +./target/release/variantbuilder_cli --help +``` + +## NOTES + +- **CI**: GitHub Actions on push/PR to master. Ubuntu. Needs `libdbus-1-dev`. +- **Edition mix**: Most crates use 2021, newer GUI crates use 2024. +- **Gerber crates tightly coupled**: gerber_viewer, gerber-types, gerber_parser — ensure only one of each in dependency tree. +- **chrono over time**: Project chose chrono (13k dependents) over time crate (3k dependents). +- **License**: TBD (likely GPL3, Apache, or MIT). diff --git a/common/AGENTS.md b/common/AGENTS.md new file mode 100644 index 00000000..f131695f --- /dev/null +++ b/common/AGENTS.md @@ -0,0 +1,47 @@ +# COMMON UTILITIES + +**Parent:** [Root AGENTS.md](../AGENTS.md) + +## OVERVIEW + +6 shared utility crates — foundational types and helpers used across all domain crates. + +## STRUCTURE + +``` +common/ +├── args/ # Primitive argument type (`Arg` enum: Boolean, String, Integer) for i18n +├── cli/ # CLI utilities: clap parsers, tracing setup, internal→CLI type adapters +├── criteria/ # Rule matching engine: `FieldCriterion` trait, ExactMatch + RegexMatch strategies +├── i18n/ # Fluent-based i18n: loads .ftl translations, wraps egui_i18n +├── math/ # Numeric utilities: angle, decimal, ratio, math operations +└── util/ # Core utilities: Source enum, sorting, path helpers, dynamic typing, assertions +``` + +## WHERE TO LOOK + +| Task | Crate | Key File | Notes | +|------|-------|----------|-------| +| Add rule matching strategy | `criteria` | `src/lib.rs` | Implement `FieldCriterion` trait — used by `part_mapper` & `package_mapper` | +| Add CLI arg type adapter | `cli` | `src/args.rs` | Internal domain types → `*Arg` enums (clap ValueEnum) | +| Add CLI parser | `cli` | `src/parsers.rs` | Clap argument parsers | +| Configure tracing | `cli` | `src/tracing.rs` | Behind `tracing` feature flag | +| Add math operation | `math` | `src/ops.rs`, `src/angle.rs` | Angle/decimal/ratio math | +| Add file source type | `util` | `src/source.rs` | `Source` enum — file/URL abstraction | +| Add sorting helper | `util` | `src/sorting.rs` | `SortOrder` enum | +| Add dynamic typing | `util` | `src/dynamic/` | `AsAny` + `DynamicEq` traits — enables trait object equality | +| Add test utility | `util` | `src/test/` | Behind `testing` feature flag | +| Add i18n translation | `i18n` | `src/lib.rs` | Loads Fluent `.ftl` files, wraps `egui_i18n` | +| Add i18n argument type | `args` | `src/lib.rs` | `Arg` enum for Fluent argument conversion | + +## CONVENTIONS + +- **`testing` feature**: `util/src/test/` gated behind `#[cfg(any(test, feature = "testing"))]` — prevents test utilities from polluting release builds. +- **Dynamic equality**: `criteria` uses `AsAny` + `DynamicEq` from `util/dynamic/` for trait object equality (`dyn FieldCriterion`). +- **i18n feature flags**: `i18n` has `json` and `args` features for different Fluent argument conversion strategies. +- **Edition mix**: `i18n`, `math`, `args` use Rust edition 2024; `cli`, `criteria`, `util` use 2021. + +## ANTI-PATTERNS + +- Do NOT add domain-specific logic here — these crates are cross-cutting utilities only. +- Do NOT bypass `FieldCriterion` trait for rule matching — always implement the trait interface. diff --git a/planning/AGENTS.md b/planning/AGENTS.md new file mode 100644 index 00000000..73caa467 --- /dev/null +++ b/planning/AGENTS.md @@ -0,0 +1,65 @@ +# PLANNING MODULE + +**Parent:** [Root AGENTS.md](../AGENTS.md) + +## OVERVIEW + +Assembly planning — 10 crates implementing the Crux core/shell architecture for PCB assembly job management. + +## STRUCTURE + +``` +planning/ +├── planning/ # Pure domain logic (Project, Phase, Process, Placement) — NO Crux, NO I/O +├── planner_app/ # Crux Core — implements crux_core::App, 70+ Events, Model, Effects +├── planner_cli/ # Crux Shell (CLI) — crossbeam-channel effect loop, auto-save +├── planner_gui_egui/ # Crux Shell (GUI) — egui frontend (see planner_gui_egui/AGENTS.md) +├── variantbuilder_app/ # Crux Core — EDA file normalization (separate from planner) +├── variantbuilder_cli/ # Crux Shell (CLI) — DipTrace/KiCad/EasyEDAPro → normalized placements +├── stores/ # Data source abstraction — CSV/file loading, aggregates assembly+mappers +├── assembly/ # Assembly variant processing — filters placements by variant rules +├── part_mapper/ # Part mapping rules engine — matches parts via criteria +└── package_mapper/ # Package mapping rules engine — matches packages via criteria +``` + +## WHERE TO LOOK + +| Task | Location | Notes | +|------|----------|-------| +| Add new Event | `planner_app/src/lib.rs` | Add variant to `Event` enum + handle in `update()` | +| Add CLI subcommand | `planner_cli/src/opts.rs` (719 lines) | Clap derive, map to Event in `main.rs` | +| Add project domain logic | `planning/src/project.rs` (2722 lines) | Pure logic — `Project` struct methods | +| Add new Phase/Process behavior | `planning/src/phase.rs`, `planning/src/process.rs` | State machine transitions | +| Add data source | `stores/src/` | Implement loader, register in stores aggregator | +| Add part/package mapping rule | `part_mapper/src/`, `package_mapper/src/` | Uses `criteria` crate for matching | +| Add EDA tool support | `variantbuilder_app/src/lib.rs` + `variantbuilder_cli/` | Add parser in `eda/`, wire through app | +| Placement sorting | `planning/src/placement.rs` | `PlacementSortingItem`, `PlacementSortingMode` | + +## DEPENDENCY FLOW + +``` +Shells (planner_cli, planner_gui_egui, variantbuilder_cli) + → Cores (planner_app, variantbuilder_app) + → stores + → assembly, part_mapper, package_mapper + → planning (pure domain) + → pnp, eda, common/* +``` + +No cycles. All dependencies flow downward. + +## CONVENTIONS + +- **Crux pattern**: Core is pure — all side effects via `Effect` enum, handled by Shell. +- **CLI auto-save**: Shell checks `view.project_modified` / `view.pcbs_modified` after every Render effect. +- **Sequence tests**: `planner_cli/tests/planner.rs` (4324 lines) — uses static mutex + sequence numbering for ordered test execution. +- **Test builders**: `tests/common/` — `TestProject`, `LoadOutCSVBuilder`, `PhasePlacementsCSVBuilder` etc. +- **ObjectPath**: Unified locator format `/pcb_instance/pcb_unit/ref_des` (e.g. `/1/2/R1`). +- **Process state machine**: Process → Operations → Tasks, three-level status tracking. +- **`testing` feature flag**: Dev-dependencies use `features = ["testing"]` to avoid polluting release builds. + +## ANTI-PATTERNS + +- Do NOT add I/O to `planning/` crate — it must stay pure domain logic. +- Do NOT handle `Effect::ProjectView` / `Effect::PcbView` in CLI shell — only GUI uses those. +- Do NOT start multiple phase tasks simultaneously — only one should be active. diff --git a/planning/planner_gui_egui/AGENTS.md b/planning/planner_gui_egui/AGENTS.md new file mode 100644 index 00000000..e31b1a4f --- /dev/null +++ b/planning/planner_gui_egui/AGENTS.md @@ -0,0 +1,75 @@ +# PLANNER GUI (egui) + +**Parent:** [Planning AGENTS.md](../AGENTS.md) + +## OVERVIEW + +egui/eframe GUI shell for the Planner Crux core — 65 source files, largest frontend in the project. + +## STRUCTURE + +``` +planner_gui_egui/src/ +├── main.rs # Entry point — eframe::run_native, i18n init, profiling setup +├── lib.rs # Module declarations +├── ui_app.rs (940 lines) # Root app state — manages projects, pcbs, tabs, toolbar +├── planner_app_core.rs # PlannerCoreService — wraps Crux Core, Effect → PlannerAction +├── config.rs # Persistent app configuration (JSON) +├── command.rs # Command pattern for UI actions +├── ui_app/ +│ └── app_tabs/ # Top-level tab types (home, new_project, new_pcb, project, pcb) +├── project/ +│ ├── mod.rs (2995 lines)# Project view — largest file, orchestrates all project tabs +│ ├── toolbar.rs # Project-specific toolbar +│ ├── process.rs # Process management UI +│ ├── tabs/ # 9 tabs: overview, explorer, pcb, unit_assignments, parts, +│ │ # load_out, placements, phase, process, issues +│ ├── tables/ # Data tables: placements, parts, load_out +│ └── dialogs/ # Dialogs: add_phase, placement_orderings, package_sources, errors +├── pcb/ +│ ├── mod.rs (1190 lines)# PCB editor view +│ └── tabs/ # panel, configuration, gerber_viewer, explorer +├── ui_components/ # Reusable UI components (gerber_viewer_ui) +├── widgets/ # Custom widgets (list_box, augmented_list_selector) +├── dialogs/ # App-level dialogs (manage_gerbers) +├── forms/ # Form validation utilities +├── filter/ # Data filtering logic +├── i18n/ # GUI-specific i18n conversions +├── runtime/ # Async runtime (tokio_runtime, legacy_runtime) +├── task/ # Background task management +├── fonts.rs # Font configuration +├── profiling.rs # puffin profiling integration +├── tabs.rs # Tab trait and egui_dock integration +├── toolbar.rs # Shared toolbar components +├── file_picker.rs # File dialog integration (rfd) +└── ui_util.rs # UI helper functions +``` + +## WHERE TO LOOK + +| Task | Location | Notes | +|------|----------|-------| +| Add project tab | `project/tabs/` | Create `*_tab.rs`, register in `project/mod.rs` | +| Add PCB editor tab | `pcb/tabs/` | Create `*_tab.rs`, register in `pcb/mod.rs` | +| Add data table | `project/tables/` | Uses `egui_deferred_table` (forked) | +| Add dialog | `project/dialogs/` or `dialogs/` | Project-scoped vs app-scoped | +| Add toolbar button | `project/toolbar.rs` or `toolbar.rs` | Project vs app level | +| Modify Crux integration | `planner_app_core.rs` | Effect → PlannerAction mapping | +| Add widget | `widgets/` | Reusable across views | +| Change app layout | `ui_app.rs` | egui_dock tab management | +| Add i18n key | `i18n/conversions.rs` + `.ftl` files | Fluent format | +| Background async work | `runtime/`, `task/` | tokio-based | + +## CONVENTIONS + +- **Effect handling**: `PlannerCoreService.update(event)` returns `Vec` — caller processes actions sequentially. +- **Tab system**: Uses `egui_dock` for dockable/floatable tabs. Each tab implements a trait. +- **Large view files**: `project/mod.rs` (2995 lines) and `pcb/mod.rs` (1190 lines) orchestrate their respective views — read these first when understanding UI flow. +- **Edition 2024**: This crate uses Rust edition 2024 (newer than most crates in workspace). +- **Assets required**: Must run from crate directory — logos and i18n `.ftl` files loaded via relative paths. + +## ANTI-PATTERNS + +- Do NOT float tabs containing data tables in debug mode — causes panic (egui_dock #278). +- Do NOT add business logic here — belongs in `planner_app` (Crux Core) or `planning` (domain). +- Do NOT bypass `PlannerCoreService` — all state changes go through Crux Events.