cyclecad 3.2.1 → 3.5.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 (66) hide show
  1. package/CLAUDE.md +155 -1
  2. package/DOCKER-SETUP-VERIFICATION.md +399 -0
  3. package/DOCKER-TESTING.md +463 -0
  4. package/FUSION360_MODULES.md +478 -0
  5. package/FUSION_MODULES_README.md +352 -0
  6. package/INTEGRATION_SNIPPETS.md +608 -0
  7. package/KILLER-FEATURES-DELIVERY.md +469 -0
  8. package/MODULES_SUMMARY.txt +337 -0
  9. package/QUICK_REFERENCE.txt +298 -0
  10. package/README-DOCKER-TESTING.txt +438 -0
  11. package/app/index.html +23 -10
  12. package/app/js/fusion-help.json +1808 -0
  13. package/app/js/help-module-v3.js +1096 -0
  14. package/app/js/killer-features-help.json +395 -0
  15. package/app/js/killer-features.js +1508 -0
  16. package/app/js/modules/fusion-assembly.js +842 -0
  17. package/app/js/modules/fusion-cam.js +785 -0
  18. package/app/js/modules/fusion-data.js +814 -0
  19. package/app/js/modules/fusion-drawing.js +844 -0
  20. package/app/js/modules/fusion-inspection.js +756 -0
  21. package/app/js/modules/fusion-render.js +774 -0
  22. package/app/js/modules/fusion-simulation.js +986 -0
  23. package/app/js/modules/fusion-sketch.js +1044 -0
  24. package/app/js/modules/fusion-solid.js +1095 -0
  25. package/app/js/modules/fusion-surface.js +949 -0
  26. package/app/tests/FUSION_TEST_SUITE.md +266 -0
  27. package/app/tests/README.md +77 -0
  28. package/app/tests/TESTING-CHECKLIST.md +177 -0
  29. package/app/tests/TEST_SUITE_SUMMARY.txt +236 -0
  30. package/app/tests/brep-live-test.html +848 -0
  31. package/app/tests/docker-integration-test.html +811 -0
  32. package/app/tests/fusion-all-tests.html +670 -0
  33. package/app/tests/fusion-assembly-tests.html +461 -0
  34. package/app/tests/fusion-cam-tests.html +421 -0
  35. package/app/tests/fusion-simulation-tests.html +421 -0
  36. package/app/tests/fusion-sketch-tests.html +613 -0
  37. package/app/tests/fusion-solid-tests.html +529 -0
  38. package/app/tests/index.html +453 -0
  39. package/app/tests/killer-features-test.html +509 -0
  40. package/app/tests/run-tests.html +874 -0
  41. package/app/tests/step-import-live-test.html +1115 -0
  42. package/app/tests/test-agent-v3.html +93 -696
  43. package/architecture-dashboard.html +1970 -0
  44. package/docs/API-REFERENCE.md +1423 -0
  45. package/docs/BREP-LIVE-TEST-GUIDE.md +453 -0
  46. package/docs/DEVELOPER-GUIDE-v3.md +795 -0
  47. package/docs/DOCKER-QUICK-TEST.md +376 -0
  48. package/docs/FUSION-FEATURES-GUIDE.md +2513 -0
  49. package/docs/FUSION-TUTORIAL.md +1203 -0
  50. package/docs/INFRASTRUCTURE-GUIDE-INDEX.md +327 -0
  51. package/docs/KEYBOARD-SHORTCUTS.md +402 -0
  52. package/docs/KILLER-FEATURES-INTEGRATION.md +412 -0
  53. package/docs/KILLER-FEATURES-SUMMARY.md +424 -0
  54. package/docs/KILLER-FEATURES-TUTORIAL.md +784 -0
  55. package/docs/KILLER-FEATURES.md +562 -0
  56. package/docs/QUICK-REFERENCE.md +282 -0
  57. package/docs/README-v3-DOCS.md +274 -0
  58. package/docs/TUTORIAL-v3.md +1190 -0
  59. package/docs/architecture-dashboard.html +1970 -0
  60. package/docs/architecture-v3.html +1038 -0
  61. package/linkedin-post-v3.md +58 -0
  62. package/package.json +1 -1
  63. package/scripts/dev-setup.sh +338 -0
  64. package/scripts/docker-health-check.sh +159 -0
  65. package/scripts/integration-test.sh +311 -0
  66. package/scripts/test-docker.sh +515 -0
