cyclecad 3.2.1 → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/DOCKER-SETUP-VERIFICATION.md +399 -0
  2. package/DOCKER-TESTING.md +463 -0
  3. package/FUSION360_MODULES.md +478 -0
  4. package/FUSION_MODULES_README.md +352 -0
  5. package/INTEGRATION_SNIPPETS.md +608 -0
  6. package/KILLER-FEATURES-DELIVERY.md +469 -0
  7. package/MODULES_SUMMARY.txt +337 -0
  8. package/QUICK_REFERENCE.txt +298 -0
  9. package/README-DOCKER-TESTING.txt +438 -0
  10. package/app/index.html +23 -10
  11. package/app/js/fusion-help.json +1808 -0
  12. package/app/js/help-module-v3.js +1096 -0
  13. package/app/js/killer-features-help.json +395 -0
  14. package/app/js/killer-features.js +1508 -0
  15. package/app/js/modules/fusion-assembly.js +842 -0
  16. package/app/js/modules/fusion-cam.js +785 -0
  17. package/app/js/modules/fusion-data.js +814 -0
  18. package/app/js/modules/fusion-drawing.js +844 -0
  19. package/app/js/modules/fusion-inspection.js +756 -0
  20. package/app/js/modules/fusion-render.js +774 -0
  21. package/app/js/modules/fusion-simulation.js +986 -0
  22. package/app/js/modules/fusion-sketch.js +1044 -0
  23. package/app/js/modules/fusion-solid.js +1095 -0
  24. package/app/js/modules/fusion-surface.js +949 -0
  25. package/app/tests/FUSION_TEST_SUITE.md +266 -0
  26. package/app/tests/README.md +77 -0
  27. package/app/tests/TESTING-CHECKLIST.md +177 -0
  28. package/app/tests/TEST_SUITE_SUMMARY.txt +236 -0
  29. package/app/tests/brep-live-test.html +848 -0
  30. package/app/tests/docker-integration-test.html +811 -0
  31. package/app/tests/fusion-all-tests.html +670 -0
  32. package/app/tests/fusion-assembly-tests.html +461 -0
  33. package/app/tests/fusion-cam-tests.html +421 -0
  34. package/app/tests/fusion-simulation-tests.html +421 -0
  35. package/app/tests/fusion-sketch-tests.html +613 -0
  36. package/app/tests/fusion-solid-tests.html +529 -0
  37. package/app/tests/index.html +453 -0
  38. package/app/tests/killer-features-test.html +509 -0
  39. package/app/tests/run-tests.html +874 -0
  40. package/app/tests/step-import-live-test.html +1115 -0
  41. package/app/tests/test-agent-v3.html +93 -696
  42. package/architecture-dashboard.html +1970 -0
  43. package/docs/API-REFERENCE.md +1423 -0
  44. package/docs/BREP-LIVE-TEST-GUIDE.md +453 -0
  45. package/docs/DEVELOPER-GUIDE-v3.md +795 -0
  46. package/docs/DOCKER-QUICK-TEST.md +376 -0
  47. package/docs/FUSION-FEATURES-GUIDE.md +2513 -0
  48. package/docs/FUSION-TUTORIAL.md +1203 -0
  49. package/docs/INFRASTRUCTURE-GUIDE-INDEX.md +327 -0
  50. package/docs/KEYBOARD-SHORTCUTS.md +402 -0
  51. package/docs/KILLER-FEATURES-INTEGRATION.md +412 -0
  52. package/docs/KILLER-FEATURES-SUMMARY.md +424 -0
  53. package/docs/KILLER-FEATURES-TUTORIAL.md +784 -0
  54. package/docs/KILLER-FEATURES.md +562 -0
  55. package/docs/QUICK-REFERENCE.md +282 -0
  56. package/docs/README-v3-DOCS.md +274 -0
  57. package/docs/TUTORIAL-v3.md +1190 -0
  58. package/docs/architecture-dashboard.html +1970 -0
  59. package/docs/architecture-v3.html +1038 -0
  60. package/linkedin-post-v3.md +58 -0
  61. package/package.json +1 -1
  62. package/scripts/dev-setup.sh +338 -0
  63. package/scripts/docker-health-check.sh +159 -0
  64. package/scripts/integration-test.sh +311 -0
  65. package/scripts/test-docker.sh +515 -0
