diff --git a/family/how-to/wireguard-vpn.md b/family/how-to/wireguard-vpn.md index 9fef50a6..35088a19 100644 --- a/family/how-to/wireguard-vpn.md +++ b/family/how-to/wireguard-vpn.md @@ -42,10 +42,8 @@ Eagle (10.99.0.2) ←→ wg0 VPS (10.99.0.1) ←→ wg1 VPS (10.99.1.1) ←→ K ## Auto-connect на Eagle `/usr/local/bin/wg-auto.sh` — следит за SSID через `WatchPaths` на `/Library/Preferences/SystemConfiguration/`: -- SSID == `ASUS5` → `wg-quick down` (дома, Kraken в локалке... но сейчас Kraken не дома, поэтому VPN всегда нужен) -- SSID != `ASUS5` → `wg-quick up` - -> ⚠️ Пока Kraken не дома (не на ASUS5) — туннель нужен всегда, даже когда Eagle на ASUS5. Скрипт нужно будет пересмотреть если Kraken вернётся домой. +- SSID == `ASUS5` → `wg-quick down` (дома, Kraken в локалке, туннель не нужен) +- SSID != `ASUS5` → `wg-quick up` (вне дома, TM через VPN) --- diff --git a/family/projects/media-toolbox-kraken.md b/family/projects/media-toolbox-kraken.md index 265b5bbd..3092a5bf 100644 --- a/family/projects/media-toolbox-kraken.md +++ b/family/projects/media-toolbox-kraken.md @@ -42,74 +42,94 @@ media-pipeline (~/Developer/media_files_db, ветка kraken-agent) --- -## Текущий статус (2026-05-14) +## Текущий статус (2026-05-14, сессия 5) -### Sync результаты (последний прогон) +### Sync результаты | Категория | Папок | NFO | Статус | |-----------|-------|-----|--------| | movies | 127 | 127 | ✅ 100% | -| series | 45 | 238 (эпизоды) | ✅ хорошо | -| cartoons | 126 | ~30 | ⚠️ советские не резолвятся | -| documentaries | 35 | ~5 | ⚠️ | -| **Итого** | **317 regions** | **222 resolved** | **70%** | +| series | 45 | ✅ | ✅ | +| cartoons | 126 | ~119 | ✅ почти всё (8 через resolve-manual) | +| documentaries | 35 | ~27 | ⚠️ 8 остались (см. ниже) | ### Что работает - ✅ Docker образ `media-pipeline:kraken` задеплоен (ветка `kraken-agent`) -- ✅ `sync` корректно вызывается (был баг: двойное `media-pipeline media-pipeline`) -- ✅ Кеш API-ответов: теперь `/config/cache` (persistent), 30-дневный TTL - ✅ Фильмы: 127/127 NFO -- ✅ Сериалы: хорошо (Black Mirror, Queens Gambit, Good Omens и т.д.) +- ✅ Сериалы: все resolved (Black Mirror, Ну погоди!, и др. — через resolve-manual) +- ✅ Кеш API-ответов: `/config/cache`, 30-дневный TTL - ✅ Transmission download-complete hook установлен -- ✅ `resolve-manual` работает (форс-резолв по TMDb/KP ID) +- ✅ `resolve-manual` работает для movie/series/single-file -### Что не работает / в работе -- ⚠️ **Советские мультики** — `bremenskie.muzykanty`, `budilnik`, `ёжик в тумане` и ~50 других не резолвятся автоматически. Legacy Go-код справлялся — нужно разобраться в чём разница -- ⚠️ **Часть Disney/Pixar** в batch-режиме не проходят arbiter (Encanto, Lightyear, Inside Out) — одиночно через `resolve-manual` работают -- 🔲 Jellyfin библиотеки — не настроены -- 🔲 torrent-fix для 7 старых торрентов с путями `D:/Movies` -- 🔲 Hermes cron на Кракене +### Открытые задачи + +#### 1. 🔴 Web search path для документалок и специфичного контента +**Принятое решение:** ничто из библиотеки не должно оставаться в unresolved. Если TMDb/KP не находят — должен срабатывать web search (IMDb HTML scrape, Tier 4). Сейчас `webSearch.enabled=true` в config.json, но 8 документалок всё равно в unresolved. + +**8 оставшихся:** +- `/media/cartoons/25е - первый день` +- `/media/documentaries/bbc. the real jungle book bear 2012` +- `/media/documentaries/bbc. секреты собак` +- `/media/documentaries/penguin meet the family (2020)` +- `/media/documentaries/бегемоты - жизнь в воде` +- `/media/documentaries/гиганты моря 2011` +- `/media/documentaries/таинственная жизнь собак (hdtvrip 720p, 2013)` +- `/media/documentaries/тайная жизнь собак (2016г)` + +**Что нужно сделать:** +- Запустить sync с `--debug` или отследить почему web search не помогает для этих item'ов +- IMDbSearchProvider (Tier 4) должен находить BBC документалки по названию +- Если IMDb тоже не находит — включить AIAgent (Tier 5) с OpenAI key, или добавить fallback: если все тиры вернули 0 кандидатов и папка содержит хотя бы один видеофайл → запускать web search по Google/IMDb с более агрессивными вариантами запроса +- Цель: `unresolved.json` после sync = пустой + +#### 2. 🟡 torrent-fix для 7 старых торрентов с путями `D:/Movies` +- Transmission хранит old paths `D:/Movies/...` — нужен `torrent-fix` subcommand + +#### 3. 🟡 Jellyfin библиотеки +- Настроить библиотеки в Jellyfin (http://192.168.1.14:8096) +- NFO файлы готовы, Jellyfin должен их подхватить + +#### 4. 🟢 Hermes cron на Кракене +- Периодический запуск sync (новые загрузки через Transmission) + +--- + +## Принятые решения (архитектурные) + +| Решение | Описание | +|---------|----------| +| **Unresolved = 0** | Цель — ничто из библиотеки не должно оставаться в unresolved после sync. Web search (Tier 4) и AI agent (Tier 5) — последние резервы перед тем как считать item нераспознанным | +| **Web search enabled** | `providers.webSearch.enabled=true` в config.json. IMDb scrape как Tier 4 для всего, что не нашли TMDb/KP | +| **Документалки приоритет KP** | BBC/Discovery документалки плохо индексированы в TMDb. KP часто знает их под русскими названиями. Стратегия: сначала KP с русским названием из папки, потом IMDb | +| **resolve-manual** | Только для экстренных случаев, не как регулярный процесс | +| **Single-file NFO** | Для `.mkv`/`.m4v` файлов NFO создаётся рядом (`film.nfo`), не внутри | --- ## Исправленные баги ### Баг 1: Двойной вызов binary (КРИТИЧЕСКИЙ) -**Проблема:** `docker run ... media-pipeline:kraken media-pipeline sync` — бинарь получал `media-pipeline` как первый аргумент = неизвестный subcommand → general help. Все прошлые dry-run не работали. -**Фикс:** `ENTRYPOINT ["media-pipeline"]` → правильный вызов `docker run ... sync ...` +`docker run ... media-pipeline:kraken media-pipeline sync` → бинарь получал `media-pipeline` как аргумент. +**Фикс:** `ENTRYPOINT ["media-pipeline"]` ### Баг 2: TitleSimilarity — симметричный Jaccard -**Проблема:** `encanto_2021_bdrip_by_dalemake` vs `Encanto`: `lengthRatio = 1/5 = 0.2` → confidence ≈ 0.05 → rejected. Noise-токены (bdrip, 1080p, год) убивали матч. -**Фикс:** Asymmetric scoring — когда query длиннее candidate, переключаемся на candidate-coverage Jaccard (покрытие кандидата запросом). `lengthRatio = 1.0` когда query длиннее. -**Коммит:** `2704ce3` +`encanto_2021_bdrip_by_dalemake` vs `Encanto`: lengthRatio=0.2 → rejected. +**Фикс:** Asymmetric scoring — candidate-coverage Jaccard когда query длиннее. Коммит `2704ce3` -### Баг 3: ProviderSearchStrategy.maxCallsPerRun = 8 -**Проблема:** 8 API-вызовов на провайдер → 192 из 200 items никогда не искались. +### Баг 3: maxCallsPerRun = 8 +8 API-вызовов → 192/200 items никогда не искались. **Фикс:** 8 → 500. Коммит `2704ce3` ### Баг 4: Series-гипотезы для одиночных файлов -**Проблема:** `NumberedEpisodesHypothesisStrategy` и `NamedEpisodesHypothesisStrategy` генерировали series-гипотезы для одиночных `.avi`/`.mkv` без S/E маркеров → TMDb искал по `/search/tv` вместо `/search/movie`. +Одиночные `.avi`/`.mkv` без S/E маркеров получали series-гипотезу → TMDb искал по `/search/tv`. **Фикс:** `videos.count < 2 && !hasAnyEpisodeMarkers → return nil`. Коммит `17c2ddc` ### Баг 5: HTTP кеш не персистился -**Проблема:** `cacheDirectory = /usr/local/bin/cache` внутри контейнера. `docker run --rm` → кеш удалялся при каждом запуске → тысячи дублирующих API запросов. -**Фикс:** Autodetect `/config` mount → `/config/cache` (persistent volume). Коммит `5a1053c` +`cacheDirectory = /usr/local/bin/cache` — удалялся при `docker run --rm`. +**Фикс:** Autodetect `/config` mount → `/config/cache`. Коммит `5a1053c` ---- - -## Следующий шаг: советские мультики - -**Задача:** понять почему `bremenskie.muzykanty`, `budilnik 1984`, `ёжик в тумане` и ~50 других советских мультиков не резолвятся, хотя легаси Go-код справлялся. - -**Гипотезы:** -1. Транслитерация → KP не ищет по Latin `bremenskie` → нужна Cyrillic варианты в query -2. NameTokenization не генерирует качественную обратную транслит для советских названий -3. KP API возвращает результаты, но TitleSimilarity не матчит (разные скрипты) -4. TMDb `dual` search по `bremenskie muzykanty` → нет результатов → нужен только KP - -**Что делать:** -- Проверить что именно возвращает KP для `bremenskie muzykanty` -- Проверить что variant'ы генерирует NameTokenization для этих файлов -- Если проблема в transliteration accuracy — починить в TitleSimilarity (cross-script fuzzy match) +### Баг 6: resolve-manual NFO path для single-файлов +`resolve-manual` писал NFO внутрь файла вместо рядом. +**Фикс:** Detect `isDirectory`, для файлов → `deletingPathExtension().appendingPathExtension("nfo")`. Коммит `c0fdc59` --- @@ -119,7 +139,7 @@ media-pipeline (~/Developer/media_files_db, ветка kraken-agent) /srv/dev-disk-by-uuid-49e8f586-3839-4c5d-a1e1-58bfc3579ade/docker/media-pipeline/ ├── config.json ← TMDb/KP ключи, Transmission RPC, directories ├── unresolved.json ← реестр нераспознанных (создаётся автоматически) -├── cache/ ← HTTP кеш 30 дней (после фикса) +├── cache/ ← HTTP кеш 30 дней └── on-download-complete.sh ``` @@ -152,6 +172,7 @@ docker run --rm ... media-pipeline:kraken \ | Transmission | http://192.168.1.14:9091 | | Исходники | `~/Developer/media_files_db/`, ветка `kraken-agent` | | Docker образ | `media-pipeline:kraken` (arm64, Colima 24GB) | +| kraken-ssh | `ssh kraken-ssh` → 10.99.1.2:22 через WireGuard (обновлено 2026-05-14) | --- @@ -160,4 +181,5 @@ docker run --rm ... media-pipeline:kraken \ - **2026-05-13 сессия 1:** HTPC разбужен, rsync запущен (~1.3TB), торрент-база импортирована (128 торрентов) - **2026-05-13 сессия 2:** Docker build arm64, deploy на Кракен, first sync - **2026-05-13 сессия 3:** `kraken-agent` ветка: UnresolvedStore, resolve-manual, agent, torrent-fix subcommands -- **2026-05-14 сессия 4:** Найдены и исправлены 5 системных багов (см. выше). Sync: 222/317 resolved. Кеш починен. +- **2026-05-14 сессия 4:** 5 системных багов исправлены. Sync: 222/317 resolved (70%). +- **2026-05-14 сессия 5:** resolve-manual для 13 items (movies/cartoons/series/documentaries). unresolved: 24 → 8. Исправлен баг NFO path для single-файлов. kraken-ssh переключён на WireGuard. diff --git a/work/wiki/apple-browsers/chat-path-onboarding-tracker-blocking.md b/work/wiki/apple-browsers/chat-path-onboarding-tracker-blocking.md index 393d7aff..f7caff31 100644 --- a/work/wiki/apple-browsers/chat-path-onboarding-tracker-blocking.md +++ b/work/wiki/apple-browsers/chat-path-onboarding-tracker-blocking.md @@ -1,83 +1,229 @@ # iOS: Chat-Path Onboarding — Tracker Blocking Demo -> **Asana:** [Ship Review task](https://app.asana.com/1/137249556945/task/1214147157456478) +> **Asana:** [Ship Review task 1214147157456478](https://app.asana.com/1/137249556945/task/1214147157456478) > **Branch stack:** `demo-tracker-blocking-onboarding` → `ui-polish` → `chat-path-dialog-polish` → `sr-feedback` → `uti-flow` > **Due:** 2026-05-15 +--- + ## PR Stack -| PR | Branch | Status | +| PR | Branch | Base | Review status | +|---|---|---|---| +| [#4544](https://github.com/duckduckgo/apple-browsers/pull/4544) | `demo-tracker-blocking-onboarding` | `main` | Open — review required (Alessandro + Rachel left comments) | +| [#4591](https://github.com/duckduckgo/apple-browsers/pull/4591) | `demo-tracker-blocking-onboarding-ui-polish` | #4544 | Approved | +| [#4664](https://github.com/duckduckgo/apple-browsers/pull/4664) | `demo-tracker-blocking-onboarding-chat-path-dialog-polish` | #4591 | Approved | +| [#4855](https://github.com/duckduckgo/apple-browsers/pull/4855) | `demo-tracker-blocking-onboarding-sr-feedback` | #4664 | Open — no review yet. Has uncommitted local changes (see below). | +| [#4668](https://github.com/duckduckgo/apple-browsers/pull/4668) | `demo-tracker-blocking-onboarding-uti-flow` | ? | Open — no review yet. Has open Bugbot + reviewer comments (see below). | + +--- + +## Uncommitted Local Changes — PR #4855 branch (`sr-feedback`) + +All of the following are in the working tree but **NOT committed or pushed**. They must be committed before #4855 can be reviewed or merged. + +### 1. `NewTabPageViewController.swift` — setBarsHidden + delegate pattern + loading guard + +**What changed:** +- Replaced `(parent as? MainViewController)?.setChatPathVisitSiteControlsLocked(true/false)` + `chromeDelegate?.setNavigationBarHidden(true/false)` with a single `chromeDelegate?.setBarsHidden(true/false, animated: false, customAnimationDuration: nil)` call. +- Removed all `(parent as? MainViewController)?` casts from `NewTabPageViewController`. +- Loading guard (`guard ... isLoading != true else { return }`) was a standalone guard that would abort dialog presentation entirely, leaving an orphaned `hostingController` reference. Folded into the outer `if` condition using the new delegate method instead. +- `dismiss()` now calls `setBarsHidden(false)` when `didHideBarsForChatPathVisitSiteDialog` is true. + +**Why `setChatPathVisitSiteControlsLocked` calls were removed:** +Alessandro's review comment on [#4855 line 280](https://github.com/duckduckgo/apple-browsers/pull/4855) asked to use `NewTabPageControllerDelegate` instead of casting `(parent as? MainViewController)`. A separate review comment on [#4855 line 477](https://github.com/duckduckgo/apple-browsers/pull/4855) noted Costas's preference to hide both address bar and toolbar via `setBarsHidden(false)`. Using `setBarsHidden` via `chromeDelegate` removes the need for the cast entirely, making `setChatPathVisitSiteControlsLocked` unreachable. The method definition still exists in `MainViewController+DuckAIExperiment.swift:166` as dead code — needs to be deleted. + +**Source:** Alessandro review comments on PR #4855 ([line 280](https://github.com/duckduckgo/apple-browsers/pull/4855), [line 473](https://github.com/duckduckgo/apple-browsers/pull/4855), [line 477](https://github.com/duckduckgo/apple-browsers/pull/4855)) + Costas's preference cited therein + Bugbot #4855 "Guard early return aborts entire dialog" + Bugbot #4855 "Navigation bar not restored when NTP dismissed". + +**Current state:** ✏️ Uncommitted local change on `sr-feedback` branch. + +### 2. `NewTabPageControllerDelegate.swift` + `MainViewController.swift` — new delegate method + +**What changed:** Added `newTabPageControllerCurrentTabIsLoading(_ controller: NewTabPageViewController) -> Bool` to the `NewTabPageControllerDelegate` protocol. Implemented in `MainViewController.swift` to return `currentTab?.isLoading == true`. + +**Source:** Alessandro review comment on [#4855 line 473](https://github.com/duckduckgo/apple-browsers/pull/4855): "should we add `(parent as? MainViewController)?.currentTab?.isLoading != true` as condition of the if instead of having the guard..." Also addresses Bugbot #4855 "Guard early return aborts entire dialog presentation" and removes the `(parent as?)` cast as requested on [#4855 line 280](https://github.com/duckduckgo/apple-browsers/pull/4855). + +**Current state:** ✏️ Uncommitted local change on `sr-feedback` branch. + +### 3. `OnboardingIntroViewModel.swift` — returning-user guard + remove hardcoded cohort override + +**What changed:** +- Uncommented `guard case .introDialog(isReturningUser: false) = introSteps.first` in `insertExperimentStepIfNeeded()`. This ensures sync-restore / returning users are excluded from the Duck.ai query experiment step. +- Removed hardcoded `return .treatmentB` override from `resolveDuckAIQueryExperimentCohortID()` (was left in for local testing). + +**Source (returning-user guard):** [Alessandro May 7 review on PR #4544](https://github.com/duckduckgo/apple-browsers/pull/4544), Asana task [1214682678629767](https://app.asana.com/1/137249556945/task/1214682678629767), Bugbot on #4855 "Returning-user guard commented out despite PR intent". The guard was temporarily commented out during development; it must be active before shipping. + +**Source (hardcoded override removal):** Bugbot on #4855 "Hardcoded debug return bypasses feature flag entirely". This was a local testing override (`return .treatmentB`) that must not ship. + +**Current state:** ✏️ Uncommitted local change on `sr-feedback` branch. + +### 4. `UserText.swift` + all 26 lproj files — `searchAndDuckAIOption` string reverted + "Ask AI" toggle label + +**What changed:** +- `searchAndDuckAIOption` reverted to `"Toggle between\nSearch and Duck.ai"` (was changed to "Toggle between\nSearch and Ask AI" in a prior commit). +- DuckAIQuery screen toggle label changed from "Duck.ai" to "Ask AI" in `OnboardingView+DuckAIExperimentSearchContent.swift`. + +**Source (revert):** Alessandro review comment on [#4855 UserText.swift:2375](https://github.com/duckduckgo/apple-browsers/pull/4855): *"the rename of 'Duck.ai' to 'Ask AI' is for the toggle we show in the Duck Ai Query screen. The copy for this screen should be reverted."* — meaning the Search Experience screen copy stays as "Duck.ai", only the DuckAI query toggle label becomes "Ask AI". + +**Source (Ask AI label):** [GJ8 ship review](https://app.asana.com/1/137249556945/task/1214147157456478): *"change 'Duck.ai' to 'Ask AI' in the toggle screen in onboarding only."* + +⚠️ **Unresolved copy question:** Alessandro's comment says "Ask.ai" (with dot). Gary's GJ8 says "Ask AI" (no dot). Needs explicit confirmation from product/design before shipping. + +**Current state:** ✏️ Uncommitted local change on `sr-feedback` branch. + +### 5. Dead code: `setChatPathVisitSiteControlsLocked` in `MainViewController+DuckAIExperiment.swift:166` + +**What:** The method has no callers now that `NewTabPageViewController` uses `setBarsHidden` via the chrome delegate instead. Should be deleted. + +**Source:** Removal of callers in item #1 above. + +**Current state:** ✏️ Still in code, needs deletion. Uncommitted. + +--- + +## Open GitHub Comment Threads — PR #4544 + +These Bugbot threads were on PR #4544 and are **not resolved on GitHub**. Status of each: + +### [Bugbot] Hardcoded return forces all users into treatment group (OnboardingIntroViewModel.swift) +**Issue:** `return .treatmentA` hardcoded override in `resolveDuckAIQueryExperimentCohortID()`. +**Code state:** The `.treatmentA` override was removed on the `#4544` branch (replaced with `.treatmentB` for testing, then also removed — see uncommitted change #3 above). The `#4544` branch tip no longer has `.treatmentA` hardcoded. +**Thread state:** 🔴 **Not resolved on GitHub.** Bugbot comment was on an old commit — outdated. → Resolve thread. + +### [Bugbot] Subscription promo override always returns true (OnboardingSubscriptionPromotionHelper.swift) +**Issue:** `shouldDisplay` was hardcoded to `return true` for testing. +**Code state:** Reverted in commit [`f8d5ba2`](https://github.com/duckduckgo/apple-browsers/commit/f8d5ba2) on #4544 branch. +**Thread state:** 🔴 **Not resolved on GitHub.** Fix is in the branch. → Resolve thread. + +### [Bugbot] Chat-path subscription redirect commented out, variable unused (RebrandedNewTabDaxDialogFactory.swift) +**Issue:** `isChatPathSubscriptionPromo` was commented out, variable unused. +**Code state:** Dead code removed in commit [`e682475`](https://github.com/duckduckgo/apple-browsers/commit/e682475) on #4544 branch. +**Thread state:** 🔴 **Not resolved on GitHub.** Fix is in the branch. → Resolve thread. + +### [Bugbot] Missing pixel definitions (PixelEvent.swift:2120) +**Issue:** `onboardingChatPathTryVisitSiteUnique` and `onboardingChatPathTrackersBlockedUnique` missing from `PixelEvent`. +**Code state:** Both defined in commit [`ec42fd8`](https://github.com/duckduckgo/apple-browsers/commit/ec42fd8) on #4544 branch (lines 268–269, 2119–2120 of PixelEvent.swift). +**Thread state:** 🔴 **Not resolved on GitHub.** Fix is in the branch. → Resolve thread. + +### [Bugbot] Chat-path completion dialog shown twice (MainViewController.swift:4711) +**Issue:** Two competing paths (`tabDidRequestNewTab` dispatch + direct call) could both invoke `presentChatPathOnboardingCompletionIfNeeded()`. +**Code state:** `presentChatPathOnboardingCompletionIfNeeded()` is guarded by `chatPathPhase == .trackerToEOJ`. Whether the double-call race was fully resolved needs verification. +**Thread state:** 🔴 **Not resolved on GitHub.** → Verify code, then resolve thread. + +### [Bugbot r3234645543] Chat-path EOJ not shown after tapping tracker dialog CTA (TabViewController.swift:4214) +**Issue:** `didTapDismissContextualOnboardingAction` doesn't call `tabDidRequestNewTab` for chat path, so tapping "Got it" on tracker dialog doesn't open a new tab for the EOJ. +**Code state:** 🔴 **NOT fixed on the #4544 branch.** The fix (`if chatPathPhase == .trackerToEOJ { tabDidRequestNewTab }` in `didTapDismissContextualOnboardingAction`) exists only on the `sr-feedback` branch (commit `6c3774e4f8`). It will be present when the full PR stack merges, but it is not in #4544 itself. +**Thread state:** 🔴 **Not resolved on GitHub.** Fix is not in this PR — it's in #4855. Note this in the thread or backport the fix to #4544. + +--- + +## Open GitHub Comment Threads — PR #4664 + +### [Alessandro + Bugbot] Title changes for all paths, not just chat path (RebrandedNewTabDaxDialogFactory.swift) +**Issue:** `createSubsequentDialog` title was changed for all flows, not gated on `isChatPath`. +**Code state:** Fixed — `isChatPath` check added (`daxDialogsFlowCoordinator.chatPathPhase == .visitSite`). The rebranded factory now uses the chat-path title conditionally. +**Thread state:** Likely resolved by the fix but confirm on GitHub. → Check and resolve thread. + +### [Bugbot] Dismiss button appears on standard path too (RebrandedContextualOnboardingDialogs+SubscriptionPromo.swift:101) +**Issue:** Dismiss button added for chat path appeared on standard path too. +**Code state:** Needs verification on #4664 branch. +**Thread state:** 🔴 **Not confirmed resolved.** → Verify code. + +--- + +## Open GitHub Comment Threads — PR #4668 + +### [aataraxiaa] Commented-out `Config(...)` line in FeatureFlag.swift:635 +**Issue:** `// Config(source: .remoteReleasable(.subfeature(AIChatSubfeature.unifiedToggleInput)))` — a dead commented-out duplicate still in code. +**Source:** [aataraxiaa review comment](https://github.com/duckduckgo/apple-browsers/pull/4668): *"Obviously you just changed this for testing, but just a reminder to change it back before we merge."* +**Code state:** 🔴 **Still in code** on `#4668` branch. The `defaultValue: .enabled` override + commented-out original are both present. +**Thread state:** 🔴 **Not resolved.** → Remove the commented-out line and the `defaultValue: .enabled` before merging. + +### [Bugbot] Hardcoded debug return bypasses cohort resolution (OnboardingIntroViewModel.swift:473) +**Issue:** Same `return .treatmentB` override as above. +**Code state:** Removed in the uncommitted local change on `sr-feedback` branch. Will be present once committed and the stack is built. Not yet fixed on #4668 branch itself. +**Thread state:** 🔴 **Not resolved.** → Will be resolved when sr-feedback is merged down or the fix is backported. + +### [Bugbot] Protocol method `embedInUnifiedInputEditingAreaIfActive` never called (MainViewController.swift + BrowserChromeManager.swift) +**Issue:** Method added to `BrowserChromeDelegate` protocol and implemented in `BrowserChromeManager`, but never called anywhere. +**Code state:** On the `sr-feedback` branch, commit `82bb0f71e3` removed the `embedDialogInEditingState` dead code path. The method may now be truly unreachable. Needs verification on #4668 branch. +**Thread state:** 🔴 **Not resolved.** → Verify, then either add a caller or delete the method and its implementations. + +--- + +## Open GitHub Comment Threads — PR #4855 + +All four Alessandro review comments and all Bugbot comments are addressed by the **uncommitted local changes** listed above. The GitHub threads are **not yet resolved** because the changes haven't been committed/pushed. + +| Comment | Fix location | Thread resolved? | |---|---|---| -| [#4544](https://github.com/duckduckgo/apple-browsers/pull/4544) | `demo-tracker-blocking-onboarding` | Open — review required | -| [#4591](https://github.com/duckduckgo/apple-browsers/pull/4591) | `demo-tracker-blocking-onboarding-ui-polish` | Approved | -| [#4664](https://github.com/duckduckgo/apple-browsers/pull/4664) | `demo-tracker-blocking-onboarding-chat-path-dialog-polish` | Approved | -| [#4668](https://github.com/duckduckgo/apple-browsers/pull/4668) | `demo-tracker-blocking-onboarding-uti-flow` | Open — no review yet | -| [#4855](https://github.com/duckduckgo/apple-browsers/pull/4855) | `demo-tracker-blocking-onboarding-sr-feedback` | Open — no review yet | +| Use `NewTabPageControllerDelegate` instead of `(parent as?)` cast (line 280) | Uncommitted — `NewTabPageControllerDelegate.swift` | 🔴 No | +| Hide both bars via `setBarsHidden` per Costas (line 477) | Uncommitted — `NewTabPageViewController.swift` | 🔴 No | +| Fold loading check into `if` condition (line 473) | Uncommitted — `NewTabPageViewController.swift` | 🔴 No | +| Revert `searchAndDuckAIOption` copy (UserText.swift:2375) | Uncommitted — `UserText.swift` + lproj files | 🔴 No | +| Bugbot: Navigation bar not restored when NTP dismissed (line 281) | Uncommitted — `NewTabPageViewController.swift` `dismiss()` | 🔴 No | +| Bugbot: Guard early return aborts dialog presentation (line 473) | Uncommitted — guard folded into `if` | 🔴 No | +| Bugbot: Hardcoded debug return bypasses feature flag (OnboardingIntroViewModel:473) | Uncommitted — hardcoded return removed | 🔴 No | +| Bugbot: Returning-user guard commented out (OnboardingIntroViewModel:451) | Uncommitted — guard uncommented | 🔴 No | + +→ **Commit and push all local changes first. Then resolve these threads.** --- -## Required Changes +## Pre-Ship Blockers -### PR #4544 -- [x] Danger CI: no `@UserDefaultsWrapper` remains -- [x] Mock refactor (alessandroboron): `MockDaxDialogsSettings.chatPathPhase` plain stored property -- [x] **Sync restore exclusion** — [Alessandro May 7](https://app.asana.com/1/137249556945/task/1214147157456478): *"if the user selects 'Restore My Stuff' we disable Dax dialogs — we should not enrol those users in the experiment"*. Fixed: uncommented `guard case .introDialog(isReturningUser: false) = introSteps.first` in `insertExperimentStepIfNeeded()` -- [x] `return .treatmentA` override removed from `resolveDuckAIQueryExperimentCohortID()` -- [x] Pixels: `onboardingChatPathTryVisitSiteUnique` / `onboardingChatPathTrackersBlockedUnique` defined, no overlap with PR #4687 +### 1. Commit and push local changes on `sr-feedback` -### PR #4664 -- [x] Title scope fix (alessandroboron): `createSubsequentDialog` uses correct title per chat-path vs standard path +All changes in the "Uncommitted Local Changes" section above must be committed to `alex/demo-tracker-blocking-onboarding-sr-feedback` and pushed before PR #4855 can be reviewed. Then the eight GitHub threads above can be resolved. -### PR #4668 -- [x] Dialog position, dismiss, UTI bar, completion path resolved -- [x] `.unifiedToggleInput` feature flag has no hardcoded `defaultValue: .enabled` +**Current state:** 🔴 Not done. -### PR #4855 -- [x] `setBarsHidden(true/false, animated: false, customAnimationDuration: nil)` replaces `setNavigationBarHidden` + `setChatPathVisitSiteControlsLocked` in show/dismiss/dismissHostingController -- [x] `newTabPageControllerCurrentTabIsLoading` added to `NewTabPageControllerDelegate`; all `(parent as? MainViewController)?` casts gone from `NewTabPageViewController` -- [x] Loading guard folded into outer `if` via delegate method -- [x] `searchAndDuckAIOption` reverted to `"Toggle between\nSearch and Duck.ai"` in `UserText.swift` + all 26 lproj files -- [x] **DuckAIQuery toggle copy** — [Gary May 6](https://app.asana.com/1/137249556945/task/1214147157456478): *"change 'Duck.ai' to 'Ask AI' in the toggle screen in onboarding only, not the standard toggle"*. Fixed: `DuckAIQueryExperiment.toggleAILabel = "Ask AI"` (uses `NotLocalizedString`) +### 2. Tell UTI team the experiment name + +**Source:** [Pete Apr 30 comment](https://app.asana.com/1/137249556945/task/1214147157456478/1214600831548835): Pete's team will exclude users enrolled in this experiment from the UTI feature rollout, to avoid breaking their onboarding. They need the final experiment name. + +**Current state:** 🔴 Blocked — experiment name not final (see #4 below). Once known: fill into [O-J <> O-N Coordination](https://app.asana.com/1/137249556945/project/1214157224317277/task/1214288645859692) and [O-N Live Onboarding Experiment Details](https://app.asana.com/1/137249556945/task/1214601039604921). + +### 3. Privacy config: add US/EN targeting to override + +**Source:** [Task 1214682678629768](https://app.asana.com/1/137249556945/task/1214682678629768): experiment must be limited to US English users. Without this, all locales worldwide would be enrolled. + +**What:** In `privacy-configuration/overrides/ios-override.json`, add `"targets": [{ "localeLanguage": "en", "localeCountry": "US" }]` to the experiment entry. + +**Current state:** 🔴 Local edit exists on wrong branch (`alex/remove-autocomplete-tabs`) in the `privacy-configuration` repo, not committed. + +### 4. Privacy config: rename the experiment + +**Source:** [Task 1214682678629768](https://app.asana.com/1/137249556945/task/1214682678629768): some internal users were enrolled under `onboardingDuckAIQueryExperiment` during testing. A new name gives production users a clean, separate enrollment. + +**What — three-part change:** +1. **BSK** (`SharedPackages/BrowserServicesKit`): add a new case to `AIChatSubfeature` enum with the new name string. +2. **App** (`iOS/Core/FeatureFlag.swift`): update `FeatureFlag.onboardingDuckAIQueryExperiment` to reference the new subfeature case. +3. **`privacy-configuration` repo** (`overrides/ios-override.json`): add new experiment entry with `targets`, and set the old `onboardingDuckAIQueryExperiment` entry to `"state": "disabled"`. + +Do this in the same PR as item #3 (both touch the same file in the same repo). + +**Current state:** 🔴 Blocked — new experiment name not decided. + +### 5. Fix commented-out feature flag line in PR #4668 + +**Source:** aataraxiaa review comment on #4668 (see Open Threads above). + +**What:** Remove `defaultValue: .enabled` and the `// Config(...)` dead line from `FeatureFlag.swift:635` for `unifiedToggleInput`. + +**Current state:** 🔴 Still in code on `#4668` branch. Not fixed. + +### 6. Clarify "Ask AI" vs "Ask.ai" copy + +**Source:** Conflict between GJ8 ("Ask AI") and Alessandro's review comment ("Ask.ai"). + +**Current state:** 🔴 Implemented as "Ask AI" (no dot) per GJ8. Awaiting explicit product/design confirmation. --- -## Before Going Live +## Experiment Config (current, local override) -### 1. UTI experiment exclusion - -**Source:** [Pete Apr 30, ship review](https://app.asana.com/1/137249556945/task/1214147157456478/1214600831548835): *"to avoid impacting any live onboarding experiments we can exclude those experiment participants when we release. Continue coordination in [O-J <> O-N Coordination](https://app.asana.com/1/137249556945/project/1214157224317277/task/1214288645859692)."* - -Task [O-J <> O-N Coordination](https://app.asana.com/1/137249556945/project/1214157224317277/task/1214288645859692) (owned by Pete) lists O-N experiments the UTI team needs to be aware of for exclusion at UTI rollout. Already lists this iOS experiment under "iOS - O-N will handle". - -- [ ] Confirm experiment is listed and named correctly in [O-J <> O-N Coordination](https://app.asana.com/1/137249556945/project/1214157224317277/task/1214288645859692) before going live. - -### 2. Privacy config targeting - -- [x] Added `"targets": [{ "localeLanguage": "en", "localeCountry": "US" }]` to `onboardingDuckAIQueryExperiment` in `privacy-configuration/overrides/ios-override.json` - -### 3. Experiment rename - -No explicit Asana comment or PR review requested this — no source found. - -- [ ] **Decide:** rename `onboardingDuckAIQueryExperiment` before production rollout? If yes: requires new `AIChatSubfeature` case in BSK + new privacy config entry + disable old one. - ---- - -## Resolved / Dismissed - -- **GJ6c** — No longer required; address bar hidden for visit-site step; Gary + Costas confirmed search after trackers-blocked is acceptable -- **GJ2** — X button removed from chat-path dialogs (PR #4664) -- **GJ3** — Address bar + toolbar hidden for visit-site step (chat-path only) -- **GJ4** — Copy: "Next, try visiting a site!" after AI -- **GJ7** — Returning users excluded from experiment enrollment -- **GJ8** — Onboarding toggle shows "Ask AI"; Search Experience screen keeps "Duck.ai" -- **Fire tabs flash** — Suppressed via `isStillOnboarding()` in `DaxDialogs` - ---- - -## Experiment Config (current) - -Entry in `privacy-configuration/overrides/ios-override.json` under `aiChat` subfeatures: +`privacy-configuration/overrides/ios-override.json` under `aiChat` subfeatures: ```json "onboardingDuckAIQueryExperiment": { @@ -91,5 +237,5 @@ Entry in `privacy-configuration/overrides/ios-override.json` under `aiChat` subf } ``` -> Feature flag: `FeatureFlag.onboardingDuckAIQueryExperiment` +> Feature flag: `FeatureFlag.onboardingDuckAIQueryExperiment` in `iOS/Core/FeatureFlag.swift` > Cohort type: `FeatureFlag.DuckAIQueryExperimentCohort`