a92a418d7f
Read-only export of DEV vd03 and QA vq03 (2026-11-12): the only
Children["DelmiaRecv"] user is CvdReactor.ProcessRecipeDownload (script 4,
identical on both envs; DEV 3 / QA 9 instances), and the only ScriptAlarm
.Severity reader is DEV TestMesMachine.AlarmStatus (script 42, SBTEST01/02).
QA has no #131 work.
Adds the original (rollback) and fixed bodies, a guarded check/apply/rollback
script that re-sends every script field, and the apply plan: #52 any time,
#131 with or after the dd4f1c2a binary. The old #131 body still compiles on
main but returns banded values; the fixed body is what fails to compile on the
deployed binaries. Rig evidence for both gates is in the README.
Refs #52 #131
Claude-Session: https://claude.ai/code/session_01GT67ACmpMR7b9LGRPLijMi
145 lines
12 KiB
Markdown
145 lines
12 KiB
Markdown
# Deploy prep: site-script fixes for Gitea #52 and #131
|
||
|
||
**Prepared:** 2026-11-12. **Not applied** to DEV or QA. Applying it is a deploy and needs the owner's approval.
|
||
|
||
**Where the facts come from:** a read-only export of DEV vd03 and QA vq03 taken at 2026-11-12 ~23:10 EST. The export used `template list|get --detail`, `shared-script list`, `api-method list|get`, `instance list` and `instance diff`, and nothing was written.
|
||
|
||
- **DEV** runs DisableLogin, so any credentials work.
|
||
- **QA** has login enabled. It authenticates against the box-local GLAuth (`ScadaBridge-LDAP` service), so the export used the documented `multi-role` test user there. The username and password were passed through environment variables, never on the command line.
|
||
|
||
**Validated:** on the docker rig (main binary, which includes `dd4f1c2a`). See [Rig evidence](#rig-evidence).
|
||
|
||
## Files
|
||
|
||
| Path | What |
|
||
|---|---|
|
||
| `original/CvdReactor.ProcessRecipeDownload.cs` | The live body of CvdReactor script 4. It is byte-identical on DEV and QA. **Rollback body.** |
|
||
| `original/TestMesMachine.AlarmStatus.cs` | The live body of DEV TestMesMachine script 42. **Rollback body.** |
|
||
| `original/*.meta.json` | Each script's other fields: trigger, parameters, return definition, lock and timeouts. |
|
||
| `fixed/CvdReactor.ProcessRecipeDownload.cs` | Changes one line: `Children["DelmiaRecv"]` becomes `Children["DelmiaReceiver"]`. |
|
||
| `fixed/TestMesMachine.AlarmStatus.cs` | Changes three `a.Severity` reads to `a.Priority`. It is byte-identical to `ALARM_CODE` in `docker/seed-mes-test-machine.sh` at `dd4f1c2a`. |
|
||
| `apply.sh` | Takes `check`, `apply` or `rollback` and a gate number (`52` or `131`). Details below. |
|
||
|
||
### What `apply.sh` does
|
||
|
||
- **`check`** only reads.
|
||
- **`apply` and `rollback`** refuse to touch a script unless its live body is byte-identical to the expected file.
|
||
- **Metadata:** they re-send every metadata field. `template script update` *replaces* the parameter and return definitions, so a bare `--code` update would wipe them. They then read the fields back and compare them.
|
||
- **Deploy:** they deploy the affected instances. `--no-deploy` skips this step.
|
||
|
||
## Inventory (live, 2026-11-12)
|
||
|
||
The export searched every template script and inbound API method on each env for `Children["…"]` names that aren't compositions, and for `.Severity` reads on a `ScriptAlarm`. There are no shared scripts on either env. Every instance's `instance diff` reports `isStale=false`, so the deployed scripts are the template bodies listed below.
|
||
|
||
| Env | Template / script | Problem | Instances to redeploy |
|
||
|---|---|---|---|
|
||
| DEV vd03 | `CvdReactor` (1) / `ProcessRecipeDownload` (4) | `Children["DelmiaRecv"]`. The only composition is `DelmiaReceiver`. **#52** | Z28061 (1), Z28062 (2), Z28061Sim (8) |
|
||
| QA vq03/vq04 | `CvdReactor` (1) / `ProcessRecipeDownload` (4) | Same body, byte for byte. **#52** | Z28061 (1), Z28062 (2), Z28063 (9), Z28064 (11), Z28065 (12), Z28066 (13), Z28067 (10), Z28068 (14), Z28069 (15) |
|
||
| DEV vd03 | `TestMesMachine` (30) / `AlarmStatus` (42) | Reads `a.Severity` in 3 places: the MinSeverity and MaxSeverity predicates and `Severity = a.Severity`. **#131** | SBTEST01 (9), SBTEST02 (10) |
|
||
| QA | — | **No #131 work.** QA has no TestMesMachine. Its `CvdReactor.AlarmStatus` (39) is a stub that returns `Alarms = []`. No other script calls `Alarms.*`. | — |
|
||
|
||
Every other `Children[...]` reference on both envs resolves: TestMesMachine's `LeftMESReceiver`, `RightMESReceiver` and `DelmiaReceiver`.
|
||
|
||
The inbound methods `SimpleAlarmStatusRequest` and `AlarmStatusRequest` only *pass* `MinSeverity`/`MaxSeverity` to the site script as arguments. They never read a `ScriptAlarm`, so they need no change.
|
||
|
||
Two corrections to the issue texts:
|
||
|
||
- **#131: the old body still compiles on main.** `ScriptAlarm.Severity` still exists after `dd4f1c2a`; it now holds the banded value. So the deployed scripts keep compiling and running on the new binary, but they return **wrong numbers and inverted filters** (rig evidence, Q1–Q3). The compile problem runs the other way: the **fixed** body references `ScriptAlarm.Priority`, which the deployed binaries don't have. Neither DEV `424db155` nor QA `b3021e7c` contains `dd4f1c2a`. On the rig, a body with an unknown `ScriptAlarm` member saves fine, because save does no compile check. Deploying it is refused with `Pre-deployment validation failed: … ScriptCompilation`.
|
||
- **#131: DEV's CvdReactor has no `AlarmStatus` script at all.** So `SimpleAlarmStatusRequest` for Z2806x answers "not supported". The `CvdReactor.SimpleAlarmStatus`/`AlarmStatus` pattern in `docs/plans/2026-06-30-mes-alarm-status-api.md` §5.3 is a doc pattern and is not deployed anywhere. If it is ever authored, write it with `a.Priority`.
|
||
|
||
## Order relative to the ScadaBridge binary deploy
|
||
|
||
### #52: any time, independent of the binary
|
||
|
||
The fixed body uses only APIs that the DEV and QA binaries already run, because the current body already uses them. The fix is one string literal.
|
||
|
||
- **Recommended:** apply it in the same window as the next binary deploy, so the instances redeploy only once.
|
||
- **Z28061 on the wonder boxes is also used by another team.** Agree a slot before redeploying it; the redeploy restarts the instance actor. Z28062 is the safe one to test against.
|
||
|
||
### #131: DEV only, with or after the binary that contains `dd4f1c2a`, in the same window
|
||
|
||
1. Deploy the new ScadaBridge binary to central and site.
|
||
2. Immediately run `apply.sh apply 131`, before MES alarm traffic is trusted again.
|
||
|
||
**Applied before the binary:** the template saves, but the SBTEST instance deploys are refused by pre-deployment compilation. The site keeps the old body, which is harmless. Run `apply.sh rollback 131 --no-deploy` to put the template back.
|
||
|
||
**Binary without this step:** MES alarm-status output for SBTEST01/02 changes. Values come back banded (800→250, 300→750, 700→500), and the MinSeverity and MaxSeverity filters select the wrong alarms.
|
||
|
||
**Alternative:** re-run `docker/seed-mes-test-machine.sh` against vd03. It produces the same AlarmStatus body. But it also rewrites the inbound methods `SimpleAlarmStatusRequest` and `AlarmStatusRequest` and every other TestMesMachine script, so diff those first. `apply.sh` changes only the one script.
|
||
|
||
## Apply (from the Mac, after approval)
|
||
|
||
```bash
|
||
cd ~/Desktop/ScadaBridge && dotnet build src/ZB.MOM.WW.ScadaBridge.CLI # apply.sh uses bin/Debug/net10.0/scadabridge (override: SB_CLI)
|
||
P=docs/deployment/deploy-prep/2026-11-12-gates-52-131
|
||
|
||
# DEV (DisableLogin: any credentials)
|
||
export SCADABRIDGE_URL=http://wonder-app-vd03.zmr.zimmer.com:8085 SCADABRIDGE_USERNAME=x SCADABRIDGE_PASSWORD=x
|
||
bash $P/apply.sh check 52; bash $P/apply.sh apply 52 # any time
|
||
bash $P/apply.sh check 131 # after the dd4f1c2a+ binary is up on DEV…
|
||
bash $P/apply.sh apply 131 # …in the same window
|
||
|
||
# QA (login enabled; box-local GLAuth; export the password from a prompt, not argv)
|
||
export SCADABRIDGE_URL=http://wonder-app-vq03.zmr.zimmer.com:8085 SCADABRIDGE_USERNAME=multi-role
|
||
read -rs SCADABRIDGE_PASSWORD && export SCADABRIDGE_PASSWORD
|
||
bash $P/apply.sh check 52; bash $P/apply.sh apply 52 # 9 instances; vq03 is the active central
|
||
```
|
||
|
||
**Manual equivalent:**
|
||
|
||
1. Update the script with `scadabridge template script update`, passing every flag:
|
||
- `--id <script id> --name <name> --trigger-type <type> --code "$(cat fixed/<x>.cs)"`
|
||
- `--parameters "<parameterDefinitions>"` and `--return-def "<returnDefinition>"`, both from `original/<x>.meta.json`
|
||
2. Run `scadabridge instance deploy --id <n>` for each instance in the inventory.
|
||
|
||
## Verify
|
||
|
||
- **#52 (read-only first):** run `scadabridge debug snapshot --id 2` on Z28062. `DelmiaReceiver.ReadyFlag` is the value the fixed script now reads.
|
||
- **#52 end-to-end:** a `DelmiaRecipeDownload` call drives the real Galaxy handshake on Z28062, so it needs the owner's go-ahead. Use either a live `WWNotifier` call or `scadabridge flow-debug run-method --method-id 4 --params '{"MachineCode":"Z28062",…}'`.
|
||
- The answer must no longer be `Receiver ready flag not set to true` while the flag is true.
|
||
- The DEV site log must stop showing `GetAttribute: attribute 'DelmiaRecv.ReadyFlag' not found`.
|
||
- **#131:** on vd03, run `SCADABRIDGE_URL=http://wonder-app-vd03.zmr.zimmer.com:8085 bash docker/verify-mes-test-machine.sh` (the `RECIPE_ROOT`/`RECIPE_OUTSIDE` values are in its header). Groups C and D must pass: C3 `Severity == 800`, C7 MinSeverity 500, C9 MaxSeverity 750. These are the same values the scripts returned before #129.
|
||
- Record the apply in `docs/deployment/deployment-records/`.
|
||
|
||
## Rollback
|
||
|
||
`bash $P/apply.sh rollback 52` and `bash $P/apply.sh rollback 131` write back `original/*.cs`, byte for byte, and redeploy. Rollback is guarded the same way: it refuses if the live body is not the fixed file.
|
||
|
||
Rolling #131 back while the new binary is still running brings back the banded values. Only roll it back together with the binary.
|
||
|
||
## Rig evidence
|
||
|
||
**Setup:** the docker rig on main, with `AlarmPriorityBands` in the deployed Commons. The rig was idle: no management calls in the previous 60 min.
|
||
|
||
### #52
|
||
|
||
A temporary rig template `CvdReactor` held the DEV `ProcessRecipeDownload` body and its parameter schema. It composed the rig's static `DelmiaReceiverSim` as `DelmiaReceiver`. The template and its instance GATE52RIG were deleted afterwards. Each run was driven by `flow-debug run-script`, and the `ReadyFlag` value was confirmed in `debug snapshot` first.
|
||
|
||
| Body | ReadyFlag | Result |
|
||
|---|---|---|
|
||
| original | true | `Receiver ready flag not set to true`; site WRN `attribute 'DelmiaRecv.ReadyFlag' not found on instance 'GATE52RIG'` |
|
||
| original | false | `Receiver ready flag not set to true` |
|
||
| fixed | true | Got past the flag check into the batch write: `Batch write failed: Attribute 'DelmiaReceiver.DownloadPath' is not a data-sourced attribute` (expected, see below) |
|
||
| fixed | false | `Receiver ready flag not set to true` (negative control: the flag really is read) |
|
||
|
||
The rig receiver is static, and `WriteBatchAndWaitAsync` only accepts data-sourced attributes. On the wonder boxes, `DelmiaReceiver.*` is Galaxy-bound, so the batch write proceeds there. The handshake code after the flag check is unchanged by this fix.
|
||
|
||
`apply → rollback → apply` round-tripped. The revision hash returned to `sha256:b2058525…` on rollback and `sha256:1da04831…` on apply. A repeat apply was a no-op.
|
||
|
||
### #131
|
||
|
||
The rig's `TestMesMachine` (5305) `AlarmStatus` was byte-identical to DEV's script 42 when the test started. Alarms were tripped with `VacuumPressure=12`, `DoorOpen=true` and `SensorStatus=-1`, which raises HighVacuumFault (priority 800, MES), DoorOpenAlarm (300) and SensorFault (700; MES on SBTEST02). Values are shown as (name, Severity, IsFlaggedForMES).
|
||
|
||
| Query | Original body on main (wrong) | Fixed body on main |
|
||
|---|---|---|
|
||
| Q1 SBTEST01 all | Door 750, HighVac 250, Sensor 500 | Door 300, HighVac 800, Sensor 700 |
|
||
| Q2 MinSeverity=500 | Door, Sensor | HighVac, Sensor |
|
||
| Q3 SBTEST02 FlaggedOnly + MaxSeverity=750 | HighVac, Sensor | Sensor |
|
||
| Q4 FlaggedOnly | HighVac 250 | HighVac 800 |
|
||
|
||
- **The fixed column matches the pre-#129 expectations** in `docker/verify-mes-test-machine.sh` (C3, C7, C9).
|
||
- **Compile gate (positive control):** a body with an unknown `ScriptAlarm` member saved, and its deploy was refused with `Pre-deployment validation failed: … ScriptCompilation`. That is what the fixed body would hit on the current DEV binary.
|
||
- **Guard:** with that unknown body live, `apply.sh apply 131` answered `REFUSED: live body is UNKNOWN`.
|
||
- **Round trip:** `rollback → apply` round-tripped.
|
||
- **Rig end state:** SBTEST01/02 are left on the fixed body (what `seed-mes-test-machine.sh` seeds since `dd4f1c2a`) with the alarm sources reset.
|