Founder caught 5 canvas defects on prov #73 (8cd1ff1a80430dc5):
1. ✅ depth=1 shows 2 bubbles (provisioner + bootstrap-kit) — confirmed
correct architecture per composer.
2. ✅ Expanding bootstrap-kit shows 3 region sub-groups — confirmed.
3. 🐛 All 135 install-* nodes had ZERO inter-HR dep edges. Snapshot
showed only 5 finish-to-start rels (tofu chain + bootstrap-kit
sequence). install-cert-manager → install-cilium etc. all missing.
4. 🐛 Canvas only emitted 2 phase groups (provisioner + bootstrap-kit).
Missing cutover/handover/apps despite being part of the canonical
5-phase lifecycle.
5. 🐛 /jobs/install-hel1-2/newapi returned 404 because TanStack Router
splits "/" in the $jobId param.
## Fixes
### Fix 3a: mergeJob preserves prev.DependsOn when next is empty
store.go:283 — `if len(next.DependsOn)==0 && len(prev.DependsOn)>0`
keeps prior list. Without this, every OnHelmReleaseEvent (which
hardcodes `DependsOn: []string{}` at line 508 because it doesn't
re-look up HR.spec.dependsOn per event) CLOBBERED the seeded deps.
Confirmed in store: 135/135 install Jobs had `dependsOn: []`
despite SeedJobsFromInformerList running with proper deps. Founder
reported this same flat-leaves bug 4 sessions in a row.
### Fix 3b: secondary watchers get region-aware seeder hook
New `attachSecondaryBridgeSeederHook` + `snapshotsToSeedsForRegion`
wire the seed path for secondary helmwatch.Watchers. Without this,
secondary install-* Jobs were only ever created by per-event
OnHelmReleaseEvent (DependsOn=[]) so the canvas dep graph was
permanently flat under secondary region groups regardless of fix
3a.
### Fix 3c: composer Layer-2 reads secondary watchers' HR.spec.dependsOn
flow_snapshot_local.go now also walks dep.secondaryWatchers and
populates hrDeps with region-prefixed keys + region-prefixed values.
After fix 3a+3b the stored Job.DependsOn is the authoritative source
(Layer 1) — this Layer-2 enrichment is the safety net for hot-
shipped charts that bypass the seed path.
### Fix 4: cutover/handover/apps phase groups
types.go — add GroupCutover/Handover/Apps constants + Display.
flow_snapshot_local.go — add phaseForChart() classifier (currently
maps self-sovereign-cutover → cutover), reparent install jobs to
the correct phase sub-group, synthesise per-region sub-groups for
each phase, emit top-level phase groups, and chain them with
finish-to-start: provisioner → bootstrap-kit → cutover → handover
→ apps.
### Fix 5: JobName separator `/` → `:` (canonical per memory rule)
phase1_watch.go:457 emits ev.Component = region + ":" + chart.
jobs_backfill.go + flow_snapshot_local.go updated to detect ":"
instead of "/". useJobLinkBuilder's encodeURIComponent already
handles ":". /jobs/install-hel1-2:newapi now matches the TanStack
Router $jobId route.
Co-authored-by: e3mrah <1234567+e3mrah@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>