@@ -0,0 +1,529 @@
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 Solid 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
+ </style>
197
+ </head>
198
+ <body>
199
+ <div class="app-container">
200
+ <iframe id="appFrame" src="../index.html"></iframe>
201
+ </div>
202
+
203
+ <div class="test-panel">
204
+ <div class="test-header">
205
+ <div class="test-title">Solid Modeling Tests</div>
206
+ <div class="test-stats">
207
+ <div class="stat-box pass">
208
+ <div class="stat-label">PASS</div>
209
+ <div class="stat-value" id="passCount">0</div>
210
+ </div>
211
+ <div class="stat-box fail">
212
+ <div class="stat-label">FAIL</div>
213
+ <div class="stat-value" id="failCount">0</div>
214
+ </div>
215
+ <div class="stat-box skip">
216
+ <div class="stat-label">SKIP</div>
217
+ <div class="stat-value" id="skipCount">0</div>
218
+ </div>
219
+ </div>
220
+ <div class="progress-bar">
221
+ <div class="progress-fill" id="progressFill"></div>
222
+ </div>
223
+ </div>
224
+
225
+ <div class="test-controls">
226
+ <button onclick="runAllTests()">Run All Tests</button>
227
+ <button class="secondary" onclick="runCategory('basic')">Basic Ops</button>
228
+ <button class="secondary" onclick="runCategory('advanced')">Advanced</button>
229
+ <button class="secondary" onclick="runCategory('features')">Features</button>
230
+ <button class="secondary" onclick="runCategory('patterns')">Patterns</button>
231
+ </div>
232
+
233
+ <div class="test-log" id="testLog"></div>
234
+
235
+ <div class="test-footer">
236
+ <div id="testStatus">Ready to test</div>
237
+ </div>
238
+ </div>
239
+
240
+ <script>
241
+ const tests = {
242
+ basic: [
243
+ { name: 'Extrude', fn: testExtrude },
244
+ { name: 'Revolve', fn: testRevolve },
245
+ { name: 'Hole', fn: testHole },
246
+ { name: 'Pocket', fn: testPocket },
247
+ { name: 'Pad', fn: testPad },
248
+ ],
249
+ advanced: [
250
+ { name: 'Sweep', fn: testSweep },
251
+ { name: 'Loft', fn: testLoft },
252
+ { name: 'Boolean Union', fn: testBooleanUnion },
253
+ { name: 'Boolean Cut', fn: testBooleanCut },
254
+ { name: 'Boolean Intersect', fn: testBooleanIntersect },
255
+ { name: 'Shell', fn: testShell },
256
+ { name: 'Draft', fn: testDraft },
257
+ ],
258
+ features: [
259
+ { name: 'Fillet', fn: testFillet },
260
+ { name: 'Chamfer', fn: testChamfer },
261
+ { name: 'Thread', fn: testThread },
262
+ { name: 'Rib', fn: testRib },
263
+ { name: 'Web', fn: testWeb },
264
+ { name: 'Scale', fn: testScale },
265
+ ],
266
+ patterns: [
267
+ { name: 'Rectangular Pattern', fn: testRectangularPattern },
268
+ { name: 'Circular Pattern', fn: testCircularPattern },
269
+ { name: 'Mirror Body', fn: testMirrorBody },
270
+ { name: 'Copy Body', fn: testCopyBody },
271
+ ],
272
+ };
273
+
274
+ let stats = { pass: 0, fail: 0, skip: 0, total: 0 };
275
+ let appFrame;
276
+ let appWindow;
277
+
278
+ async function init() {
279
+ appFrame = document.getElementById('appFrame');
280
+ await new Promise(resolve => {
281
+ appFrame.onload = resolve;
282
+ });
283
+ appWindow = appFrame.contentWindow;
284
+ addLog('info', 'App loaded', 'Solid modeling tests ready');
285
+ }
286
+
287
+ async function runAllTests() {
288
+ resetStats();
289
+ for (const category in tests) {
290
+ await runCategory(category);
291
+ }
292
+ addLog('info', 'Completed', `${stats.pass} passed, ${stats.fail} failed, ${stats.skip} skipped`);
293
+ }
294
+
295
+ async function runCategory(categoryName) {
296
+ resetStats();
297
+ const categoryTests = tests[categoryName] || [];
298
+
299
+ for (const test of categoryTests) {
300
+ try {
301
+ const result = await test.fn();
302
+ recordResult(test.name, result);
303
+ await delay(300);
304
+ } catch (error) {
305
+ recordResult(test.name, { pass: false, error: error.message });
306
+ }
307
+ }
308
+
309
+ updateProgress();
310
+ }
311
+
312
+ function recordResult(testName, result) {
313
+ stats.total++;
314
+ if (result.skip) {
315
+ stats.skip++;
316
+ addLog('skip', testName, 'Skipped');
317
+ } else if (result.pass) {
318
+ stats.pass++;
319
+ addLog('pass', testName, 'Passed');
320
+ } else {
321
+ stats.fail++;
322
+ addLog('fail', testName, result.error || 'Failed');
323
+ }
324
+ updateStats();
325
+ }
326
+
327
+ function updateStats() {
328
+ document.getElementById('passCount').textContent = stats.pass;
329
+ document.getElementById('failCount').textContent = stats.fail;
330
+ document.getElementById('skipCount').textContent = stats.skip;
331
+ }
332
+
333
+ function updateProgress() {
334
+ const percent = stats.total > 0 ? (stats.pass / stats.total) * 100 : 0;
335
+ document.getElementById('progressFill').style.width = percent + '%';
336
+ }
337
+
338
+ function resetStats() {
339
+ stats = { pass: 0, fail: 0, skip: 0, total: 0 };
340
+ document.getElementById('testLog').innerHTML = '';
341
+ updateStats();
342
+ }
343
+
344
+ function addLog(level, label, message) {
345
+ const log = document.getElementById('testLog');
346
+ const entry = document.createElement('div');
347
+ entry.className = `test-log-entry ${level}`;
348
+ entry.innerHTML = `<span class="log-label">${label}</span><span class="log-message">${message}</span>`;
349
+ log.appendChild(entry);
350
+ log.scrollTop = log.scrollHeight;
351
+ }
352
+
353
+ function delay(ms) {
354
+ return new Promise(resolve => setTimeout(resolve, ms));
355
+ }
356
+
357
+ // Test implementations
358
+ async function testExtrude() {
359
+ try {
360
+ const ops = appWindow.cycleCAD?.operations;
361
+ if (!ops) return { skip: true };
362
+
363
+ const result = await ops.extrude({ depth: 10, direction: 'normal' });
364
+ return { pass: result !== null };
365
+ } catch (e) {
366
+ return { pass: false, error: e.message };
367
+ }
368
+ }
369
+
370
+ async function testRevolve() {
371
+ try {
372
+ const ops = appWindow.cycleCAD?.operations;
373
+ if (!ops) return { skip: true };
374
+
375
+ const result = await ops.revolve({ axis: 'z', angle: 360, depth: 10 });
376
+ return { pass: result !== null };
377
+ } catch (e) {
378
+ return { pass: false, error: e.message };
379
+ }
380
+ }
381
+
382
+ async function testHole() {
383
+ try {
384
+ const ops = appWindow.cycleCAD?.operations;
385
+ if (!ops) return { skip: true };
386
+
387
+ const result = await ops.hole({ diameter: 10 });
388
+ return { pass: result !== null };
389
+ } catch (e) {
390
+ return { pass: false, error: e.message };
391
+ }
392
+ }
393
+
394
+ async function testPocket() {
395
+ return { skip: true };
396
+ }
397
+
398
+ async function testPad() {
399
+ return { skip: true };
400
+ }
401
+
402
+ async function testSweep() {
403
+ try {
404
+ const ops = appWindow.cycleCAD?.operations;
405
+ if (!ops) return { skip: true };
406
+
407
+ const result = await ops.sweep({ profile: null, path: null });
408
+ return { pass: result !== null };
409
+ } catch (e) {
410
+ return { pass: false, error: e.message };
411
+ }
412
+ }
413
+
414
+ async function testLoft() {
415
+ try {
416
+ const ops = appWindow.cycleCAD?.operations;
417
+ if (!ops) return { skip: true };
418
+
419
+ const result = await ops.loft({ profiles: [] });
420
+ return { pass: result !== null };
421
+ } catch (e) {
422
+ return { pass: false, error: e.message };
423
+ }
424
+ }
425
+
426
+ async function testBooleanUnion() {
427
+ try {
428
+ const ops = appWindow.cycleCAD?.operations;
429
+ if (!ops) return { skip: true };
430
+
431
+ const result = await ops.booleanUnion();
432
+ return { pass: result !== null };
433
+ } catch (e) {
434
+ return { pass: false, error: e.message };
435
+ }
436
+ }
437
+
438
+ async function testBooleanCut() {
439
+ try {
440
+ const ops = appWindow.cycleCAD?.operations;
441
+ if (!ops) return { skip: true };
442
+
443
+ const result = await ops.booleanCut();
444
+ return { pass: result !== null };
445
+ } catch (e) {
446
+ return { pass: false, error: e.message };
447
+ }
448
+ }
449
+
450
+ async function testBooleanIntersect() {
451
+ try {
452
+ const ops = appWindow.cycleCAD?.operations;
453
+ if (!ops) return { skip: true };
454
+
455
+ const result = await ops.booleanIntersect();
456
+ return { pass: result !== null };
457
+ } catch (e) {
458
+ return { pass: false, error: e.message };
459
+ }
460
+ }
461
+
462
+ async function testShell() {
463
+ return { skip: true };
464
+ }
465
+
466
+ async function testDraft() {
467
+ return { skip: true };
468
+ }
469
+
470
+ async function testFillet() {
471
+ try {
472
+ const ops = appWindow.cycleCAD?.operations;
473
+ if (!ops) return { skip: true };
474
+
475
+ const result = await ops.fillet({ radius: 2 });
476
+ return { pass: result !== null };
477
+ } catch (e) {
478
+ return { pass: false, error: e.message };
479
+ }
480
+ }
481
+
482
+ async function testChamfer() {
483
+ try {
484
+ const ops = appWindow.cycleCAD?.operations;
485
+ if (!ops) return { skip: true };
486
+
487
+ const result = await ops.chamfer({ distance: 1 });
488
+ return { pass: result !== null };
489
+ } catch (e) {
490
+ return { pass: false, error: e.message };
491
+ }
492
+ }
493
+
494
+ async function testThread() {
495
+ return { skip: true };
496
+ }
497
+
498
+ async function testRib() {
499
+ return { skip: true };
500
+ }
501
+
502
+ async function testWeb() {
503
+ return { skip: true };
504
+ }
505
+
506
+ async function testScale() {
507
+ return { skip: true };
508
+ }
509
+
510
+ async function testRectangularPattern() {
511
+ return { skip: true };
512
+ }
513
+
514
+ async function testCircularPattern() {
515
+ return { skip: true };
516
+ }
517
+
518
+ async function testMirrorBody() {
519
+ return { skip: true };
520
+ }
521
+
522
+ async function testCopyBody() {
523
+ return { skip: true };
524
+ }
525
+
526
+ window.addEventListener('DOMContentLoaded', init);
527
+ </script>
528
+ </body>
529
+ </html>