Skip to content

Add a three-workflow VibeCAD click harness - #2

Closed
jkbennitt wants to merge 19 commits into
mainfrom
cursor/workflow-harness-7f69
Closed

jkbennitt wants to merge 19 commits into
mainfrom
cursor/workflow-harness-7f69

Conversation

@jkbennitt

@jkbennitt jkbennitt commented Sep 17, 2026 •

Copy link
Copy Markdown
Member

Accept the Extrude task with the visible Tasks-dock QDialogButtonBox OK, then export a non-empty STEP from the solid that has Faces (BodyResult, PartDesign::DesignBodyPublication). DesignExtrude.Shape stays null after OK. VibeCADAgentControl.py is unchanged.

Verification

  • For code changes, a test failed before the implementation and passes afterward; for non-code changes, the PR explains why TDD does not apply.
  • The PR lists the exact build and test commands and their results.
python3 -m pytest src/Mod/VibeCAD/vibecad_tests/test_workflow_harness_contract.py -q --tb=short
# before: FAILED assert 'accept_design_task' in workflows
# after:  2 passed

python3 tools/vibecad_workflow_harness_selftest.py
# ok true, 11 scenarios

python3 tools/vibecad_workflow_harness.py --fake
# passed true

Live rerun, no --fake, no rebuild, no Pixi copy:

python tools/vibecad_workflow_harness.py --judge

A pass writes a non-empty STEP from BodyResult to %LOCALAPPDATA%\\Temp\\vibecad-workflow-harness.step.

Open in Web Open in Cursor 

10-X-eng and others added 11 commits September 17, 2026 14:07
The visible tour stays a demo. Workflows post to /v1/ui/click, check
documents and the tree after each step, and run in CI against a fake
loopback channel when no display is present. Jev stays optional and
does not run without TYPESAFE_API_KEY.

Assisted-by: Cursor Grok 4.6

Co-authored-by: Jason <[email protected]>
The live judge still skips when TYPESAFE_API_KEY is unset. Fake export
files stay in a temp directory so --fake does not write into the repo.

Assisted-by: Cursor Grok 4.6

Co-authored-by: Jason <[email protected]>
Fix macOS runtime packaging and ship Codex 0.154.0 in build6
The live ribbon is the visible surface, so workflows no longer start on File.
Harness checks own pass/fail when Std_New creates a document even if the
agent reports focus_restored false. Sketch and pad now use PartDesign_NewBody,
PartDesign_NewSketch, and PartDesign_Pad, the commands that window exposes.

Co-authored-by: Jason <[email protected]>
The loaded click path only walked toolbar and menu-bar actions(), so
PartDesign_NewBody was invisible even though main.findChildren(QAction)
already listed it. Sketch now uses Sketcher_NewSketch, the name that
window lists next to New Body.

Co-authored-by: Jason <[email protected]>
Sketcher_NewSketch runs QDialog.exec() on the GUI thread that the agent
dispatch waits on, so click and status timed out. Action triggers are
queued onto the next Qt turn, and a dialog kind accepts the already
selected XY plane without moving the OS cursor.

Co-authored-by: Jason <[email protected]>
PartDesign_Pad is not a findChildren QAction while the sketch editor is open, and the rebuilt Model ribbon surfaces PartDesign_DesignExtrude instead.

Co-authored-by: Jason <[email protected]>
An empty profile makes FeatureSketchBased throw Linked shape object is empty and the extrude task panel never opens. Sketcher_CreateRectangle is the real Geometry control, but it only starts a draw handler.

Co-authored-by: Jason <[email protected]>
cursoragent and others added 8 commits September 18, 2026 02:48
Sketcher_CreateRectangle only arms a draw handler, so the harness now
adds the same Part.Circle via the existing agent /v1/run route after
leave sketch, clicks PartDesign_DesignExtrude, and writes a STEP with
Import.export. Stopping before Extrude cannot catch the empty-sketch
task-panel failure.

Co-authored-by: Jason <[email protected]>
The closed-profile and export steps store click as null, so the
self-test must not call .get on that field.

Co-authored-by: Jason <[email protected]>
…ancel.

select_sketch used addSelection(doc.Name, sketch.Name), which is not
the enable path in this tree. designProfileOperationActive() needs a
reusable sketch or InternalFace*; Edge1 disables the command. The
harness now selects InternalFace1 and calls Gui.Command.update() so
the Extrude QAction is actually enabled.

A leftover Document Recovery dialog is dismissed with its real Cancel
button before the workflows. Start Recovery is the relabeled Ok button
and is not clicked.

Co-authored-by: Jason <[email protected]>
…en copy.

Gui.isCommandActive is Command.canInvoke(). The click path required a
unique name match that was also visible, so a hidden command QAction
or disabled placeholder made Extrude look disabled after InternalFace1
already reported command_active. The click now picks the enabled
visible action, or the single enabled command action.

Co-authored-by: Jason <[email protected]>
Live 49d37d3 still returned UI_TARGET_DISABLED with no action_pick after
select_sketch reported command_active. The unique findChildren match is
not isEnabled(), so QAction.trigger() cannot fire. Queue
Gui.Command.get(name).run() when Gui.isCommandActive is true, and put
action_pick on the disabled payload.

Co-authored-by: Jason <[email protected]>
Live 9f7225e opened Unnamed2 while a leftover Sketch editor still
belonged to an earlier document. CmdSketcherLeaveSketch passes
activeDocument into leaveActiveSketch, and requireExactEditState
throws when that is not editDocument. Finish the editor with
SketcherGui.leaveActiveSketch on Gui.editDocument, then place the
circle and Extrude on the same document.

Co-authored-by: Jason <[email protected]>
Live 6714cd6 Import.export returned without creating the Windows temp
file, then getsize raised FileNotFoundError. WriterStep only throws on
hard OCCT failures. Recompute the solid, require a non-null Shape with
Faces, try Import.export, and if that path is still missing or empty
write Shape.exportStep. Do not report success unless the file exists
and is non-empty.

Co-authored-by: Jason <[email protected]>
The Tasks-dock OK is a QDialogButtonBox, not a QDialog titled OK.
After that OK, DesignExtrude.Shape stays null; BodyResult has the faces.

Co-authored-by: Jason <[email protected]>
@jkbennitt jkbennitt closed this Sep 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants