docs(localdb): parallel-wave execution config, Opus implementers

Claude-Session: https://claude.ai/code/session_01BL2Vu1ESDQ9SCN4gVKkdts
This commit is contained in:
Joseph Doherty
2026-07-19 02:00:05 -04:00
parent ed9644fa3d
commit b0d4e2edac
2 changed files with 35 additions and 13 deletions
@@ -8,6 +8,22 @@
**Tech Stack:** .NET 10, `ZB.MOM.WW.LocalDb` 0.1.0 + `.Replication` + `.Contracts` (Gitea feed), Microsoft.Data.Sqlite, gRPC on the existing site Kestrel (8083), xunit. **Tech Stack:** .NET 10, `ZB.MOM.WW.LocalDb` 0.1.0 + `.Replication` + `.Contracts` (Gitea feed), Microsoft.Data.Sqlite, gRPC on the existing site Kestrel (8083), xunit.
**Execution configuration (saved for later execution):**
- Resume with `/superpowers-extended-cc:executing-plans docs/plans/2026-07-19-localdb-adoption-phase1.md` — the co-located `.tasks.json` carries the dependency graph.
- **Model: Opus for every implement subagent** (`model: "opus"` on Agent dispatch). Review chain per task classification (high-risk tasks get serial spec + code review, small tasks a single Sonnet/Haiku code-reviewer pass).
- **Dispatch tasks in waves — every task in a wave runs concurrently** (file sets are disjoint; verified below). Parallel implementers editing one repo MUST use worktree isolation (`Agent isolation: "worktree"`) — concurrent git in a shared worktree races destructively.
| Wave | Tasks (concurrent) |
|---|---|
| 1 | Task 1 (packages) |
| 2 | Task 2 (schema helpers) |
| 3 | Task 3 (composition root) |
| 4 | Task 4 (tracking store) ∥ Task 5 (event logger) ∥ Task 7 (replication wiring) |
| 5 | Task 6 (migrator) ∥ Task 8 (auth interceptor) ∥ Task 9 (health signal) |
| 6 | Task 10 (convergence test) ∥ Task 11 (rig config) |
| 7 | Task 12 (live gate — serial, on the real rig) |
| 8 | Task 13 (docs) ∥ Task 14 (Phase 2 planning) |
**Hard constraints learned from the code (do not rediscover):** **Hard constraints learned from the code (do not rediscover):**
- `AddZbLocalDb(config, onReady)` is one-DB-per-process, first-registration-wins. Table DDL must run inside `onReady` **before** `RegisterReplicated`; rows inserted before registration are never captured/snapshotted. - `AddZbLocalDb(config, onReady)` is one-DB-per-process, first-registration-wins. Table DDL must run inside `onReady` **before** `RegisterReplicated`; rows inserted before registration are never captured/snapshotted.
- `site_events.id` must change from `INTEGER AUTOINCREMENT` to TEXT (GUID) — two nodes minting the same autoincrement id silently overwrite each other under LWW. - `site_events.id` must change from `INTEGER AUTOINCREMENT` to TEXT (GUID) — two nodes minting the same autoincrement id silently overwrite each other under LWW.
@@ -161,7 +177,7 @@ services.AddZbLocalDb(config, SiteLocalDbSetup.OnReady);
**Classification:** standard **Classification:** standard
**Estimated implement time:** ~4 min **Estimated implement time:** ~4 min
**Parallelizable with:** Task 5 **Parallelizable with:** Task 5, Task 7
**Files:** **Files:**
- Modify: `src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Tracking/OperationTrackingStore.cs` - Modify: `src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Tracking/OperationTrackingStore.cs`
@@ -182,7 +198,7 @@ services.AddZbLocalDb(config, SiteLocalDbSetup.OnReady);
**Classification:** standard **Classification:** standard
**Estimated implement time:** ~5 min **Estimated implement time:** ~5 min
**Parallelizable with:** Task 4 **Parallelizable with:** Task 4, Task 7
**Files:** **Files:**
- Modify: `src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/SiteEventLogger.cs` - Modify: `src/ZB.MOM.WW.ScadaBridge.SiteEventLogging/SiteEventLogger.cs`
@@ -204,7 +220,7 @@ services.AddZbLocalDb(config, SiteLocalDbSetup.OnReady);
**Classification:** high-risk (data migration) **Classification:** high-risk (data migration)
**Estimated implement time:** ~5 min **Estimated implement time:** ~5 min
**Parallelizable with:** none (needs Tasks 3-5) **Parallelizable with:** Task 8, Task 9 (needs Tasks 4-5 done)
**Files:** **Files:**
- Create: `src/ZB.MOM.WW.ScadaBridge.Host/SiteLocalDbLegacyMigrator.cs` - Create: `src/ZB.MOM.WW.ScadaBridge.Host/SiteLocalDbLegacyMigrator.cs`
@@ -227,7 +243,7 @@ Run the migrator tests + full Host.Tests; commit.
**Classification:** high-risk (wiring + endpoint exposure) **Classification:** high-risk (wiring + endpoint exposure)
**Estimated implement time:** ~4 min **Estimated implement time:** ~4 min
**Parallelizable with:** none **Parallelizable with:** Task 4, Task 5 (needs Task 3 only; touches Program.cs, disjoint from the store files)
**Files:** **Files:**
- Modify: `src/ZB.MOM.WW.ScadaBridge.Host/Program.cs` site block (`:515-536`) - Modify: `src/ZB.MOM.WW.ScadaBridge.Host/Program.cs` site block (`:515-536`)
@@ -245,7 +261,7 @@ Run the migrator tests + full Host.Tests; commit.
**Classification:** high-risk (security) **Classification:** high-risk (security)
**Estimated implement time:** ~5 min **Estimated implement time:** ~5 min
**Parallelizable with:** Task 9 **Parallelizable with:** Task 6, Task 9
**Files:** **Files:**
- Create: `src/ZB.MOM.WW.ScadaBridge.Host/LocalDbSyncAuthInterceptor.cs` - Create: `src/ZB.MOM.WW.ScadaBridge.Host/LocalDbSyncAuthInterceptor.cs`
@@ -279,7 +295,7 @@ Tests (TDD, write first): non-sync path passes with no key; sync path with no co
**Classification:** small **Classification:** small
**Estimated implement time:** ~3 min **Estimated implement time:** ~3 min
**Parallelizable with:** Task 8 **Parallelizable with:** Task 6, Task 8
**Files:** **Files:**
- Modify: `src/ZB.MOM.WW.ScadaBridge.Host/SiteServiceRegistration.cs` (health wiring — follow the `AddSiteEventLogHealthMetricsBridge` precedent at :76) - Modify: `src/ZB.MOM.WW.ScadaBridge.Host/SiteServiceRegistration.cs` (health wiring — follow the `AddSiteEventLogHealthMetricsBridge` precedent at :76)
@@ -293,7 +309,7 @@ Bridge `ISyncStatus` (`Connected`, `OplogBacklog` — **nullable**, null must su
**Classification:** high-risk **Classification:** high-risk
**Estimated implement time:** ~5 min **Estimated implement time:** ~5 min
**Parallelizable with:** none **Parallelizable with:** Task 11
**Files:** **Files:**
- Create: `tests/ZB.MOM.WW.ScadaBridge.IntegrationTests/LocalDbSitePairConvergenceTests.cs` - Create: `tests/ZB.MOM.WW.ScadaBridge.IntegrationTests/LocalDbSitePairConvergenceTests.cs`
@@ -312,7 +328,7 @@ Offline, no docker. Run: `dotnet test tests/ZB.MOM.WW.ScadaBridge.IntegrationTes
**Classification:** small **Classification:** small
**Estimated implement time:** ~4 min **Estimated implement time:** ~4 min
**Parallelizable with:** none **Parallelizable with:** Task 10
**Files:** **Files:**
- Modify: `docker/site-a-node-a/appsettings.Site.json` — add `"Replication": { "PeerAddress": "http://<site-a-node-b container name>:8083", "ApiKey": "<dev key>" }` under `LocalDb` (take exact container hostname from `docker/docker-compose.yml`) - Modify: `docker/site-a-node-a/appsettings.Site.json` — add `"Replication": { "PeerAddress": "http://<site-a-node-b container name>:8083", "ApiKey": "<dev key>" }` under `LocalDb` (take exact container hostname from `docker/docker-compose.yml`)
@@ -345,7 +361,7 @@ Evidence (commands + output) goes in the PR/commit message. Any failure here loo
**Classification:** trivial **Classification:** trivial
**Estimated implement time:** ~4 min **Estimated implement time:** ~4 min
**Parallelizable with:** none **Parallelizable with:** Task 14
- ScadaBridge `CLAUDE.md`: consolidated-DB note, config keys, replication flag posture, deleted config keys (old tracking/eventlog paths) marked migration-only. - ScadaBridge `CLAUDE.md`: consolidated-DB note, config keys, replication flag posture, deleted config keys (old tracking/eventlog paths) marked migration-only.
- scadaproj `CLAUDE.md` LocalDb component row: "no app adoption yet" → ScadaBridge Phase 1 adopted (state exactly what is and is not live, per the component-status-honesty convention). - scadaproj `CLAUDE.md` LocalDb component row: "no app adoption yet" → ScadaBridge Phase 1 adopted (state exactly what is and is not live, per the component-status-honesty convention).
@@ -1,5 +1,11 @@
{ {
"planPath": "docs/plans/2026-07-19-localdb-adoption-phase1.md", "planPath": "docs/plans/2026-07-19-localdb-adoption-phase1.md",
"execution": {
"mode": "parallel-waves",
"implementerModel": "opus",
"isolation": "worktree",
"note": "Dispatch every unblocked task concurrently (waves in the plan header). Parallel implementers MUST use worktree isolation - concurrent git in one worktree races destructively."
},
"tasks": [ "tasks": [
{"id": 1, "subject": "Task 1: Add LocalDb packages to the build", "status": "pending"}, {"id": 1, "subject": "Task 1: Add LocalDb packages to the build", "status": "pending"},
{"id": 2, "subject": "Task 2: Shared schema helpers (tracking + events, GUID PK)", "status": "pending", "blockedBy": [1]}, {"id": 2, "subject": "Task 2: Shared schema helpers (tracking + events, GUID PK)", "status": "pending", "blockedBy": [1]},
@@ -7,12 +13,12 @@
{"id": 4, "subject": "Task 4: Rewire OperationTrackingStore onto ILocalDb connections", "status": "pending", "blockedBy": [3]}, {"id": 4, "subject": "Task 4: Rewire OperationTrackingStore onto ILocalDb connections", "status": "pending", "blockedBy": [3]},
{"id": 5, "subject": "Task 5: Rewire SiteEventLogger + EventLogQueryService (GUID ids)", "status": "pending", "blockedBy": [3]}, {"id": 5, "subject": "Task 5: Rewire SiteEventLogger + EventLogQueryService (GUID ids)", "status": "pending", "blockedBy": [3]},
{"id": 6, "subject": "Task 6: One-time legacy data migrator", "status": "pending", "blockedBy": [4, 5]}, {"id": 6, "subject": "Task 6: One-time legacy data migrator", "status": "pending", "blockedBy": [4, 5]},
{"id": 7, "subject": "Task 7: Replication registration + sync endpoint (default OFF)", "status": "pending", "blockedBy": [6]}, {"id": 7, "subject": "Task 7: Replication registration + sync endpoint (default OFF)", "status": "pending", "blockedBy": [3]},
{"id": 8, "subject": "Task 8: Bearer auth interceptor for the sync endpoint", "status": "pending", "blockedBy": [7]}, {"id": 8, "subject": "Task 8: Bearer auth interceptor for the sync endpoint", "status": "pending", "blockedBy": [7]},
{"id": 9, "subject": "Task 9: Surface ISyncStatus as site health signal", "status": "pending", "blockedBy": [7]}, {"id": 9, "subject": "Task 9: Surface ISyncStatus as site health signal", "status": "pending", "blockedBy": [7]},
{"id": 10, "subject": "Task 10: Two-node in-process convergence test", "status": "pending", "blockedBy": [8]}, {"id": 10, "subject": "Task 10: Two-node in-process convergence test", "status": "pending", "blockedBy": [6, 8]},
{"id": 11, "subject": "Task 11: Docker rig enablement (site-a pair)", "status": "pending", "blockedBy": [10]}, {"id": 11, "subject": "Task 11: Docker rig enablement (site-a pair)", "status": "pending", "blockedBy": [8]},
{"id": 12, "subject": "Task 12: Live gate on the docker rig", "status": "pending", "blockedBy": [11]}, {"id": 12, "subject": "Task 12: Live gate on the docker rig", "status": "pending", "blockedBy": [9, 10, 11]},
{"id": 13, "subject": "Task 13: Documentation truth pass", "status": "pending", "blockedBy": [12]}, {"id": 13, "subject": "Task 13: Documentation truth pass", "status": "pending", "blockedBy": [12]},
{"id": 14, "subject": "Task 14: Phase 2 gate - plan the bespoke-replicator migration", "status": "pending", "blockedBy": [12]} {"id": 14, "subject": "Task 14: Phase 2 gate - plan the bespoke-replicator migration", "status": "pending", "blockedBy": [12]}
], ],