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,461 @@
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 Assembly 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">Assembly 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('joints')">Joints</button>
228
+ <button class="secondary" onclick="runCategory('components')">Components</button>
229
+ <button class="secondary" onclick="runCategory('analysis')">Analysis</button>
230
+ </div>
231
+
232
+ <div class="test-log" id="testLog"></div>
233
+
234
+ <div class="test-footer">
235
+ <div id="testStatus">Ready to test</div>
236
+ </div>
237
+ </div>
238
+
239
+ <script>
240
+ const tests = {
241
+ joints: [
242
+ { name: 'Fixed Joint', fn: testFixedJoint },
243
+ { name: 'Revolute Joint', fn: testRevoluteJoint },
244
+ { name: 'Slider Joint', fn: testSliderJoint },
245
+ { name: 'Ball Joint', fn: testBallJoint },
246
+ { name: 'Screw Joint', fn: testScrewJoint },
247
+ { name: 'Cylindrical Joint', fn: testCylindricalJoint },
248
+ { name: 'Planar Joint', fn: testPlanarJoint },
249
+ ],
250
+ components: [
251
+ { name: 'Insert Component', fn: testInsertComponent },
252
+ { name: 'Ground Component', fn: testGroundComponent },
253
+ { name: 'Suppress Component', fn: testSuppressComponent },
254
+ { name: 'Hide Component', fn: testHideComponent },
255
+ { name: 'Show Component', fn: testShowComponent },
256
+ ],
257
+ analysis: [
258
+ { name: 'Interference Detection', fn: testInterferenceDetection },
259
+ { name: 'Assembly Explode', fn: testAssemblyExplode },
260
+ { name: 'Assembly Collapse', fn: testAssemblyCollapse },
261
+ { name: 'Motion Study', fn: testMotionStudy },
262
+ { name: 'Drive Joint', fn: testDriveJoint },
263
+ ],
264
+ };
265
+
266
+ let stats = { pass: 0, fail: 0, skip: 0, total: 0 };
267
+ let appFrame;
268
+ let appWindow;
269
+
270
+ async function init() {
271
+ appFrame = document.getElementById('appFrame');
272
+ await new Promise(resolve => {
273
+ appFrame.onload = resolve;
274
+ });
275
+ appWindow = appFrame.contentWindow;
276
+ addLog('info', 'App loaded', 'Assembly tests ready');
277
+ }
278
+
279
+ async function runAllTests() {
280
+ resetStats();
281
+ for (const category in tests) {
282
+ await runCategory(category);
283
+ }
284
+ addLog('info', 'Completed', `${stats.pass} passed, ${stats.fail} failed, ${stats.skip} skipped`);
285
+ }
286
+
287
+ async function runCategory(categoryName) {
288
+ resetStats();
289
+ const categoryTests = tests[categoryName] || [];
290
+
291
+ for (const test of categoryTests) {
292
+ try {
293
+ const result = await test.fn();
294
+ recordResult(test.name, result);
295
+ await delay(300);
296
+ } catch (error) {
297
+ recordResult(test.name, { pass: false, error: error.message });
298
+ }
299
+ }
300
+
301
+ updateProgress();
302
+ }
303
+
304
+ function recordResult(testName, result) {
305
+ stats.total++;
306
+ if (result.skip) {
307
+ stats.skip++;
308
+ addLog('skip', testName, 'Skipped');
309
+ } else if (result.pass) {
310
+ stats.pass++;
311
+ addLog('pass', testName, 'Passed');
312
+ } else {
313
+ stats.fail++;
314
+ addLog('fail', testName, result.error || 'Failed');
315
+ }
316
+ updateStats();
317
+ }
318
+
319
+ function updateStats() {
320
+ document.getElementById('passCount').textContent = stats.pass;
321
+ document.getElementById('failCount').textContent = stats.fail;
322
+ document.getElementById('skipCount').textContent = stats.skip;
323
+ }
324
+
325
+ function updateProgress() {
326
+ const percent = stats.total > 0 ? (stats.pass / stats.total) * 100 : 0;
327
+ document.getElementById('progressFill').style.width = percent + '%';
328
+ }
329
+
330
+ function resetStats() {
331
+ stats = { pass: 0, fail: 0, skip: 0, total: 0 };
332
+ document.getElementById('testLog').innerHTML = '';
333
+ updateStats();
334
+ }
335
+
336
+ function addLog(level, label, message) {
337
+ const log = document.getElementById('testLog');
338
+ const entry = document.createElement('div');
339
+ entry.className = `test-log-entry ${level}`;
340
+ entry.innerHTML = `<span class="log-label">${label}</span><span class="log-message">${message}</span>`;
341
+ log.appendChild(entry);
342
+ log.scrollTop = log.scrollHeight;
343
+ }
344
+
345
+ function delay(ms) {
346
+ return new Promise(resolve => setTimeout(resolve, ms));
347
+ }
348
+
349
+ // Test implementations
350
+ async function testFixedJoint() {
351
+ try {
352
+ const assembly = appWindow.cycleCAD?.assembly;
353
+ if (!assembly) return { skip: true };
354
+
355
+ const result = await assembly.createJoint('fixed');
356
+ return { pass: result !== null };
357
+ } catch (e) {
358
+ return { pass: false, error: e.message };
359
+ }
360
+ }
361
+
362
+ async function testRevoluteJoint() {
363
+ try {
364
+ const assembly = appWindow.cycleCAD?.assembly;
365
+ if (!assembly) return { skip: true };
366
+
367
+ const result = await assembly.createJoint('revolute');
368
+ return { pass: result !== null };
369
+ } catch (e) {
370
+ return { pass: false, error: e.message };
371
+ }
372
+ }
373
+
374
+ async function testSliderJoint() {
375
+ return { skip: true };
376
+ }
377
+
378
+ async function testBallJoint() {
379
+ return { skip: true };
380
+ }
381
+
382
+ async function testScrewJoint() {
383
+ return { skip: true };
384
+ }
385
+
386
+ async function testCylindricalJoint() {
387
+ return { skip: true };
388
+ }
389
+
390
+ async function testPlanarJoint() {
391
+ return { skip: true };
392
+ }
393
+
394
+ async function testInsertComponent() {
395
+ try {
396
+ const assembly = appWindow.cycleCAD?.assembly;
397
+ if (!assembly) return { skip: true };
398
+
399
+ const result = await assembly.insertComponent();
400
+ return { pass: result !== null };
401
+ } catch (e) {
402
+ return { pass: false, error: e.message };
403
+ }
404
+ }
405
+
406
+ async function testGroundComponent() {
407
+ return { skip: true };
408
+ }
409
+
410
+ async function testSuppressComponent() {
411
+ return { skip: true };
412
+ }
413
+
414
+ async function testHideComponent() {
415
+ return { skip: true };
416
+ }
417
+
418
+ async function testShowComponent() {
419
+ return { skip: true };
420
+ }
421
+
422
+ async function testInterferenceDetection() {
423
+ return { skip: true };
424
+ }
425
+
426
+ async function testAssemblyExplode() {
427
+ try {
428
+ const assembly = appWindow.cycleCAD?.assembly;
429
+ if (!assembly) return { skip: true };
430
+
431
+ const result = await assembly.explode();
432
+ return { pass: result !== null };
433
+ } catch (e) {
434
+ return { pass: false, error: e.message };
435
+ }
436
+ }
437
+
438
+ async function testAssemblyCollapse() {
439
+ try {
440
+ const assembly = appWindow.cycleCAD?.assembly;
441
+ if (!assembly) return { skip: true };
442
+
443
+ const result = await assembly.collapse();
444
+ return { pass: result !== null };
445
+ } catch (e) {
446
+ return { pass: false, error: e.message };
447
+ }
448
+ }
449
+
450
+ async function testMotionStudy() {
451
+ return { skip: true };
452
+ }
453
+
454
+ async function testDriveJoint() {
455
+ return { skip: true };
456
+ }
457
+
458
+ window.addEventListener('DOMContentLoaded', init);
459
+ </script>
460
+ </body>
461
+ </html>