Repository navigation
P0 Studio: protect SMV/PTP baseline, send live phase table, improve operator layout #245
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
95746c7
8f900dd
ca0f4be
4bff585
51b0716
3995051
87452b3
a34492b
7a9a00e
763f3c9
4d8455b
315690b
9659134
69a33f7
858c8ea
460979d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -53,10 +53,10 @@ def main() -> None: | |
| and "root.pendingApply" in main_qml | ||
| and "pendingApply = true" in main_qml, | ||
| "table edits must expose unsent setpoints without claiming wire readback") | ||
| require("Layout.minimumHeight: root.compactLayout ? 180 : 210" in main_qml | ||
| and "Layout.fillHeight: true" in main_qml | ||
| require("Layout.preferredHeight: Math.min(410, Math.max(215, root.height - 365))" in main_qml | ||
| and "Layout.maximumHeight: 410" in main_qml | ||
| and "ColumnLayout {" in main_qml, | ||
| "voltage and current must stack vertically and fill the workspace") | ||
| "voltage and current must stack vertically with bounded content height") | ||
| require('property bool ptpDefaultStartAttempted: false' in main_qml | ||
| and 'root.ptpDefaultStartAttempted = true' in main_qml | ||
| and '!root.startPtpRole("SOURCE")' in main_qml, | ||
|
|
@@ -76,6 +76,30 @@ def main() -> None: | |
| and "root.ptpRestoreChecks > 120" in main_qml | ||
| and "root.ptpDesiredForSession = false" in main_qml, | ||
| "PTP user intent restoration must be bounded, explicit and cancellable") | ||
| ribbon = source("ModernRibbon.qml") | ||
| checkbox = source("StudioDarkCheckBox.qml") | ||
| calm = source("CalmButton.qml") | ||
| require("Layout.preferredWidth: bar.compact ? 232 : 286" in ribbon | ||
| and "font.pixelSize: bar.compact ? 21 : 25" in ribbon, | ||
| "operator brand/logo must stay legible") | ||
|
Comment on lines
+82
to
+84
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The Qt CI workflow runs this script, but the newly required layout and branding strings contradict assertions that remain later in the same function. Running Useful? React with 👍 / 👎. |
||
| require("indicator: Rectangle {" in checkbox, | ||
| "checkbox must keep one stable custom indicator on hover") | ||
| require("anchors.centerIn: parent" in calm, | ||
| "button caption needs horizontal centering") | ||
| require("root.sendSignal(group, row)" in main_qml | ||
| and "Layout.fillHeight: false" in main_qml | ||
| and "Layout.preferredHeight: 196" in main_qml, | ||
| "tables and live sent phases must use explicit bounded layout") | ||
| require('property bool ptpDefaultStartAttempted: false' in main_qml | ||
| and 'root.startPtpRole("SOURCE")' in main_qml | ||
| and "device.deviceVerified" in main_qml, | ||
| "default PTP must reuse verified session ownership") | ||
| device_cpp = (STUDIO / "src/DeviceController.cpp").read_text(encoding="utf-8") | ||
| require('commands << QStringLiteral("FREQ %1")' in device_cpp | ||
| and "const double phase = row.at(1).toDouble(&phaseOk);" in device_cpp | ||
| and "const double angleMdeg = phaseDegrees * 1000.0;" in device_cpp | ||
| and "commands << QStringLiteral(\"START\");" in device_cpp, | ||
| "START must send actual eight model phases as millidegree SET commands before START") | ||
| matrix = source("SignalMatrix.qml") | ||
| require("Layout.fillHeight: true" in matrix | ||
| and "Layout.minimumHeight: 34" in matrix | ||
|
|
@@ -93,9 +117,9 @@ def main() -> None: | |
| and main_qml.index("id: voltageMatrix") < main_qml.index("id: currentMatrix"), | ||
| "Voltage and Current need a vertical, flexible-height editor workspace") | ||
| ribbon_qml = source("ModernRibbon.qml") | ||
| require("Layout.preferredWidth: bar.compact ? 220 : 270" in ribbon_qml | ||
| and "font.pixelSize: bar.compact ? 20 : 22" in ribbon_qml | ||
| and "width: 44" in ribbon_qml, | ||
| require("Layout.preferredWidth: bar.compact ? 232 : 286" in ribbon_qml | ||
| and "font.pixelSize: bar.compact ? 21 : 25" in ribbon_qml | ||
| and "width: 53" in ribbon_qml, | ||
| "SMV Injector branding must be readable at compact and normal widths") | ||
| device_controller = (STUDIO / "src/DeviceController.cpp").read_text(encoding="utf-8") | ||
| workflow = source("WorkflowBar.qml") | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| # ARStack Studio SV–PTP no-regression baseline — 18 Oct 2026 | ||
|
|
||
| This document freezes observed evidence and operator-visible behavior without calling host-receiver timing a hardware accuracy certificate. | ||
|
|
||
| ## Known-good evidence | ||
|
|
||
| The user's independent 120-second ASIX/Npcap capture demonstrated: 480,294 canonical SV frames (svID ARSTACK_SV01, APPID 0x4000), no diagnostic mirror, no smpCnt gaps/duplicates, 120 counter wraps, all smpSynch=1 under SOURCE + AUTO. PTP domain 0 carried 120 Announce, 120 Sync, and 120 matched Follow_Up. Host-relative smpCnt=0 to PTP epoch estimate median +48.9us, P95 +67.2us. This includes frame-publication and capture path delay; it is NOT a hardware sample-clock phase-error guarantee. | ||
|
|
||
| ## Non-regression gates | ||
|
|
||
| 1. Native Preview firmware must match the exact GUI commit and include PTP phase servo, MAC TX timing evidence, and broadcast mirror disabled. Never regress to a v0.1.1 bundle built from the old main firmware. | ||
| 2. Local smpSynch=1 is qualified by actual sample timing; neither PTP visibility nor manual metadata suffices. Do not assert global smpSynch=2 for a local class-248 SOURCE. | ||
| 3. At 50 Hz / 80 SPC, canonical SV rate is 4000 fps and smpCnt wraps 3999→0, with no healthy-stream discontinuities. | ||
| 4. Every START flushes editor debounces and sends the eight current table setpoints as an ordered FREQ/SET/ENABLE/SHAPE/START batch; serial phase encoding is signed millidegrees (Ia −30.00° -> -30000). No silent reuse of stale ESP32-P4 setpoints. | ||
| 5. Editing live phase-link behavior must use the same ListModels as the visible table and enqueue all affected phases. Do not claim on-wire equality without PCAP and timestamp-matched setpoints. | ||
| 6. PTP SOURCE has exactly one owner for the verified-session default ON behavior; user OFF cancels it. Do not add duplicate startup timers, modal barriers, or write PTP/SMV clock state from presentation. | ||
| 7. GUI: readable brand/logo, consistently centered buttons, dark text for pale hover, only one stable checkbox indicator, vertical voltage/current tables with bounded heights; preserve Windows DPI 100/150/175 acceptance. | ||
| 8. GUI-only improvements must not alter Ethernet SV frames, PTP hardware epoch lease, timestamp/ISR behavior, wire quality, or smpCnt logic. | ||
|
|
||
| ## Next evidence for release | ||
|
|
||
| Studio Qt CI, Windows Lifecycle and exact-head Native Preview must pass. After installation, inspect serial FREQ/SET phase commands and independent decoded waveforms for Ia −30°, Ib −150°, Ic +90° and the requested Ua/Ub/Uc. Capture >120 seconds after AUTO becomes local 1, include STOP/START and PTP SOURCE fault/recovery. Confirm no missing counters and stable epoch alignment. Physical synchronization accuracy and cross-vendor subscriber acceptance are separate from host timing screening. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When the device command queue is full or locked by an exclusive transaction, each
sendSignal()still returns true becauseDeviceController::sendCommandBatch()reports only whether the queued Qt invocation was scheduled; the actual admission failure occurs later inDeviceIoWorker::enqueueCommandsInternal(). Consequently, toggling 3-phase link can reject some or all eight SETs while this line clearspendingApply, falsely presenting the visible table as applied. Send these SETs as one admission-checked batch or retain the pending state until worker acceptance is reported.AGENTS.md reference: AGENTS.md:L116-L116
Useful? React with 👍 / 👎.