Skip to content

skills: fix gcode's export remediation; add cad-viewer test suite; repair skill deps - #335

Merged
earthtojake merged 7 commits into
earthtojake:developfrom
warun7:fix/skill-remediations-and-coverage
Aug 26, 2026
Merged

skills: fix gcode's export remediation; add cad-viewer test suite; repair skill deps#335
earthtojake merged 7 commits into
earthtojake:developfrom
warun7:fix/skill-remediations-and-coverage

Conversation

@warun7

@warun7 warun7 commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Summary

Skill-level fixes and coverage gaps found in review.

gcode remediation text pointed agents at a command that does not exist

The remediation emitted at runtime said python scripts/step --kind part <input> --stl <output>.stl - but the cad skill has no scripts/step and never had a --kind flag, so every STEP/DXF/URDF/SDF slicing flow got misdirected exactly when it needed help. The real CLI is scripts/export <input> --stl <output>.stl (gen sources and imported STEP/STP alike). Fixed in gcode_tool.py, SKILL.md:123 and references/slicer-backends.md.

cad-viewer was the only skill without a test suite

New tests/python/skills/cad-viewer/test_packaged_viewer.py:

  • static pins on the packaged layout (vendored viewer runtime, npm start script + shim, Python launcher, requirements pinning the vendored cadgen) and on SKILL.md documenting the start command and port 3245
  • a live smoke that runs npm --prefix scripts/viewer run start on a free port and asserts /__cad/server answers JSON with backend=local-fs on that exact port

Skill dependency repairs

  • skills/implicit-cad/ shipped no requirements.txt although its documented snapshot CLI hard-imports playwright -> one added (--editable ./scripts/packages/cadgen + playwright), matching sdf/srdf/urdf.
  • skills/dxf/requirements.txt was missing playwright for the same reason -> added.
  • snapshot_core.py's missing-playwright error told users to "Install the CAD skill requirements" - another skill's manifest. Now says "the invoking skill's own requirements.txt".

Dropped from scope since the scan: daemon - stdin inline handling is already documented in cadgen_daemon/client.py.

Verification

  • scripts/test/test-python.sh: all 15 suites OK, including the new cad-viewer suite (5 tests) wired into the runner via its tests/python/skills/<skill> directory
  • gcode suite green against the rewritten remediation text

warun7 added 6 commits August 26, 2026 00:49
… skill deps

Finding-driven cleanup across the skills:

The gcode skill's remediation text -- emitted to agents at runtime -- told
them to run 'python scripts/step --kind part <input> --stl <output>.stl', but
the cad skill has no scripts/step and no --kind flag. The real command is
'python scripts/export <input> --stl <output>.stl'. Fixed in gcode_tool.py,
SKILL.md and slicer-backends.md.

The cad-viewer skill was the only one without a test suite. It now has one:
static pins on the packaged layout, the documented start command and the
default port, plus a live smoke that boots  on a free port and
asserts /__cad/server answers with the local-fs backend on that port.

implicit-cad had no requirements.txt even though its documented snapshot CLI
hard-imports playwright; it now ships one, and dxf's gains the playwright it
was missing. snapshot_core's missing-playwright error no longer points agents
at another skill's manifest.
CreateProcess cannot spawn the bare 'npm' name -- it is an .cmd shim there.
Resolve it via shutil.which (skipping the live smoke when npm is absent) so
the suite runs, rather than errors, on Windows.
…utput

The Windows runner has no CAD python toolchain for the launcher's runtime
probe to find, so the smoke died in require_cadgen_runtime before serving.
The suite boots the SERVE surface, not the build toolchain -- set
VIEWER_CAD_BACKEND_VALIDATED=1 (the same escape hatch test_server_startup
uses) and include the process's captured output when it exits early.
Windows re-grabs the ephemeral probe port between our close() and the
viewer's bind, so 'already in use' is a race to retry with the next free
port, not a broken start command. The early-exit diagnostic now raises a
dedicated error carrying the captured output.
Windows NAT drivers reserve blocks of the ephemeral range where connect()
to a closed port fails without refusal, which the launcher's occupancy
probe must read as occupied -- so every ephemeral candidate reported busy.
Probe ports now come from a low, non-ephemeral band.
@earthtojake

Copy link
Copy Markdown
Owner

Looks like windows CI/CD is failing

earthtojake added a commit to warun7/text-to-cad that referenced this pull request Aug 26, 2026
The launcher's port_is_free connected to the port and counted only
ConnectionRefusedError as free. On Windows a connect to a closed port
routinely fails some other way (Hyper-V/WSL port exclusions, loopback
filtering, refusals arriving as timeouts), so every port read as occupied
and the launcher refused to start with a false "already in use" error.
Found by earthtojake#335's Windows smoke test, where four random ports Python had
just bound and released all failed the connect probe.

Bind instead: it is the same operation the server is about to perform, so
the probe cannot disagree with reality. EADDRINUSE and EACCES (Windows's
answer for excluded port ranges) keep the friendly rerun-with---port
message; any other error counts as free, because the probe exists only
for that message and the server's own bind stays authoritative.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@earthtojake
earthtojake merged commit 6f0265d into earthtojake:develop Aug 26, 2026
3 checks passed
@earthtojake

Copy link
Copy Markdown
Owner

Merged, thanks for this and for chasing the Windows failure as far as you did.

The failure was in our launcher, not your test. port_is_free probed by connecting to the port and counted only ConnectionRefusedError as free. On the Windows runners a connect to a closed port fails in other ways (Hyper-V port exclusions, refusals arriving as timeouts), so every port read as occupied and the launcher refused to start. Your _free_port comment about ports binding fine and then reading as busy pointed straight at it: once your workarounds ruled out the ephemeral range and pre-bind verification, the probe was the only suspect left. #336 changes it to probe by binding, the same operation the server performs, and your smoke test passed on Windows with that fix underneath it.

earthtojake pushed a commit that referenced this pull request Aug 26, 2026
Source ref: develop
Source commit: cce04de
Target branch: main
Previous target: 8f9a7d7
Release base: 8f9a7d7
Previous source: 96675ba

Included commits since previous source:
cce04de Merge pull request #337 from earthtojake/release/0.4.28
c3f3856 Release 0.4.28
c7e2a7c Merge pull request #305 from warun7/fix/viewer-worker-deadlock-and-timeouts
2b65d4f Merge branch 'develop' into fix/viewer-worker-deadlock-and-timeouts
6f0265d Merge pull request #335 from warun7/fix/skill-remediations-and-coverage
1e4aea1 Merge branch 'develop' into fix/skill-remediations-and-coverage
1f75ced Merge pull request #336 from earthtojake/claude/port-probe-bind
3236a5c viewer: probe port availability by binding, not connecting
99a806f tests: pick viewer-smoke ports outside the ephemeral range
5633b65 tests: call the module-level drain helper directly
788bb5d tests: retire a busy candidate port instead of failing the viewer smoke
7306fbe tests: skip the cadgen probe in the viewer start smoke, surface its output
603e812 tests: resolve npm through PATH for the viewer start smoke on Windows
0b64fa3 skills: point gcode at the real cad export CLI; cover cad-viewer; fix skill deps
24e9d28 viewer: restore run_cadgen_cold's terminal error return
3150457 tests: drive the stderr drainer from a real subprocess pipe
dbeea4f viewer: kill the CAD worker and cold subprocess on idleness, not wall clock
06bf1b3 viewer: add worker and cold process timeouts and stream large assets
@warun7

warun7 commented Aug 26, 2026

Copy link
Copy Markdown
Contributor Author

yeah that makes sense
i thought i was just running low on sleep lol
thanks

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.

2 participants