({ args })
| 513 | }, |
| 514 | }, |
| 515 | async run({ args }) { |
| 516 | const project = resolveProject(args.dir); |
| 517 | const samples = Math.max(1, parseInt(args.samples as string, 10) || 9); |
| 518 | const tolerance = Math.max(0, parseFloat(args.tolerance as string) || 2); |
| 519 | const timeout = Math.max(500, parseInt(args.timeout as string, 10) || 5000); |
| 520 | const maxIssues = Math.max(1, parseInt(args["max-issues"] as string, 10) || 80); |
| 521 | const at = parseAt(args.at); |
| 522 | const atTransitions = !!args["at-transitions"]; |
| 523 | const maxTransitionSamplesRaw = parseInt(args["max-transition-samples"] as string, 10); |
| 524 | const maxTransitionSamples = |
| 525 | Number.isFinite(maxTransitionSamplesRaw) && maxTransitionSamplesRaw > 0 |
| 526 | ? maxTransitionSamplesRaw |
| 527 | : undefined; |
| 528 | const strict = !!args.strict; |
| 529 | const collapseStatic = args["collapse-static"] !== false; |
| 530 | |
| 531 | // Motion verification (#1437): an optional `*.motion.json` sidecar opts the |
| 532 | // composition into seeked-timeline assertion checks. Absent → layout-only. |
| 533 | const motionSpecPath = findMotionSpec(project.dir); |
| 534 | const motionSpec = motionSpecPath |
| 535 | ? resolveMotionSpec(motionSpecPath, !!args.json) |
| 536 | : undefined; |
| 537 | |
| 538 | if (!args.json) { |
| 539 | const baseLabel = at ? `${at.length} explicit timestamp(s)` : `${samples} timeline samples`; |
| 540 | const sampleLabel = atTransitions ? `${baseLabel} + transition boundaries` : baseLabel; |
| 541 | const motionLabel = motionSpec |
| 542 | ? ` + motion spec (${motionSpec.assertions.length} assertion(s))` |
| 543 | : ""; |
| 544 | console.log( |
| 545 | `${c.accent("◆")} Inspecting layout for ${c.accent(project.name)} (${sampleLabel}${motionLabel})`, |
| 546 | ); |
| 547 | } |
| 548 | |
| 549 | try { |
| 550 | const result = await runLayoutAudit(project.dir, { |
| 551 | samples, |
| 552 | at, |
| 553 | atTransitions, |
| 554 | maxTransitionSamples, |
| 555 | timeout, |
| 556 | tolerance, |
| 557 | motion: motionSpec, |
| 558 | }); |
| 559 | if (!args.json && result.transitionSamplesDropped > 0) { |
| 560 | console.log( |
| 561 | `${c.warn("⚠")} ${result.transitionSamplesDropped} transition sample(s) omitted by --max-transition-samples; raise or drop it to sample every boundary`, |
| 562 | ); |
| 563 | } |
| 564 | const allIssues = collapseStatic |
| 565 | ? collapseStaticLayoutIssues(result.rawIssues) |
| 566 | : result.rawIssues; |
| 567 | const limited = limitLayoutIssues(allIssues, maxIssues); |
| 568 | const summary = summarizeLayoutIssues(allIssues); |
| 569 | const ok = summary.errorCount === 0 && (!strict || summary.warningCount === 0); |
| 570 | |
| 571 | if (args.json) { |
| 572 | console.log( |
nothing calls this directly
no test coverage detected