From eb2a5d27b99077e085bd597535884c78d84ad48b Mon Sep 17 00:00:00 2001 From: bherbruck Date: Wed, 7 Oct 2026 23:15:09 +0000 Subject: [PATCH] Scope decisions (in-scope parity headline, deferred tabs), STEP import and kernel notes in ROADMAP/plan Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL --- ROADMAP.md | 41 +++++++++++++----- docs/parity.md | 102 ++++++++++++++++++++++++-------------------- xtask/src/parity.rs | 32 +++++++++++--- 3 files changed, 112 insertions(+), 63 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index 549a21da..8713251a 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -8,13 +8,31 @@ features → parametric timeline) as an open, pure-Rust, agent-drivable applicat | Question | Answer | |---|---| | Where are we? | **M0 done; M1/M2 in progress.** Sketch with solver, extrude (taper, two-sided, through all), revolve, fillet/chamfer, holes, patterns, mirror, shell, draft, loft, sweep, split, construction planes, parameters that rebuild the timeline, STEP/STL export, desktop and browser (wasm) app with Fusion-style selection (hover/selected highlights, origin planes, click-to-pick sketch planes, multi-select, window/crossing box selection, animated view cube), CLI, MCP server, oracle harness. | -| Command parity (SOLID + SKETCH toolbar) | **57 / 291 (20%)** — [docs/parity.md](docs/parity.md) | -| Fusion oracle | **29 / 29 parts match** Fusion's measurements — [docs/oracle.md](docs/oracle.md) | +| Command parity (in scope) | **139 / 541 (26%)** in-scope commands; SOLID + SKETCH **102 / 291 (35%)** — [docs/parity.md](docs/parity.md) | +| Fusion oracle | **38 / 66 parts match** (batch 1: 29/29; batch 2 in progress) — [docs/oracle.md](docs/oracle.md) | | Tests | 85 (solver, profiles, kernel booleans/blends/measures, expressions, timeline, file formats, camera, engine end-to-end, hostile-input fuzz over every command) | | Gates | `cargo xtask ci`: fmt, clippy -D warnings, tests, asset attribution, layering, wasm32 build — green | | Weighted parity estimate | **≈ 5%** of Fusion's Design workspace by importance (sketch + basic solids are the core, but surfaces, assemblies, sheet metal, CAM, drawings are untouched) | | Time to a useful alpha (M0–M6) | ≈ **150 agent hours** remain | +## Scope (owner decision, 2026-10-07) + +In scope, in priority order: +1. SOLID and SKETCH (now). +2. Parameters / functional constraints: user parameters with units and expressions (+-*/, ^, + parentheses, sin/cos/sqrt/min/max/floor/ceil/round, unit conversion), model parameters + d1, d2… for every dimension and feature input, references between parameters with a + dependency graph and cycle detection, re-evaluation on change, comments, favourites, + CSV/JSON import and export. +3. Components and assemblies with joints (M9). +4. SHEET METAL: flange, contour flange, bend, unfold/refold, flat pattern with DXF export, sheet + metal rules (thickness, K-factor, bend radius) (M10). +5. A small PLASTIC subset for enclosures, after sheet metal: Boss, Rib, Web, Lip/Groove, Snap Fit. + +Deferred until further notice: MESH, FORM (T-splines), SURFACE beyond what solids need, PCB / 3D +PCB / Package, Render, Animation, Simulation, Manufacture/CAM, Drawings. The parity report's +headline counts in-scope tabs only and lists the deferred ones separately. + ## Milestones | # | Milestone | Status | Hours left | @@ -27,10 +45,10 @@ features → parametric timeline) as an open, pure-Rust, agent-drivable applicat | M5 | Persistent naming of faces and edges | planned | 20 | | M6 | UI depth: selection feedback and origin (done), timeline editing (done: edit feature, history marker drag, reorder with dependency checks, suppress, rename, delete with dependents, re-resolved references), live previews, measure tool, section view, drag-solve | in progress | 16 | | M7 | Sweep, loft, rib, web, emboss, thread, coil, pipe | planned | 24 | -| M8 | Surface workspace | planned | 30 | -| M9 | Components and assemblies (Fusion-style): New Component / Create Components from Bodies, active component, per-component origin/bodies/sketches/timeline entries, occurrences with transforms, Copy/Paste vs Paste New, nested Browser tree with visibility and isolate; Ground, Move/Copy of occurrences, joints (rigid, revolute, slider, cylindrical, pin-slot, planar, ball) by joint origins with limits and Drive Joints, As-built Joint, Rigid Group, contact sets later; interference, per-component physical properties; STEP with assembly structure. Groundwork done: the document is a component tree (features and bodies carry a component, active component, New Component, Create Components from Bodies) | planned | 40 | -| M10 | Sheet metal | planned | 30 | -| M11 | 2D drawings | planned | 30 | +| M8 | Surface workspace | deferred | — | +| M9 | Components and assemblies (Fusion-style): New Component / Create Components from Bodies, active component, per-component origin/bodies/sketches/timeline entries, occurrences with transforms, Copy/Paste vs Paste New, nested Browser tree with visibility and isolate; Ground, Move/Copy of occurrences, joints (rigid, revolute, slider, cylindrical, pin-slot, planar, ball) by joint origins with limits and Drive Joints, As-built Joint, Rigid Group, contact sets later; interference, per-component physical properties; STEP with assembly structure. Groundwork done: component tree, occurrences with transforms (instances, Paste New), world placement, active component as authoring frame, ground, Capture/Revert Position, moving bodies and sketches | in progress | 32 | +| M10 | Sheet metal: flange, contour flange, bend, unfold/refold, flat pattern + DXF, rules (thickness, K-factor, bend radius); then the PLASTIC enclosure subset (Boss, Rib, Web, Lip/Groove, Snap Fit) | planned | 36 | +| M11 | 2D drawings | deferred | — | | M12 | Release: installers, signing, docs, performance | planned | 16 | ## Known limitations @@ -43,12 +61,13 @@ features → parametric timeline) as an open, pure-Rust, agent-drivable applicat voids are not supported. Spheres are built from six pole-free patches so they combine reliably. - Mass properties come from fine tessellation (curved faces within ~1e-4 relative). -- STEP import reads solids (B-rep with analytic and B-spline geometry), units, product names, - colours and assemblies; offset surfaces and pcurve-only edges are not read yet, and assembly - components are flattened into bodies (the tree is kept for M9). +- STEP import (our own reader, crates/kernel/src/step_in; all 29 Fusion STEP files pass + `cargo xtask step-corpus`) reads solids (B-rep with analytic and B-spline geometry), units, + product names, colours and assemblies; offset surfaces and pcurve-only edges are not read yet, + and assembly components are flattened into bodies. Closed periodic faces (torus, B-spline + bands) are split in two for meshing; measure() uses a finer tolerance for small radii. - No persistent naming (fillet edges are re-found by position). -- Shell and draft work on convex bodies with planar faces; loft is ruled (no tangency end conditions). -- Dialogs have no live preview of the result yet. +- Shell works on planar bodies (convex or not), draft on convex planar bodies; loft is ruled. ## Kernel diff --git a/docs/parity.md b/docs/parity.md index d357b150..8e6b2a9d 100644 --- a/docs/parity.md +++ b/docs/parity.md @@ -2,19 +2,21 @@ Generated by `cargo xtask parity` from `xtask/data/fusion-catalog.tsv` (the toolbar commands of Fusion's Design workspace, ids and names only) and the live command registry (`solvecraft-cli commands`). A command counts as live when SolveCraft registers the same command id. This measures breadth, not depth; see ROADMAP.md and docs/oracle.md for depth. -**SOLID + SKETCH: 93 / 291 commands live (32%).** All Design tabs: 186 / 1175 (16%). Registered commands: 123. +**In scope (SOLID, SKETCH, ASSEMBLY, SHEET METAL, PLASTIC enclosure subset): 139 / 541 commands live (26%).** SOLID + SKETCH: 102 / 291 (35%). Registered commands: 145. + +Deferred until further notice (not in the in-scope figure): MESH, FORM, SURFACE beyond what solids need, PCB, render, animation, simulation, manufacture, drawings, MANAGE, UTILITIES and the rest of PLASTIC. All Design tabs together: 225 / 1175 (19%). | Tab | Panel | Live | Total | % | |---|---|---:|---:|---:| -| SOLID | CREATE | 13 | 35 | 37% | -| SOLID | MODIFY | 11 | 32 | 34% | -| SOLID | ASSEMBLE | 1 | 21 | 5% | +| SOLID | CREATE | 16 | 35 | 46% | +| SOLID | MODIFY | 14 | 32 | 44% | +| SOLID | ASSEMBLE | 2 | 21 | 10% | | SOLID | CONFIGURE | 0 | 3 | 0% | | SOLID | CONSTRUCT | 2 | 20 | 10% | | SOLID | INSPECT | 1 | 25 | 4% | | SOLID | INSERT | 1 | 11 | 9% | | SOLID | SELECT | 0 | 15 | 0% | -| SOLID | POSITION | 0 | 2 | 0% | +| SOLID | POSITION | 2 | 2 | 100% | | SKETCH | CREATE | 35 | 41 | 85% | | SKETCH | MODIFY | 12 | 12 | 100% | | SKETCH | CONSTRAINTS | 13 | 15 | 87% | @@ -24,18 +26,45 @@ Generated by `cargo xtask parity` from `xtask/data/fusion-catalog.tsv` (the tool | SKETCH | ASSEMBLE | 0 | 1 | 0% | | SKETCH | SELECT | 0 | 15 | 0% | | SKETCH | FINISH SKETCH | 1 | 2 | 50% | -| SURFACE | CREATE | 4 | 25 | 16% | -| SURFACE | MODIFY | 8 | 26 | 31% | +| SHEET METAL | CREATE | 8 | 19 | 42% | +| SHEET METAL | MODIFY | 7 | 21 | 33% | +| SHEET METAL | ASSEMBLE | 1 | 20 | 5% | +| SHEET METAL | CONFIGURE | 0 | 3 | 0% | +| SHEET METAL | CONSTRUCT | 2 | 20 | 10% | +| SHEET METAL | INSPECT | 1 | 25 | 4% | +| SHEET METAL | INSERT | 1 | 11 | 9% | +| SHEET METAL | SELECT | 0 | 15 | 0% | +| SHEET METAL | REFOLD | 0 | 1 | 0% | +| SHEET METAL | POSITION | 2 | 2 | 100% | +| ASSEMBLY | INSERT | 1 | 8 | 12% | +| ASSEMBLY | CREATE | 4 | 8 | 50% | +| ASSEMBLY | RELATIONSHIPS | 0 | 11 | 0% | +| ASSEMBLY | MOTION | 0 | 3 | 0% | +| ASSEMBLY | MODIFY | 5 | 11 | 45% | +| ASSEMBLY | CONTACT | 0 | 2 | 0% | +| ASSEMBLY | CONFIGURE | 0 | 3 | 0% | +| ASSEMBLY | CONSTRUCT | 2 | 20 | 10% | +| ASSEMBLY | INSPECT | 1 | 25 | 4% | +| ASSEMBLY | SELECT | 0 | 15 | 0% | +| ASSEMBLY | POSITION | 2 | 2 | 100% | +| PLASTIC | enclosure subset | 0 | 5 | 0% | + +### Deferred tabs + +| Tab | Panel | Live | Total | % | +|---|---|---:|---:|---:| +| SURFACE | CREATE | 5 | 25 | 20% | +| SURFACE | MODIFY | 10 | 26 | 38% | | SURFACE | ASSEMBLE | 1 | 20 | 5% | | SURFACE | CONFIGURE | 0 | 3 | 0% | | SURFACE | CONSTRUCT | 2 | 20 | 10% | | SURFACE | INSPECT | 1 | 25 | 4% | | SURFACE | INSERT | 1 | 11 | 9% | | SURFACE | SELECT | 0 | 15 | 0% | -| SURFACE | POSITION | 0 | 2 | 0% | -| MESH | CREATE | 1 | 5 | 20% | +| SURFACE | POSITION | 2 | 2 | 100% | +| MESH | CREATE | 2 | 5 | 40% | | MESH | PREPARE | 0 | 4 | 0% | -| MESH | MODIFY | 4 | 30 | 13% | +| MESH | MODIFY | 5 | 30 | 17% | | MESH | ASSEMBLE | 1 | 21 | 5% | | MESH | CONFIGURE | 0 | 3 | 0% | | MESH | CONSTRUCT | 2 | 20 | 10% | @@ -43,9 +72,9 @@ Generated by `cargo xtask parity` from `xtask/data/fusion-catalog.tsv` (the tool | MESH | INSERT | 0 | 10 | 0% | | MESH | SELECT | 0 | 10 | 0% | | MESH | EXPORT | 0 | 1 | 0% | -| MESH | POSITION | 0 | 2 | 0% | -| FORM | CREATE | 1 | 14 | 7% | -| FORM | MODIFY | 2 | 31 | 6% | +| MESH | POSITION | 2 | 2 | 100% | +| FORM | CREATE | 2 | 14 | 14% | +| FORM | MODIFY | 3 | 31 | 10% | | FORM | SYMMETRY | 0 | 6 | 0% | | FORM | UTILITIES | 0 | 5 | 0% | | FORM | CONSTRUCT | 2 | 20 | 10% | @@ -54,37 +83,16 @@ Generated by `cargo xtask parity` from `xtask/data/fusion-catalog.tsv` (the tool | FORM | ASSEMBLE | 0 | 1 | 0% | | FORM | SELECT | 0 | 15 | 0% | | FORM | FINISH FORM | 0 | 1 | 0% | -| SHEET METAL | CREATE | 6 | 19 | 32% | -| SHEET METAL | MODIFY | 6 | 21 | 29% | -| SHEET METAL | ASSEMBLE | 1 | 20 | 5% | -| SHEET METAL | CONFIGURE | 0 | 3 | 0% | -| SHEET METAL | CONSTRUCT | 2 | 20 | 10% | -| SHEET METAL | INSPECT | 1 | 25 | 4% | -| SHEET METAL | INSERT | 1 | 11 | 9% | -| SHEET METAL | SELECT | 0 | 15 | 0% | -| SHEET METAL | REFOLD | 0 | 1 | 0% | -| SHEET METAL | POSITION | 0 | 2 | 0% | | PLASTIC | SETUP | 0 | 2 | 0% | -| PLASTIC | CREATE | 13 | 35 | 37% | -| PLASTIC | MODIFY | 11 | 32 | 34% | +| PLASTIC | CREATE | 16 | 35 | 46% | +| PLASTIC | MODIFY | 14 | 32 | 44% | | PLASTIC | ASSEMBLE | 1 | 20 | 5% | | PLASTIC | CONFIGURE | 0 | 3 | 0% | | PLASTIC | CONSTRUCT | 2 | 20 | 10% | | PLASTIC | INSPECT | 1 | 26 | 4% | | PLASTIC | INSERT | 1 | 11 | 9% | | PLASTIC | SELECT | 0 | 15 | 0% | -| PLASTIC | POSITION | 0 | 2 | 0% | -| ASSEMBLY | INSERT | 1 | 8 | 12% | -| ASSEMBLY | CREATE | 3 | 8 | 38% | -| ASSEMBLY | RELATIONSHIPS | 0 | 11 | 0% | -| ASSEMBLY | MOTION | 0 | 3 | 0% | -| ASSEMBLY | MODIFY | 4 | 11 | 36% | -| ASSEMBLY | CONTACT | 0 | 2 | 0% | -| ASSEMBLY | CONFIGURE | 0 | 3 | 0% | -| ASSEMBLY | CONSTRUCT | 2 | 20 | 10% | -| ASSEMBLY | INSPECT | 1 | 25 | 4% | -| ASSEMBLY | SELECT | 0 | 15 | 0% | -| ASSEMBLY | POSITION | 0 | 2 | 0% | +| PLASTIC | POSITION | 2 | 2 | 100% | | MANAGE | ASSIGN | 0 | 1 | 0% | | MANAGE | RELEASE | 0 | 2 | 0% | | MANAGE | BOM | 0 | 2 | 0% | @@ -98,7 +106,7 @@ Generated by `cargo xtask parity` from `xtask/data/fusion-catalog.tsv` (the tool | UTILITIES | INSPECT | 1 | 24 | 4% | | UTILITIES | CREATE PMI | 0 | 4 | 0% | | UTILITIES | SELECT | 0 | 15 | 0% | -| UTILITIES | POSITION | 0 | 2 | 0% | +| UTILITIES | POSITION | 2 | 2 | 100% | ## Live (SOLID, SKETCH) @@ -108,10 +116,13 @@ Generated by `cargo xtask parity` from `xtask/data/fusion-catalog.tsv` (the tool - SOLID › CREATE › Sweep (`Sweep`) - SOLID › CREATE › Loft (`SolidLoft`) - SOLID › CREATE › Hole (`FusionHoleCommand`) +- SOLID › CREATE › Thread (`FusionThreadCommand`) - SOLID › CREATE › Box (`PrimitiveBox`) - SOLID › CREATE › Cylinder (`PrimitiveCylinder`) - SOLID › CREATE › Sphere (`PrimitiveSphere`) - SOLID › CREATE › Torus (`PrimitiveTorus`) +- SOLID › CREATE › Pipe (`PrimitivePipe`) +- SOLID › CREATE › Bounding Solid (`StockModelCommand`) - SOLID › CREATE › Rectangular Pattern (`PatternRectangular`) - SOLID › CREATE › Circular Pattern (`PatternCircular`) - SOLID › CREATE › Mirror (`MirrorCommand`) @@ -120,17 +131,23 @@ Generated by `cargo xtask parity` from `xtask/data/fusion-catalog.tsv` (the tool - SOLID › MODIFY › Chamfer (`FusionChamferCommand`) - SOLID › MODIFY › Shell (`FusionShellBodyCommand`) - SOLID › MODIFY › Draft (`FusionDraftCommand`) +- SOLID › MODIFY › Scale (`ModifyScale`) - SOLID › MODIFY › Combine (`FusionCombineCommand`) +- SOLID › MODIFY › Offset Face (`FusionOffsetFacesCommand`) - SOLID › MODIFY › Split Body (`FusionSplitBodyCommand`) - SOLID › MODIFY › Move/Copy (`FusionMoveCommand`) - SOLID › MODIFY › Delete (`FusionDeleteCommand`) +- SOLID › MODIFY › Physical Material (`PhysicalMaterialCommand`) - SOLID › MODIFY › Change Parameters (`ChangeParameterCommand`) - SOLID › MODIFY › Compute All (`FusionComputeAllCommand`) - SOLID › ASSEMBLE › Insert Component (`FusionImportCommandFromToolbar`) +- SOLID › ASSEMBLE › New Component (`FusionCreateNewComponentCommand`) - SOLID › CONSTRUCT › Offset Plane (`ConstructionPlaneOffsetFromPlaneCommand`) - SOLID › CONSTRUCT › Plane at Angle (`ConstructionPlaneAtAngleCommand`) - SOLID › INSPECT › Measure (`MeasureCommand`) - SOLID › INSERT › Insert Mesh (`ParaMeshInsertAlignCommand`) +- SOLID › POSITION › Capture Position (`SnapshotCmd`) +- SOLID › POSITION › Revert Position (`AsBuiltPositionsCmd`) - SKETCH › CREATE › Line (`DrawPolyline`) - SKETCH › CREATE › Midpoint Line (`SketchMidpointLine`) - SKETCH › CREATE › 2-Point Rectangle (`ShapeRectangleTwoPoint`) @@ -204,10 +221,7 @@ Generated by `cargo xtask parity` from `xtask/data/fusion-catalog.tsv` (the tool - SOLID › CREATE › Rib (`FusionRibCommand`) - SOLID › CREATE › Web (`FusionWebCommand`) - SOLID › CREATE › Emboss (`EmbossCmd`) -- SOLID › CREATE › Thread (`FusionThreadCommand`) - SOLID › CREATE › Coil (`PrimitiveCoil`) -- SOLID › CREATE › Pipe (`PrimitivePipe`) -- SOLID › CREATE › Bounding Solid (`StockModelCommand`) - SOLID › CREATE › Pattern on Path (`PatternOnPath`) - SOLID › CREATE › Geometric Pattern (`FusionPatternGeometricCommand`) - SOLID › CREATE › Thicken (`FusionSurfaceThickenCommand`) @@ -221,8 +235,6 @@ Generated by `cargo xtask parity` from `xtask/data/fusion-catalog.tsv` (the tool - SOLID › CREATE › Joint Origin (`JointOrigin`) - SOLID › CREATE › Generate Timeline (`TimelineBuilderCommand`) - SOLID › MODIFY › Edit Face (`EditFaceCommand`) -- SOLID › MODIFY › Scale (`ModifyScale`) -- SOLID › MODIFY › Offset Face (`FusionOffsetFacesCommand`) - SOLID › MODIFY › Replace Face (`FusionReplaceFaceCommand`) - SOLID › MODIFY › Split Face (`FusionSplitFaceCommand`) - SOLID › MODIFY › Silhouette Split (`FusionPartingLineSplitCmd`) @@ -235,13 +247,11 @@ Generated by `cargo xtask parity` from `xtask/data/fusion-catalog.tsv` (the tool - SOLID › MODIFY › Volumetric Lattice (`VolFieldCreateLatticeCommand`) - SOLID › MODIFY › Volumetric Texture (`VolFieldTextureCommand`) - SOLID › MODIFY › VolFieldModifyModelCommand (`VolFieldModifyModelCommand`) -- SOLID › MODIFY › Physical Material (`PhysicalMaterialCommand`) - SOLID › MODIFY › Appearance (`AppearanceCommand`) - SOLID › MODIFY › Manage Materials (`MaterialCommand`) - SOLID › MODIFY › Compute Unresolved (`FusionComputeUnresolvedCommand`) - SOLID › MODIFY › Convert (`TSpline2BRepCommand`) - SOLID › MODIFY › Bill of Materials (`MaterializedBomHybridCmd`) -- SOLID › ASSEMBLE › New Component (`FusionCreateNewComponentCommand`) - SOLID › ASSEMBLE › Duplicate With Joints (`FusionDuplicateWithJointsCommand`) - SOLID › ASSEMBLE › Constrain Components (`AssemblyMateCommand`) - SOLID › ASSEMBLE › Align Constraint (`AlignConstraintCmd`) @@ -331,8 +341,6 @@ Generated by `cargo xtask parity` from `xtask/data/fusion-catalog.tsv` (the tool - SOLID › SELECT › Select Edge Priority (`SelectEdgePriorityCommand`) - SOLID › SELECT › Select Component Priority (`SelectComponentPriorityCommand`) - SOLID › SELECT › Selection Filters (`SelectionFilterCommand`) -- SOLID › POSITION › Capture Position (`SnapshotCmd`) -- SOLID › POSITION › Revert Position (`AsBuiltPositionsCmd`) - SKETCH › CREATE › SketchConstrainer (`SketchConstrainer`) - SKETCH › CREATE › Fit Curves to Mesh Section (`FitCurvesToSectionCommand`) - SKETCH › CREATE › Spun Profile (`SpunProfileCmd`) diff --git a/xtask/src/parity.rs b/xtask/src/parity.rs index e22a638c..ab7586f5 100644 --- a/xtask/src/parity.rs +++ b/xtask/src/parity.rs @@ -24,9 +24,19 @@ const TABS: &[(&str, &str)] = &[ ("ToolsTab", "UTILITIES"), ]; -/// The tabs the headline number counts (M0 scope). +/// The tabs the headline number counts (now: SOLID and SKETCH). const HEADLINE: &[&str] = &["SOLID", "SKETCH"]; +/// The owner's scope: these tabs (and the PLASTIC subset below) count toward the in-scope +/// figure; the rest of Fusion is deferred and listed separately. +const IN_SCOPE_TABS: &[&str] = &["SOLID", "SKETCH", "ASSEMBLY", "SHEET METAL"]; +/// The PLASTIC commands in scope (enclosure features). +const PLASTIC_SUBSET: &[&str] = &["FusionBossCommand", "FusionRibCommand", "FusionWebCommand", "FusionLipCommand", "FusionSnapFitCommand"]; + +fn in_scope(e: &Entry) -> bool { + IN_SCOPE_TABS.contains(&e.tab.as_str()) || (e.tab == "PLASTIC" && PLASTIC_SUBSET.contains(&e.id.as_str())) +} + #[derive(Clone, Debug)] pub struct Entry { pub tab: String, @@ -117,13 +127,17 @@ pub fn run(root: &Path, refresh: bool) -> Result<(), String> { let head: Vec<&Entry> = catalog.iter().filter(|e| HEADLINE.contains(&e.tab.as_str())).collect(); let head_live = head.iter().filter(|e| live(e)).count(); let all_live = catalog.iter().filter(|e| live(e)).count(); + let scope: Vec<&Entry> = catalog.iter().filter(|e| in_scope(e)).collect(); + let scope_live = scope.iter().filter(|e| live(e)).count(); let mut md = format!( - "# Fusion command parity\n\nGenerated by `cargo xtask parity` from `xtask/data/fusion-catalog.tsv` (the toolbar commands of Fusion's Design workspace, ids and names only) and the live command registry (`solvecraft-cli commands`). A command counts as live when SolveCraft registers the same command id. This measures breadth, not depth; see ROADMAP.md and docs/oracle.md for depth.\n\n**SOLID + SKETCH: {head_live} / {} commands live ({:.0}%).** All Design tabs: {all_live} / {} ({:.0}%). Registered commands: {}.\n\n| Tab | Panel | Live | Total | % |\n|---|---|---:|---:|---:|\n", + "# Fusion command parity\n\nGenerated by `cargo xtask parity` from `xtask/data/fusion-catalog.tsv` (the toolbar commands of Fusion's Design workspace, ids and names only) and the live command registry (`solvecraft-cli commands`). A command counts as live when SolveCraft registers the same command id. This measures breadth, not depth; see ROADMAP.md and docs/oracle.md for depth.\n\n**In scope (SOLID, SKETCH, ASSEMBLY, SHEET METAL, PLASTIC enclosure subset): {scope_live} / {} commands live ({:.0}%).** SOLID + SKETCH: {head_live} / {} ({:.0}%). Registered commands: {}.\n\nDeferred until further notice (not in the in-scope figure): MESH, FORM, SURFACE beyond what solids need, PCB, render, animation, simulation, manufacture, drawings, MANAGE, UTILITIES and the rest of PLASTIC. All Design tabs together: {all_live} / {} ({:.0}%).\n\n| Tab | Panel | Live | Total | % |\n|---|---|---:|---:|---:|\n", + scope.len(), + pct(scope_live, scope.len()), head.len(), pct(head_live, head.len()), + ids.len(), catalog.len(), pct(all_live, catalog.len()), - ids.len() ); let mut groups: Vec<(String, String, usize, usize)> = Vec::new(); for e in &catalog { @@ -136,7 +150,13 @@ pub fn run(root: &Path, refresh: bool) -> Result<(), String> { None => groups.push((e.tab.clone(), e.panel.clone(), l, 1)), } } - for (t, p, l, n) in &groups { + for (t, p, l, n) in groups.iter().filter(|g| IN_SCOPE_TABS.contains(&g.0.as_str())) { + md += &format!("| {t} | {p} | {l} | {n} | {:.0}% |\n", pct(*l, *n)); + } + let plastic: Vec<&Entry> = catalog.iter().filter(|e| e.tab == "PLASTIC" && PLASTIC_SUBSET.contains(&e.id.as_str())).collect(); + md += &format!("| PLASTIC | enclosure subset | {} | {} | {:.0}% |\n", plastic.iter().filter(|e| live(e)).count(), plastic.len(), pct(plastic.iter().filter(|e| live(e)).count(), plastic.len())); + md += "\n### Deferred tabs\n\n| Tab | Panel | Live | Total | % |\n|---|---|---:|---:|---:|\n"; + for (t, p, l, n) in groups.iter().filter(|g| !IN_SCOPE_TABS.contains(&g.0.as_str())) { md += &format!("| {t} | {p} | {l} | {n} | {:.0}% |\n", pct(*l, *n)); } md += "\n## Live (SOLID, SKETCH)\n\n"; @@ -149,7 +169,9 @@ pub fn run(root: &Path, refresh: bool) -> Result<(), String> { } std::fs::write(root.join("docs/parity.md"), md).map_err(|e| format!("docs/parity.md: {e}"))?; println!( - "parity: SOLID+SKETCH {head_live}/{} ({:.0}%), all tabs {all_live}/{} → docs/parity.md", + "parity: in scope {scope_live}/{} ({:.0}%), SOLID+SKETCH {head_live}/{} ({:.0}%), all tabs {all_live}/{} → docs/parity.md", + scope.len(), + pct(scope_live, scope.len()), head.len(), pct(head_live, head.len()), catalog.len()