docs(plan): followups-and-tickets — 10 tasks closing every recorded follow-up
This commit is contained in:
@@ -0,0 +1,461 @@
|
||||
# Follow-ups and Tickets Implementation Plan
|
||||
|
||||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers-extended-cc:subagent-driven-development
|
||||
> to execute this plan task-by-task in this session.
|
||||
|
||||
**Goal:** Close every follow-up recorded in `docs/plans/2026-08-17-followup-closeout.md`
|
||||
(as-built notes, "Follow-ups recorded, not started") plus the two ticket-worthy windev
|
||||
findings — leaving no recorded open item anywhere.
|
||||
|
||||
**Architecture:** No new components. Ten independent closures: two toolchain/script fixes
|
||||
(Check 4 Windows pin, Gradle 9 `checkGeneratedClean`), two dashboard display gaps
|
||||
(Settings recent-limit rows, push-driven Alarms truncation banner), two documentation
|
||||
audits (Server-0xx resolution regression sweep, `Authentication.md` runnable-examples
|
||||
pass), one worker-test investigation (the deterministic `WorkerPipeSessionTests` failure
|
||||
on windev), one bounded rig probe (ack-leg unblock paths), a windev verification pass
|
||||
(including the `protoc-gen-go-grpc` 1.6.2 pin install), and bookkeeping.
|
||||
|
||||
**Tech Stack:** PowerShell (codegen scripts), Gradle/Groovy (Java client), Blazor
|
||||
server-side Razor + xUnit/bUnit-style render tests (dashboard), .NET Framework 4.8 x86
|
||||
xUnit (worker tests, windev-only), wnwrap probe harness (windev rig), Markdown.
|
||||
|
||||
**Branch:** `feat/followups-tickets` off `main` (`45058d5`).
|
||||
|
||||
---
|
||||
|
||||
## Ground rules for every implementer subagent
|
||||
|
||||
- **Git discipline (Mac tree):** NEVER `git stash`, `git reset`, `git clean`, or
|
||||
`git checkout <sha/branch>`. Commit with **pathspecs on the commit**:
|
||||
`git commit -m "..." -- <paths>`. If `index.lock` blocks you, wait 5 s and retry.
|
||||
- **Build/test lock:** before any `dotnet build`/`dotnet test`/`cargo`/`gradle`/`go test`
|
||||
on the Mac, acquire the lock:
|
||||
`mkdir /private/tmp/claude-501/-Users-dohertj2-Desktop-MxAccessGateway/f36938ae-bbca-4245-b5c9-fac512d69e22/scratchpad/buildlock`
|
||||
(retry with backoff until it succeeds); `rmdir` it on ALL exit paths, including failure.
|
||||
- **Quality gates:** `TreatWarningsAsErrors=true`, `Nullable=enable`. Follow
|
||||
`docs/style-guides/CSharpStyleGuide.md` (file-scoped namespaces, `sealed` by default,
|
||||
`Async` suffix). Update affected docs in the same commit as source.
|
||||
- **MXAccess parity:** never synthesize events; the dashboard/gateway forwards only what
|
||||
the worker/monitor emits. The `snapshot_status` frame is a gateway-status frame (like
|
||||
`provider_status`), NOT a synthesized MXAccess event.
|
||||
- **Never log or echo secrets, API keys, credentials, or tag values.**
|
||||
- **Scope contract:** the task's `Files:` block is the `files_to_edit` contract. If the
|
||||
task needs other files, that is a plan defect — surface it in your report, don't
|
||||
silently expand scope. (Exception: Tasks 7 and 8 are investigations; their Files list
|
||||
is starting points, and they must report every file they end up touching.)
|
||||
- **Windev access (Tasks 7, 8, 9 only):** `ssh windev` lands in PowerShell. The CI clone
|
||||
is `C:\build\mxaccessgw-ci`. Quirks: the first `slnx` build after a pull often fails on
|
||||
stale Contracts obj artifacts (CS2001/CS0016) — clear the Contracts `obj`/`bin` and
|
||||
rebuild, it is not a regression; the gateway suite is load-sensitive — rerun a filtered
|
||||
subset before believing a flake. To get branch code there:
|
||||
`git -C C:\build\mxaccessgw-ci fetch origin && git -C C:\build\mxaccessgw-ci checkout feat/followups-tickets && git -C C:\build\mxaccessgw-ci pull` —
|
||||
which requires the Mac side to have pushed the branch first (the controller pushes;
|
||||
ask if the branch tip you need is not on origin).
|
||||
|
||||
---
|
||||
|
||||
### Task 1: check-codegen Check 4 — tolerate the Windows `.exe` version banner
|
||||
|
||||
**Classification:** small
|
||||
**Estimated implement time:** ~4 min
|
||||
**Parallelizable with:** Task 2, Task 3, Task 4, Task 5, Task 7
|
||||
|
||||
**Files:**
|
||||
- Modify: `clients/go/generate-proto.ps1` (pin compare at `:52-67`, pin constants at `:10-11`)
|
||||
- Modify: any doc that states Check 4 is unrunnable on Windows (grep `docs/` and
|
||||
`code-reviews/` for "Check 4"; `docs/GatewayTesting.md` is the likely holder)
|
||||
|
||||
**Problem.** On Windows the plugins report their invoked name with an `.exe` suffix
|
||||
(`protoc-gen-go.exe v1.36.11`), so the exact-string compare against
|
||||
`'protoc-gen-go v1.36.11'` throws and Check 4 (which shells this script) is unrunnable on
|
||||
any Windows host — including windev, the box where regeneration actually happens.
|
||||
|
||||
**Step 1: Normalize the banner before comparing.** Add a small helper and use it for both
|
||||
plugin compares (protoc stays warn-only and gets the same normalization for a fair warn):
|
||||
|
||||
```powershell
|
||||
function Get-NormalizedToolVersion {
|
||||
# On Windows a plugin reports its argv[0] name, so the banner carries an `.exe`
|
||||
# suffix ("protoc-gen-go.exe v1.36.11"). Strip it so the pin compare is
|
||||
# host-independent; the version part must still match exactly.
|
||||
param([string]$RawBanner)
|
||||
return ($RawBanner -replace '\.exe(?=\s)', '')
|
||||
}
|
||||
```
|
||||
|
||||
Apply to `$protocGenGoVersion`, `$protocGenGoGrpcVersion`, `$protocVersion` at the point
|
||||
each is read (`:54`, `:59`, `:64`), keeping the pinned constants unchanged. Update the
|
||||
comment block at `:4-9` to note the normalization.
|
||||
|
||||
**Step 2: Verify on macOS.** Acquire the build lock, then run
|
||||
`pwsh scripts/check-codegen.ps1` — all 4 checks must pass (banner has no `.exe` here, so
|
||||
this proves no regression). Also assert the helper logic directly:
|
||||
`pwsh -c "& { <paste helper> ; Get-NormalizedToolVersion 'protoc-gen-go.exe v1.36.11' }"`
|
||||
must print `protoc-gen-go v1.36.11`, and a name-only match check for
|
||||
`protoc-gen-go-grpc.exe 1.6.2` → `protoc-gen-go-grpc 1.6.2`.
|
||||
|
||||
**Step 3: Fix the stale prose.** Wherever docs state Check 4 cannot run on Windows,
|
||||
rewrite to: Check 4 runs on Windows; the plugin pins must be installed
|
||||
(`go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.36.11`,
|
||||
`go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.6.2`).
|
||||
Do NOT edit `docs/plans/2026-08-17-followup-closeout.md` — Task 10 owns plan bookkeeping.
|
||||
|
||||
**Step 4: Commit** with pathspecs on the touched files:
|
||||
`fix(codegen): normalize .exe off plugin version banners so Check 4 runs on Windows`.
|
||||
|
||||
Windows-side proof is deferred to Task 9 (windev runs check-codegen 1–4 after installing
|
||||
the 1.6.2 pin).
|
||||
|
||||
---
|
||||
|
||||
### Task 2: Gradle 9 — revive `checkGeneratedClean` without `Project.exec`
|
||||
|
||||
**Classification:** small
|
||||
**Estimated implement time:** ~4 min
|
||||
**Parallelizable with:** Task 1, Task 3, Task 4, Task 5, Task 7
|
||||
|
||||
**Files:**
|
||||
- Modify: `clients/java/zb-mom-ww-mxgateway-client/build.gradle` (`checkGeneratedClean`, `:71-92`)
|
||||
- Modify: `docs/GatewayTesting.md` only if it describes the task's mechanism (grep
|
||||
`checkGeneratedClean`)
|
||||
|
||||
**Problem.** The task's `doLast` calls the script-level `exec {}` (i.e. `Project.exec`),
|
||||
removed in Gradle 9 — the task is dead on any Gradle 9 host.
|
||||
|
||||
**Step 1: Replace with `ProviderFactory.exec`** (available since Gradle 7.5, so it works
|
||||
on both the current toolchain and Gradle 9, and is configuration-cache safe). Capture the
|
||||
provider reference at configuration time, call `.get()` in `doLast` so the git status
|
||||
runs at execution time:
|
||||
|
||||
```groovy
|
||||
tasks.register('checkGeneratedClean') {
|
||||
group = 'verification'
|
||||
description = 'Fails if the committed generated Java tree differs from a fresh regeneration.'
|
||||
dependsOn 'generateProto'
|
||||
def generatedDir = 'clients/java/src/main/generated'
|
||||
def repoRoot = rootProject.projectDir.parentFile.parentFile
|
||||
// Project.exec was removed in Gradle 9; ProviderFactory.exec runs the probe lazily
|
||||
// at doLast time and works on Gradle 7.5+.
|
||||
def gitStatus = providers.exec {
|
||||
workingDir = repoRoot
|
||||
commandLine 'git', 'status', '--porcelain', '--', generatedDir
|
||||
ignoreExitValue = true
|
||||
}
|
||||
doLast {
|
||||
def dirty = gitStatus.standardOutput.asText.get().trim()
|
||||
if (!dirty.isEmpty()) {
|
||||
throw new GradleException(
|
||||
"Generated Java is stale:\n${dirty}\n" +
|
||||
"Regenerate and commit the Java client after a .proto change " +
|
||||
"(gradle :zb-mom-ww-mxgateway-client:generateProto).")
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Preserve the explanatory comment block above the task (`:61-70`) — amend it, don't delete.
|
||||
|
||||
**Step 2: Verify.** Acquire the build lock. From `clients/java`:
|
||||
`gradle :zb-mom-ww-mxgateway-client:checkGeneratedClean` must pass (tree is clean), and
|
||||
`gradle --version` must be recorded in your report. Then prove the failure path: touch a
|
||||
scratch edit inside `clients/java/src/main/generated/` (append a comment line to one
|
||||
generated file), rerun the task, confirm it fails with the stale message, then **revert
|
||||
that file with `git checkout -- <that one file>`** (this narrow file-level checkout is the
|
||||
one permitted use; the file is committed generated output).
|
||||
|
||||
**Step 3: Commit:**
|
||||
`fix(java-client): checkGeneratedClean via ProviderFactory.exec — Project.exec is gone in Gradle 9`.
|
||||
|
||||
---
|
||||
|
||||
### Task 3: SettingsPage — RecentFaultLimit / RecentSessionLimit rows
|
||||
|
||||
**Classification:** small
|
||||
**Estimated implement time:** ~4 min
|
||||
**Parallelizable with:** Task 1, Task 2, Task 4, Task 5, Task 7
|
||||
|
||||
**Files:**
|
||||
- Modify: `src/ZB.MOM.WW.MxGateway.Server/Dashboard/Components/Pages/SettingsPage.razor`
|
||||
(dashboard rows around `:98-102`)
|
||||
- Test: `src/ZB.MOM.WW.MxGateway.Tests/` — extend the existing settings render coverage
|
||||
(`SettingsPageTagVisibilityRenderTests` or its sibling settings render test class; find
|
||||
with `grep -rl "SettingsPage" src/ZB.MOM.WW.MxGateway.Tests`)
|
||||
- Modify: `docs/GatewayDashboardDesign.md` only if it enumerates settings rows (grep
|
||||
`RecentFaultLimit` / "Snapshot interval" there first)
|
||||
|
||||
**Problem.** `EffectiveDashboardConfiguration` carries `RecentFaultLimit` and
|
||||
`RecentSessionLimit` (already projected by `GatewayConfigurationProvider.cs:62-63`), but
|
||||
`SettingsPage` renders every member except these two.
|
||||
|
||||
**Step 1: Write the failing test.** Extend the settings render test: rendered page
|
||||
contains `Recent fault limit` with the configured value and `Recent session limit` with
|
||||
the configured value (use non-default values in the arranged options so the assertion
|
||||
proves plumbing, not defaults).
|
||||
|
||||
**Step 2: Run it, expect FAIL** (`dotnet test --filter "FullyQualifiedName~SettingsPage"`
|
||||
under the build lock).
|
||||
|
||||
**Step 3: Add the two rows** next to the other Dashboard rows (after "Snapshot interval",
|
||||
matching the existing `<tr><th scope="row">…</th><td>…</td></tr>` idiom):
|
||||
|
||||
```razor
|
||||
<tr><th scope="row">Recent fault limit</th><td>@Snapshot.Configuration.Dashboard.RecentFaultLimit</td></tr>
|
||||
<tr><th scope="row">Recent session limit</th><td>@Snapshot.Configuration.Dashboard.RecentSessionLimit</td></tr>
|
||||
```
|
||||
|
||||
**Step 4: Run the filtered test, expect PASS.**
|
||||
|
||||
**Step 5: Commit:**
|
||||
`feat(dashboard): settings page shows RecentFaultLimit and RecentSessionLimit`.
|
||||
|
||||
---
|
||||
|
||||
### Task 4: Authentication.md — runnable-as-written examples pass
|
||||
|
||||
**Classification:** small
|
||||
**Estimated implement time:** ~5 min
|
||||
**Parallelizable with:** Task 1, Task 2, Task 3, Task 5, Task 7
|
||||
|
||||
**Files:**
|
||||
- Modify: `docs/Authentication.md`
|
||||
|
||||
**Problem.** The doc's CLI/scope examples were flagged during the previous branch as not
|
||||
runnable as written — notably samples that grant only invoke/event scopes with no
|
||||
`session:open`, which since Server-004's validation would produce keys that cannot open a
|
||||
session (or, for unknown scope strings, be rejected at create time). The canonical scope
|
||||
catalog is: `session:open`, `session:close`, `invoke:read`, `invoke:write`,
|
||||
`invoke:secure`, `events:read`, `metadata:read`, `admin`; the verb is `apikey create-key`
|
||||
with `--key-id` required.
|
||||
|
||||
**Step 1: Sweep every example** (` ```-fenced blocks and inline commands) in the doc. For
|
||||
each, either (a) make it runnable as written — canonical verb, required flags, only
|
||||
canonical scopes, scope sets that support what the surrounding prose says the key is for
|
||||
(a key described as opening sessions needs `session:open`) — or (b) if it is deliberately
|
||||
a fragment, mark it explicitly (e.g. "illustrative — not a complete command"). Prefer (a);
|
||||
use (b) only where completeness would obscure the point being made.
|
||||
|
||||
**Step 2: Cross-check** each corrected scope list against
|
||||
`src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/GatewayScopes.cs` (read-only) —
|
||||
do not invent scope strings.
|
||||
|
||||
**Step 3: Commit:** `docs(auth): make Authentication.md examples runnable as written`.
|
||||
|
||||
---
|
||||
|
||||
### Task 5: AlarmsPage — push-driven truncation banner from the snapshot_status frame
|
||||
|
||||
**Classification:** standard
|
||||
**Estimated implement time:** ~5 min
|
||||
**Parallelizable with:** Task 1, Task 2, Task 3, Task 4, Task 7
|
||||
|
||||
**Files:**
|
||||
- Modify: `src/ZB.MOM.WW.MxGateway.Server/Dashboard/Components/Pages/AlarmsPage.razor`
|
||||
(in-process feed loop around `:199-230`, `_snapshotTruncated` at `:170`/`:401`)
|
||||
- Test: `src/ZB.MOM.WW.MxGateway.Tests/` — the AlarmsPage/dashboard alarm test class
|
||||
(find with `grep -rl "AlarmsPage" src/ZB.MOM.WW.MxGateway.Tests`); if no AlarmsPage
|
||||
render/behavior test exists, add coverage at the level the existing dashboard tests use
|
||||
- Modify: `docs/GatewayDashboardDesign.md` (truncation-banner description, if it says the
|
||||
banner is poll-driven)
|
||||
|
||||
**Problem.** The truncation banner (`_snapshotTruncated`, rendered at `:39`) updates only
|
||||
from the 3-second poll (`:401`), even though the page already holds an in-process
|
||||
subscription to the alarm feed (the loop at `:211-213` that feeds the provider-status
|
||||
badge). The feed now carries an edge-triggered `snapshot_status` frame
|
||||
(`AlarmFeedMessage.PayloadCase.SnapshotStatus`, shipped `fccf753`) — consume it so the
|
||||
banner flips on the edge instead of up to 3 s late.
|
||||
|
||||
**Spec:**
|
||||
- In the existing in-process feed loop, add a case for
|
||||
`AlarmFeedMessage.PayloadCase.SnapshotStatus`: set `_snapshotTruncated =
|
||||
message.SnapshotStatus.Truncated` and re-render (same invoke/StateHasChanged pattern the
|
||||
provider-status case uses).
|
||||
- Keep the poll's assignment at `:401` — the poll is the reconcile baseline and both
|
||||
sources derive from the same `GatewayAlarmMonitor` verdict, so they cannot disagree
|
||||
except transiently. Do not remove or restructure the poll.
|
||||
- Remember `StreamAsync` primes every subscriber with an unconditional `snapshot_status`
|
||||
baseline frame after `provider_status` — so on attach the page gets the current verdict
|
||||
push-side too. No extra priming logic needed in the page.
|
||||
- Do NOT touch `GatewayAlarmMonitor` or the proto — gateway emission is done and shipped.
|
||||
|
||||
**Steps:** failing test first (a `SnapshotStatus` frame delivered through the in-process
|
||||
subscription flips the banner state without a poll tick; a `false` frame clears it), then
|
||||
implement, then filtered dashboard/alarm tests green under the build lock, then commit:
|
||||
`feat(dashboard): alarms page consumes snapshot_status feed frame for the truncation banner`.
|
||||
|
||||
---
|
||||
|
||||
### Task 6: Server-0xx resolution audit — doc-only "Resolved" entries re-verified
|
||||
|
||||
**Classification:** standard
|
||||
**Estimated implement time:** ~5 min (audit) + fixes as found
|
||||
**Parallelizable with:** none (runs after Task 4 lands — both may touch `docs/Authentication.md`)
|
||||
|
||||
**Files:**
|
||||
- Modify: `code-reviews/Server/findings.md` (annotations only — do not rewrite history)
|
||||
- Modify: any file where a claimed correction is found absent (expected candidates:
|
||||
`CLAUDE.md`, `docs/*.md`, XML doc comments named in findings — report each)
|
||||
|
||||
**Problem.** Server-012 was recorded *Resolved 2026-05-18* claiming two scope-list
|
||||
corrections that were absent from the tree when `feat/followup-closeout` looked — a
|
||||
resolution that regressed or was never applied. Findings that read Resolved are never
|
||||
re-examined, so every *documentation/comment-only* resolution needs the same spot-check.
|
||||
|
||||
**Procedure:**
|
||||
1. Enumerate every `Server-0xx` entry in `code-reviews/Server/findings.md` whose
|
||||
Resolution describes documentation-only or comment-only changes (no test named, prose
|
||||
like "Pure documentation change" — at minimum Server-011, Server-012, Server-013/014
|
||||
remarks rewrites; sweep all entries, don't assume).
|
||||
2. For each, verify the specific claimed text exists in today's tree (grep the exact
|
||||
phrases/identifiers the resolution names).
|
||||
3. Where present: append one line to that finding's Resolution:
|
||||
`Re-verified present 2026-08-18 (feat/followups-tickets).`
|
||||
4. Where absent: re-apply the correction in the target file, and append:
|
||||
`Regressed or never applied; re-fixed 2026-08-18 in <file> (feat/followups-tickets).`
|
||||
(Server-012 itself was already re-fixed on the previous branch — annotate it as such,
|
||||
citing commits `a5f843c`/`f2a422b`, rather than re-fixing.)
|
||||
5. Report a table: finding id → verified/regressed → action.
|
||||
|
||||
**Commit:** `docs(reviews): re-verify doc-only Server-0xx resolutions; re-fix regressions`.
|
||||
|
||||
---
|
||||
|
||||
### Task 7: WorkerPipeSessionTests deterministic failure — investigate and fix (windev)
|
||||
|
||||
**Classification:** high-risk
|
||||
**Estimated implement time:** investigation timeboxed ~10 min; fix ≤5 min
|
||||
**Parallelizable with:** Task 1–5 (only windev user in wave 1)
|
||||
|
||||
**Files (starting points — investigation task, report everything touched):**
|
||||
- Test: `src/ZB.MOM.WW.MxGateway.Worker.Tests/Ipc/WorkerPipeSessionTests.cs`
|
||||
(`RunAsync_LongInFlightCommandThatKeepsPumping_DoesNotFaultAndDeliversReply`)
|
||||
- Suspect: `src/ZB.MOM.WW.MxGateway.Worker/` pipe-session / frame-protocol sources the
|
||||
test exercises (follow the test's references)
|
||||
|
||||
**Problem.** The test fails deterministically on windev, and reproduces on `main` —
|
||||
pre-existing, not introduced by any recent branch. Everything else in the worker suite
|
||||
passes (523/523 otherwise).
|
||||
|
||||
**Procedure (all building/testing on windev over ssh; edits in the Mac tree, pushed by
|
||||
the controller, pulled on the CI clone — coordinate via your report if you need a push):**
|
||||
1. Repro on the CI clone at this branch:
|
||||
`dotnet test src/ZB.MOM.WW.MxGateway.Worker.Tests/ZB.MOM.WW.MxGateway.Worker.Tests.csproj -p:Platform=x86 --filter "FullyQualifiedName~RunAsync_LongInFlightCommandThatKeepsPumping"`.
|
||||
Capture the full failure output (assertion text, timeout, stack).
|
||||
2. Read the test and the code under test. Classify: (a) test defect (bad timing
|
||||
assumption, races in the harness), (b) product defect in the pipe session under a
|
||||
long in-flight command, or (c) environment-specific (windev timing/load).
|
||||
**Timebox: if the cause is not isolated after ~10 minutes of investigation, stop and
|
||||
report your best hypothesis with evidence — do not churn.**
|
||||
3. Fix minimally per the classification. A product fix in the frame/pipe layer is
|
||||
high-risk territory: preserve the frame protocol (`docs/WorkerFrameProtocol.md`), the
|
||||
STA pumping rules, and MXAccess parity. A test fix must keep the scenario's intent —
|
||||
a long in-flight command that keeps pumping must not fault the session and must
|
||||
deliver its reply; don't weaken it into a sleep-and-hope.
|
||||
4. Verify: the fixed test passes 3 consecutive runs on windev; then the full worker suite
|
||||
(`-p:Platform=x86`) is green. If you touched product code, also build the full `slnx`
|
||||
on windev and run the gateway suite filtered to any shared-surface tests.
|
||||
5. Docs in the same commit if behavior/rules changed.
|
||||
|
||||
**Commit:** `fix(worker): <cause> — WorkerPipeSessionTests long-in-flight repro` (adjust
|
||||
`fix(worker-tests)` if the defect is in the test).
|
||||
|
||||
---
|
||||
|
||||
### Task 8: Ack-leg probe — bounded unblock attempt (windev rig)
|
||||
|
||||
**Classification:** standard
|
||||
**Estimated implement time:** timeboxed ~15 min of probing
|
||||
**Parallelizable with:** Task 6 (runs after Task 7 — serialize windev use)
|
||||
|
||||
**Files (starting points — investigation task):**
|
||||
- Modify: `docs/AlarmProbeFindings.md` (append a third-attempt section, whatever the outcome)
|
||||
- Reference (read-only): the probe harness locations named in that doc's earlier attempts;
|
||||
the mxaccess analysis project at `C:\Users\dohertj2\Desktop\mxaccess` (windev)
|
||||
|
||||
**Problem.** The acknowledge leg remains unobserved: every wnwrap ack surface is
|
||||
accepted-but-inert (`rc=0`, state stays `UNACK_ALM`), and `.Acked` is write-rejected
|
||||
(OperationalError 1007). Two recorded unblock paths remain
|
||||
(`docs/AlarmProbeFindings.md`, "Remaining unblock paths for the acknowledge leg").
|
||||
|
||||
**Procedure — attempt path 2 first (it is inspectable), path 1 only if non-interactive:**
|
||||
1. **Path 2 — ack-security configuration:** inspect whether the rig's galaxy/`alarmmgr`
|
||||
is configured with an alarm-acknowledgement security requirement the wnwrap consumer
|
||||
(operator *name* string, no authenticated identity) cannot meet. Look in galaxy
|
||||
configuration (the `ZB` SQL Galaxy Repository — read-only queries only), area/object
|
||||
security settings for the `TestMachine_00x` objects, and any alarm-security docs in
|
||||
the mxaccess analysis project. **Read-only: do not change galaxy security config.**
|
||||
2. **Path 1 — platform-side ack:** only if a *scriptable, non-interactive* path exists on
|
||||
the rig as-installed (e.g. an existing harness or automation entry point). Do NOT
|
||||
install software, do NOT drive GUI automation, do NOT change rig state beyond the
|
||||
established raise/clear pattern on `TestMachine_001.TestAlarm001`. If only interactive
|
||||
IDE/InTouch paths exist, record that and stop.
|
||||
3. Whatever the outcome, append the third-attempt section: what was inspected, evidence,
|
||||
and the leg's final status (observed / unavailable-by-configuration / still assumed
|
||||
with the paths requiring a human). If the ack was actually observed, record whether
|
||||
`STATE` reached `ACK_ALM` and whether the GUID survived — that answers the original
|
||||
question and should update the findings table at the top of the doc.
|
||||
4. **Stop condition:** at ~15 minutes of probing without a decisive result, write up what
|
||||
was learned and conclude "still assumed" — the doc itself notes this is a
|
||||
documentation gap, not a correctness one.
|
||||
|
||||
**Commit:** `docs(probe): ack-leg third attempt — <outcome>`.
|
||||
|
||||
---
|
||||
|
||||
### Task 9: Windev toolchain pin + full verification
|
||||
|
||||
**Classification:** verification (no review chain)
|
||||
**Estimated implement time:** ~15 min wall (mostly build/test wait)
|
||||
**Parallelizable with:** none (after all code tasks land and are pushed)
|
||||
|
||||
**Files:** none in-repo except possibly `docs/ToolchainLinks.md` (update the windev
|
||||
`protoc-gen-go-grpc` entry if it records 1.6.1).
|
||||
|
||||
**Procedure (all over `ssh windev`, CI clone `C:\build\mxaccessgw-ci` at this branch tip):**
|
||||
1. `go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.6.2` — then
|
||||
`protoc-gen-go-grpc --version` must report 1.6.2. Update `docs/ToolchainLinks.md` if
|
||||
it pins the old version (commit from the Mac tree).
|
||||
2. Full `slnx` build — 0 warnings / 0 errors (clear Contracts obj/bin on CS2001/CS0016).
|
||||
3. Worker tests `-p:Platform=x86` — expect the Task 7 outcome (fully green if fixed;
|
||||
otherwise the documented known-failure only).
|
||||
4. Gateway tests — full suite; rerun filtered on load flakes before believing a failure.
|
||||
5. `powershell scripts/check-codegen.ps1` — **all 4 checks**, proving Task 1 on the
|
||||
platform that had the bug.
|
||||
6. `gradle --version` + `gradle :zb-mom-ww-mxgateway-client:checkGeneratedClean` from
|
||||
`clients\java` if Gradle is installed there — record version and result either way.
|
||||
7. Live MXAccess smoke: `MXGATEWAY_RUN_LIVE_MXACCESS_TESTS=1`, filter
|
||||
`WorkerLiveMxAccessSmokeTests` — 8/8.
|
||||
8. Report every result verbatim (counts, not "green").
|
||||
|
||||
---
|
||||
|
||||
### Task 10: Bookkeeping — close the follow-ups record
|
||||
|
||||
**Classification:** trivial
|
||||
**Estimated implement time:** ~3 min
|
||||
**Parallelizable with:** none (last)
|
||||
|
||||
**Files:**
|
||||
- Modify: `docs/plans/2026-08-17-followup-closeout.md` (follow-ups block `:483-507`):
|
||||
annotate each bullet closed with this branch's closing commit (or precisely narrowed,
|
||||
e.g. ack leg if still assumed)
|
||||
- Modify: `docs/plans/2026-08-18-followups-and-tickets.md` (this file): append as-built
|
||||
notes — per-task commits, review outcomes, verification results, anything learned
|
||||
- Modify: `docs/plans/2026-08-18-followups-and-tickets.md.tasks.json`: final statuses
|
||||
|
||||
**Commit:** `chore(plan): followups-and-tickets as-built record; prior follow-ups closed`.
|
||||
|
||||
---
|
||||
|
||||
## Execution notes for the controller
|
||||
|
||||
- **Model/review chains** (subagent-driven-development skill): Tasks 1–4 small → Sonnet
|
||||
implementer + Haiku code review (diffs <100 LOC). Task 5 standard → Opus implementer,
|
||||
spec (Haiku) ∥ code (Sonnet). Task 6 standard → Opus implementer, spec ∥ code. Task 7
|
||||
high-risk → Opus implementer, serial spec (Haiku) → code (Sonnet). Task 8 standard →
|
||||
Opus implementer, spec ∥ code. Task 9 verification → Opus, no review. Task 10 trivial →
|
||||
Sonnet, no review.
|
||||
- **Waves:** Wave 1 = Tasks 1, 2, 3, 4, 5, 7 (disjoint files; Task 7 alone on windev).
|
||||
Wave 2 = Task 6 (after 4) and Task 8 (after 7). Wave 3 = push branch, Task 9.
|
||||
Wave 4 = Task 10, final integration review, then hold for the user's merge decision.
|
||||
- **Push cadence:** controller pushes the branch before any windev task needs its code
|
||||
there (Task 7 investigates on-branch; Tasks 8–9 need the wave-1/2 tips).
|
||||
Reference in New Issue
Block a user