Skip to content

Conversation

@jtran
Copy link
Contributor

@jtran jtran commented Jan 7, 2026

When editing a sketch, current main re-executes the KCL program from the beginning up to and including the sketch block. But this doesn't make sense because mock execution can't call the engine. So any code prior to the sketch block that depends on engine responses will always be wrong.

This PR makes it so that engine execution properly caches needed scene objects in cached "memory" so that when we mock execute for sketch mode, we can mock execute only the sketch block and everything that's needed is available.

As part of this, we allow sketching on custom planes, i.e. from a KCL object or offsetPlane(), and faces. But the user needs to assign it to a variable first. In particular, negative planes like -XY need to be assigned to a variable first. Same with faces by using the new faceOf() to sketch on the face. You need to assign it to a variable first.

face1 = faceOf(solid1, face = tag1)
sketch(on = face1) { }

Note: This works differently from TypeScript-implemented partial execution because that works by snipping the pipeline expression out of the AST and only executing that. On the other hand, this PR works by marking the sketch block AST node, and the executor skips nodes up to it and exits immediately afterwards.


Note

Enables targeted execution for sketch editing and updates geometry primitives to support it.

  • Implement sketch-mode partial execution: skip non-relevant code, run only the chosen sketch block; add MockConfig.sketch_block_id, ExecState.sketch_mode, and skip logic in exec_ast.rs
  • Persist mock-exec state: replace cached memory with SketchModeState (stack, module infos, and scene_objects) and wire into run paths and LSP
  • Scene graph/IDs: use module-local object ID generator; expose scene_object_by_id(_mut) helpers; keep IDs stable when re-executing
  • Frontend API: switch to SketchCtor { on: String }, add only_sketch_block, execute new sketch with real engine to seed cache, and support editing/deleting with sketch-mode
  • Add Face objects to API and emit face/plane scene objects when created
  • Plane refactor: PlaneTypePlaneKind; Plane now tracks initialization via optional object_id; add ensure_sketch_plane_in_engine; update std ops (planes, sketch, gdt, extrude, shapes) and type coercions
  • Parser: enforce sketch(on = <identifier>) (no arbitrary expressions)
  • Tests and snapshots updated (object ID shifts, new face/plane objects, freedom analysis expectations)

Written by Cursor Bugbot for commit ad4f8d3. This will update automatically on new commits. Configure here.

@jtran jtran added the sketch-solve PRs changing sketch-solve functionality only. label Jan 7, 2026
@vercel
Copy link

vercel bot commented Jan 7, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
modeling-app Ready Ready Preview, Comment Jan 14, 2026 1:08am

@codspeed-hq
Copy link

codspeed-hq bot commented Jan 7, 2026

Merging this PR will improve performance by 91.7%

⚡ 1 improved benchmark
✅ 150 untouched benchmarks
🆕 1 new benchmark
⏩ 93 skipped benchmarks1

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Simulation parse_car-wheel-assembly 1,380.3 µs 720 µs +91.7%
🆕 Simulation parse_wheel-hub N/A 14.2 ms N/A

Comparing jtran/partial-execution (747b39d) with main (794d566)2

Open in CodSpeed

Footnotes

  1. 93 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

  2. No successful run was found on main (53f56ef) during the generation of this report, so 794d566 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@jtran jtran force-pushed the jtran/partial-execution branch from 1c3f2c3 to 8db6f45 Compare January 7, 2026 19:45
@jtran jtran force-pushed the jtran/partial-execution branch from 8db6f45 to 50a16a3 Compare January 8, 2026 00:08
@jtran jtran force-pushed the jtran/partial-execution branch 3 times, most recently from 4bfd370 to 775bc72 Compare January 8, 2026 22:32
@jtran jtran force-pushed the jtran/partial-execution branch from 2639c74 to 52a7c21 Compare January 9, 2026 19:50
@jtran jtran force-pushed the jtran/partial-execution branch from 52a7c21 to af1ee95 Compare January 12, 2026 16:06
@jtran jtran force-pushed the jtran/partial-execution branch from af1ee95 to 61ab327 Compare January 12, 2026 17:14
@jtran jtran force-pushed the jtran/partial-execution branch from 61ab327 to 22d2294 Compare January 12, 2026 20:47
@jtran jtran force-pushed the jtran/partial-execution branch from 22d2294 to d954f8d Compare January 12, 2026 21:08
@jtran jtran force-pushed the jtran/partial-execution branch 2 times, most recently from f688970 to 50f2484 Compare January 12, 2026 22:55
@jtran jtran force-pushed the jtran/partial-execution branch from 50f2484 to 12937c7 Compare January 13, 2026 01:17
@jtran jtran marked this pull request as ready for review January 13, 2026 01:17
@jtran jtran requested review from a team as code owners January 13, 2026 01:17
match preserve_mem {
PreserveMem::Always => {
#[cfg(feature = "artifact-graph")]
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really understand this change, what's going on here?

Copy link
Contributor Author

@jtran jtran Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When a statement is added to the end of a KCL file, we don't re-execute the whole file. We only execute that new statement.

When executing only the new statement(s) or mock executing for sketch mode, we need the scene objects that were created during the last execution, which are in the execution cache. The cache is read to create the initial module state. Depending on whether it's mock execution or engine execution, it's rehydrated differently. The preserve_mem parameter is another complication. Depending on it, we may use local_state or we may not.

I agree that this is confusing, even before this PR's changes. I researched it some to make #9511, but I still don't completely understand it. To be honest, I don't really know if I got this part all right, except the fact that the tests I made all pass. I can add comments explaining what I know.

Copy link
Contributor Author

@jtran jtran Jan 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was able to simplify this a little in b875fea. Comments added in 59406a0.

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR is being reviewed by Cursor Bugbot

Details

You are on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

@jtran jtran force-pushed the jtran/partial-execution branch from a4e769b to b875fea Compare January 14, 2026 00:43
@jtran jtran merged commit c7f6808 into main Jan 14, 2026
75 checks passed
@jtran jtran deleted the jtran/partial-execution branch January 14, 2026 01:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

sketch-solve PRs changing sketch-solve functionality only.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Partial execution of sketch block only

4 participants