@@ -0,0 +1,613 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>cycleCAD Sketch Tests</title>
7
+ <style>
8
+ * {
9
+ margin: 0;
10
+ padding: 0;
11
+ box-sizing: border-box;
12
+ }
13
+
14
+ body {
15
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', sans-serif;
16
+ background: #0f172a;
17
+ color: #e2e8f0;
18
+ display: flex;
19
+ height: 100vh;
20
+ gap: 1px;
21
+ }
22
+
23
+ .app-container {
24
+ flex: 0 0 70%;
25
+ background: #1a202c;
26
+ border: 1px solid #2d3748;
27
+ }
28
+
29
+ iframe {
30
+ width: 100%;
31
+ height: 100%;
32
+ border: none;
33
+ }
34
+
35
+ .test-panel {
36
+ flex: 0 0 30%;
37
+ display: flex;
38
+ flex-direction: column;
39
+ background: #1a202c;
40
+ border-left: 1px solid #2d3748;
41
+ overflow: hidden;
42
+ }
43
+
44
+ .test-header {
45
+ padding: 16px;
46
+ border-bottom: 1px solid #2d3748;
47
+ background: #0f172a;
48
+ }
49
+
50
+ .test-title {
51
+ font-size: 18px;
52
+ font-weight: 600;
53
+ margin-bottom: 12px;
54
+ color: #38bdf8;
55
+ }
56
+
57
+ .test-stats {
58
+ display: grid;
59
+ grid-template-columns: 1fr 1fr 1fr;
60
+ gap: 8px;
61
+ font-size: 12px;
62
+ }
63
+
64
+ .stat-box {
65
+ padding: 8px;
66
+ background: #1e293b;
67
+ border-radius: 4px;
68
+ border-left: 2px solid #64748b;
69
+ }
70
+
71
+ .stat-box.pass {
72
+ border-left-color: #10b981;
73
+ }
74
+
75
+ .stat-box.fail {
76
+ border-left-color: #ef4444;
77
+ }
78
+
79
+ .stat-box.skip {
80
+ border-left-color: #f59e0b;
81
+ }
82
+
83
+ .stat-label {
84
+ font-size: 11px;
85
+ color: #94a3b8;
86
+ margin-bottom: 2px;
87
+ }
88
+
89
+ .stat-value {
90
+ font-size: 18px;
91
+ font-weight: 600;
92
+ }
93
+
94
+ .test-controls {
95
+ display: flex;
96
+ gap: 8px;
97
+ padding: 12px;
98
+ border-bottom: 1px solid #2d3748;
99
+ flex-wrap: wrap;
100
+ }
101
+
102
+ button {
103
+ padding: 8px 12px;
104
+ background: #0ea5e9;
105
+ color: white;
106
+ border: none;
107
+ border-radius: 4px;
108
+ cursor: pointer;
109
+ font-size: 12px;
110
+ font-weight: 500;
111
+ transition: background 0.2s;
112
+ }
113
+
114
+ button:hover {
115
+ background: #0284c7;
116
+ }
117
+
118
+ button.secondary {
119
+ background: #475569;
120
+ }
121
+
122
+ button.secondary:hover {
123
+ background: #64748b;
124
+ }
125
+
126
+ .test-log {
127
+ flex: 1;
128
+ overflow-y: auto;
129
+ padding: 12px;
130
+ font-size: 12px;
131
+ font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
132
+ }
133
+
134
+ .test-log-entry {
135
+ margin-bottom: 8px;
136
+ padding: 8px;
137
+ background: #0f172a;
138
+ border-left: 3px solid #64748b;
139
+ border-radius: 2px;
140
+ line-height: 1.5;
141
+ }
142
+
143
+ .test-log-entry.pass {
144
+ border-left-color: #10b981;
145
+ background: rgba(16, 185, 129, 0.05);
146
+ }
147
+
148
+ .test-log-entry.fail {
149
+ border-left-color: #ef4444;
150
+ background: rgba(239, 68, 68, 0.05);
151
+ }
152
+
153
+ .test-log-entry.skip {
154
+ border-left-color: #f59e0b;
155
+ background: rgba(245, 158, 11, 0.05);
156
+ }
157
+
158
+ .test-log-entry.info {
159
+ border-left-color: #3b82f6;
160
+ background: rgba(59, 130, 246, 0.05);
161
+ }
162
+
163
+ .log-label {
164
+ font-weight: 600;
165
+ color: #38bdf8;
166
+ margin-right: 8px;
167
+ }
168
+
169
+ .log-message {
170
+ color: #cbd5e1;
171
+ }
172
+
173
+ .test-footer {
174
+ padding: 12px;
175
+ border-top: 1px solid #2d3748;
176
+ background: #0f172a;
177
+ font-size: 12px;
178
+ color: #94a3b8;
179
+ }
180
+
181
+ .progress-bar {
182
+ width: 100%;
183
+ height: 4px;
184
+ background: #1e293b;
185
+ border-radius: 2px;
186
+ overflow: hidden;
187
+ margin-top: 8px;
188
+ }
189
+
190
+ .progress-fill {
191
+ height: 100%;
192
+ background: linear-gradient(90deg, #10b981, #38bdf8, #f59e0b);
193
+ width: 0%;
194
+ transition: width 0.3s;
195
+ }
196
+
197
+ .highlight-flash {
198
+ animation: flashHighlight 0.5s ease-out;
199
+ }
200
+
201
+ @keyframes flashHighlight {
202
+ 0% {
203
+ background: rgba(16, 185, 129, 0.6);
204
+ box-shadow: 0 0 8px rgba(16, 185, 129, 0.8);
205
+ }
206
+ 100% {
207
+ background: transparent;
208
+ box-shadow: none;
209
+ }
210
+ }
211
+ </style>
212
+ </head>
213
+ <body>
214
+ <div class="app-container">
215
+ <iframe id="appFrame" src="../index.html"></iframe>
216
+ </div>
217
+
218
+ <div class="test-panel">
219
+ <div class="test-header">
220
+ <div class="test-title">Sketch Feature Tests</div>
221
+ <div class="test-stats">
222
+ <div class="stat-box pass">
223
+ <div class="stat-label">PASS</div>
224
+ <div class="stat-value" id="passCount">0</div>
225
+ </div>
226
+ <div class="stat-box fail">
227
+ <div class="stat-label">FAIL</div>
228
+ <div class="stat-value" id="failCount">0</div>
229
+ </div>
230
+ <div class="stat-box skip">
231
+ <div class="stat-label">SKIP</div>
232
+ <div class="stat-value" id="skipCount">0</div>
233
+ </div>
234
+ </div>
235
+ <div class="progress-bar">
236
+ <div class="progress-fill" id="progressFill"></div>
237
+ </div>
238
+ </div>
239
+
240
+ <div class="test-controls">
241
+ <button onclick="runAllTests()">Run All Tests</button>
242
+ <button class="secondary" onclick="runCategory('basic')">Basic Shapes</button>
243
+ <button class="secondary" onclick="runCategory('advanced')">Advanced</button>
244
+ <button class="secondary" onclick="runCategory('constraints')">Constraints</button>
245
+ <button class="secondary" onclick="runCategory('export')">Export</button>
246
+ </div>
247
+
248
+ <div class="test-log" id="testLog"></div>
249
+
250
+ <div class="test-footer">
251
+ <div id="testStatus">Ready to test</div>
252
+ </div>
253
+ </div>
254
+
255
+ <script>
256
+ const tests = {
257
+ basic: [
258
+ { name: 'Create Line', fn: testCreateLine },
259
+ { name: 'Create Rectangle', fn: testCreateRectangle },
260
+ { name: 'Create Circle', fn: testCreateCircle },
261
+ { name: 'Create Ellipse', fn: testCreateEllipse },
262
+ { name: 'Create Arc', fn: testCreateArc },
263
+ { name: 'Create Spline', fn: testCreateSpline },
264
+ { name: 'Create Slot', fn: testCreateSlot },
265
+ { name: 'Create Polygon', fn: testCreatePolygon },
266
+ ],
267
+ advanced: [
268
+ { name: 'Mirror Sketch', fn: testMirror },
269
+ { name: 'Pattern Sketch', fn: testPattern },
270
+ { name: 'Offset', fn: testOffset },
271
+ { name: 'Trim', fn: testTrim },
272
+ { name: 'Extend', fn: testExtend },
273
+ { name: 'Fillet 2D', fn: testFillet2D },
274
+ { name: 'Chamfer 2D', fn: testChamfer2D },
275
+ { name: 'Project Geometry', fn: testProjectGeometry },
276
+ ],
277
+ constraints: [
278
+ { name: 'Coincident Constraint', fn: testCoincident },
279
+ { name: 'Horizontal Constraint', fn: testHorizontal },
280
+ { name: 'Vertical Constraint', fn: testVertical },
281
+ { name: 'Parallel Constraint', fn: testParallel },
282
+ { name: 'Perpendicular Constraint', fn: testPerpendicular },
283
+ { name: 'Tangent Constraint', fn: testTangent },
284
+ { name: 'Equal Constraint', fn: testEqual },
285
+ { name: 'Fixed Constraint', fn: testFixed },
286
+ { name: 'Concentric Constraint', fn: testConcentric },
287
+ { name: 'Symmetric Constraint', fn: testSymmetric },
288
+ { name: 'Distance Constraint', fn: testDistanceConstraint },
289
+ { name: 'Angle Constraint', fn: testAngleConstraint },
290
+ ],
291
+ export: [
292
+ { name: 'Export to DXF', fn: testExportDXF },
293
+ { name: 'Export to SVG', fn: testExportSVG },
294
+ ],
295
+ };
296
+
297
+ let stats = { pass: 0, fail: 0, skip: 0, total: 0 };
298
+ let appFrame;
299
+ let appWindow;
300
+
301
+ async function init() {
302
+ appFrame = document.getElementById('appFrame');
303
+ await new Promise(resolve => {
304
+ appFrame.onload = resolve;
305
+ });
306
+ appWindow = appFrame.contentWindow;
307
+ addLog('info', 'App loaded and ready', 'Sketch tests initialized');
308
+ }
309
+
310
+ async function runAllTests() {
311
+ resetStats();
312
+ for (const category in tests) {
313
+ await runCategory(category);
314
+ }
315
+ addLog('info', 'All tests completed', `${stats.pass} passed, ${stats.fail} failed, ${stats.skip} skipped`);
316
+ }
317
+
318
+ async function runCategory(categoryName) {
319
+ resetStats();
320
+ const categoryTests = tests[categoryName] || [];
321
+
322
+ for (const test of categoryTests) {
323
+ try {
324
+ const result = await test.fn();
325
+ recordResult(test.name, result);
326
+ await delay(300);
327
+ } catch (error) {
328
+ recordResult(test.name, { pass: false, error: error.message });
329
+ }
330
+ }
331
+
332
+ updateProgress();
333
+ }
334
+
335
+ function recordResult(testName, result) {
336
+ stats.total++;
337
+ if (result.skip) {
338
+ stats.skip++;
339
+ addLog('skip', testName, 'Skipped');
340
+ } else if (result.pass) {
341
+ stats.pass++;
342
+ addLog('pass', testName, 'Passed');
343
+ } else {
344
+ stats.fail++;
345
+ addLog('fail', testName, result.error || 'Failed');
346
+ }
347
+ updateStats();
348
+ }
349
+
350
+ function updateStats() {
351
+ document.getElementById('passCount').textContent = stats.pass;
352
+ document.getElementById('failCount').textContent = stats.fail;
353
+ document.getElementById('skipCount').textContent = stats.skip;
354
+ }
355
+
356
+ function updateProgress() {
357
+ const percent = stats.total > 0 ? (stats.pass / stats.total) * 100 : 0;
358
+ document.getElementById('progressFill').style.width = percent + '%';
359
+ }
360
+
361
+ function resetStats() {
362
+ stats = { pass: 0, fail: 0, skip: 0, total: 0 };
363
+ document.getElementById('testLog').innerHTML = '';
364
+ updateStats();
365
+ }
366
+
367
+ function addLog(level, label, message) {
368
+ const log = document.getElementById('testLog');
369
+ const entry = document.createElement('div');
370
+ entry.className = `test-log-entry ${level}`;
371
+ entry.innerHTML = `<span class="log-label">${label}</span><span class="log-message">${message}</span>`;
372
+ log.appendChild(entry);
373
+ log.scrollTop = log.scrollHeight;
374
+ }
375
+
376
+ function delay(ms) {
377
+ return new Promise(resolve => setTimeout(resolve, ms));
378
+ }
379
+
380
+ // Test implementations
381
+ async function testCreateLine() {
382
+ try {
383
+ const sketch = appWindow.sketch;
384
+ if (!sketch) return { skip: true };
385
+
386
+ sketch.startLine();
387
+ sketch.addPoint(0, 0);
388
+ sketch.addPoint(100, 100);
389
+ sketch.finishLine();
390
+
391
+ return { pass: sketch.entities.length > 0 };
392
+ } catch (e) {
393
+ return { pass: false, error: e.message };
394
+ }
395
+ }
396
+
397
+ async function testCreateRectangle() {
398
+ try {
399
+ const sketch = appWindow.sketch;
400
+ if (!sketch) return { skip: true };
401
+
402
+ sketch.startRectangle();
403
+ sketch.addPoint(10, 10);
404
+ sketch.addPoint(110, 110);
405
+ sketch.finishRectangle();
406
+
407
+ return { pass: sketch.entities.length > 0 };
408
+ } catch (e) {
409
+ return { pass: false, error: e.message };
410
+ }
411
+ }
412
+
413
+ async function testCreateCircle() {
414
+ try {
415
+ const sketch = appWindow.sketch;
416
+ if (!sketch) return { skip: true };
417
+
418
+ sketch.startCircle();
419
+ sketch.addPoint(50, 50);
420
+ sketch.setRadius(30);
421
+ sketch.finishCircle();
422
+
423
+ return { pass: sketch.entities.length > 0 };
424
+ } catch (e) {
425
+ return { pass: false, error: e.message };
426
+ }
427
+ }
428
+
429
+ async function testCreateEllipse() {
430
+ try {
431
+ const sketch = appWindow.sketch;
432
+ if (!sketch) return { skip: true };
433
+
434
+ sketch.startEllipse();
435
+ sketch.addPoint(50, 50);
436
+ sketch.addPoint(80, 50);
437
+ sketch.addPoint(50, 70);
438
+ sketch.finishEllipse();
439
+
440
+ return { pass: sketch.entities.length > 0 };
441
+ } catch (e) {
442
+ return { pass: false, error: e.message };
443
+ }
444
+ }
445
+
446
+ async function testCreateArc() {
447
+ try {
448
+ const sketch = appWindow.sketch;
449
+ if (!sketch) return { skip: true };
450
+
451
+ sketch.startArc();
452
+ sketch.addPoint(50, 50);
453
+ sketch.addPoint(100, 50);
454
+ sketch.addPoint(75, 75);
455
+ sketch.finishArc();
456
+
457
+ return { pass: sketch.entities.length > 0 };
458
+ } catch (e) {
459
+ return { pass: false, error: e.message };
460
+ }
461
+ }
462
+
463
+ async function testCreateSpline() {
464
+ try {
465
+ const sketch = appWindow.sketch;
466
+ if (!sketch) return { skip: true };
467
+
468
+ sketch.startSpline();
469
+ sketch.addPoint(0, 0);
470
+ sketch.addPoint(50, 50);
471
+ sketch.addPoint(100, 0);
472
+ sketch.finishSpline();
473
+
474
+ return { pass: sketch.entities.length > 0 };
475
+ } catch (e) {
476
+ return { pass: false, error: e.message };
477
+ }
478
+ }
479
+
480
+ async function testCreateSlot() {
481
+ try {
482
+ const sketch = appWindow.sketch;
483
+ if (!sketch) return { skip: true };
484
+
485
+ sketch.startSlot();
486
+ sketch.addPoint(10, 50);
487
+ sketch.addPoint(90, 50);
488
+ sketch.setRadius(20);
489
+ sketch.finishSlot();
490
+
491
+ return { pass: sketch.entities.length > 0 };
492
+ } catch (e) {
493
+ return { pass: false, error: e.message };
494
+ }
495
+ }
496
+
497
+ async function testCreatePolygon() {
498
+ try {
499
+ const sketch = appWindow.sketch;
500
+ if (!sketch) return { skip: true };
501
+
502
+ sketch.startPolygon(6);
503
+ sketch.addPoint(50, 50);
504
+ sketch.setRadius(40);
505
+ sketch.finishPolygon();
506
+
507
+ return { pass: sketch.entities.length > 0 };
508
+ } catch (e) {
509
+ return { pass: false, error: e.message };
510
+ }
511
+ }
512
+
513
+ async function testMirror() {
514
+ return { skip: true };
515
+ }
516
+
517
+ async function testPattern() {
518
+ return { skip: true };
519
+ }
520
+
521
+ async function testOffset() {
522
+ return { skip: true };
523
+ }
524
+
525
+ async function testTrim() {
526
+ return { skip: true };
527
+ }
528
+
529
+ async function testExtend() {
530
+ return { skip: true };
531
+ }
532
+
533
+ async function testFillet2D() {
534
+ return { skip: true };
535
+ }
536
+
537
+ async function testChamfer2D() {
538
+ return { skip: true };
539
+ }
540
+
541
+ async function testProjectGeometry() {
542
+ return { skip: true };
543
+ }
544
+
545
+ async function testCoincident() {
546
+ try {
547
+ const app = appWindow.cycleCAD;
548
+ if (!app || !app.constraintSolver) return { skip: true };
549
+
550
+ const result = app.constraintSolver.addConstraint('coincident', [0, 1]);
551
+ return { pass: result !== null };
552
+ } catch (e) {
553
+ return { pass: false, error: e.message };
554
+ }
555
+ }
556
+
557
+ async function testHorizontal() {
558
+ return { skip: true };
559
+ }
560
+
561
+ async function testVertical() {
562
+ return { skip: true };
563
+ }
564
+
565
+ async function testParallel() {
566
+ return { skip: true };
567
+ }
568
+
569
+ async function testPerpendicular() {
570
+ return { skip: true };
571
+ }
572
+
573
+ async function testTangent() {
574
+ return { skip: true };
575
+ }
576
+
577
+ async function testEqual() {
578
+ return { skip: true };
579
+ }
580
+
581
+ async function testFixed() {
582
+ return { skip: true };
583
+ }
584
+
585
+ async function testConcentric() {
586
+ return { skip: true };
587
+ }
588
+
589
+ async function testSymmetric() {
590
+ return { skip: true };
591
+ }
592
+
593
+ async function testDistanceConstraint() {
594
+ return { skip: true };
595
+ }
596
+
597
+ async function testAngleConstraint() {
598
+ return { skip: true };
599
+ }
600
+
601
+ async function testExportDXF() {
602
+ return { skip: true };
603
+ }
604
+
605
+ async function testExportSVG() {
606
+ return { skip: true };
607
+ }
608
+
609
+ // Initialize when DOM is ready
610
+ window.addEventListener('DOMContentLoaded', init);
611
+ </script>
612
+ </body>
613
+ </html>