diff --git a/family/how-to/openmediavault-rpi5.md b/family/how-to/openmediavault-rpi5.md index d8b3bfe7..99a1dab6 100644 --- a/family/how-to/openmediavault-rpi5.md +++ b/family/how-to/openmediavault-rpi5.md @@ -211,9 +211,9 @@ cd /home/kraken/ && sudo docker compose pull && sudo docker compose up -d Compose: `/home/kraken/timemachine/docker-compose.yml` Данные: `/srv/dev-disk-by-uuid-49e8f586-3839-4c5d-a1e1-58bfc3579ade/timemachine/` -**Расписание** (crontab kraken-пользователя): -- `0 4 * * *` UTC (10:00 GMT+6) → `/usr/local/bin/tm-start.sh` — поднять контейнер -- `0 16 * * *` UTC (22:00 GMT+6) → `/usr/local/bin/tm-stop.sh` — остановить контейнер +**Расписание** (root crontab): +- `0 4 * * *` UTC (10:00 GMT+6) → `/usr/local/bin/tm-start.sh` — поднять контейнер ✅ добавлен 2026-05-14 +- `0 16 * * *` UTC (22:00 GMT+6) → `/usr/local/bin/tm-stop.sh` — остановить контейнер ✅ добавлен 2026-05-14 - `restart: no` — при загрузке Pi не стартует автоматически **Credentials:** diff --git a/work/plans/time-machine-tunnel-backup.md b/work/plans/time-machine-tunnel-backup.md index 0ea06092..c1fef22a 100644 --- a/work/plans/time-machine-tunnel-backup.md +++ b/work/plans/time-machine-tunnel-backup.md @@ -159,3 +159,4 @@ sudo docker stop cloudflared - `AllowedIPs = 10.99.0.0/24` — только VPN-трафик через туннель, интернет напрямую - SMB через WireGuard достаточно быстр для TM - VPS = single point of failure для TM, это приемлемо +- Time Machine login/pass: timemachine/timemachine 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 6d032287..393d7aff 100644 --- a/work/wiki/apple-browsers/chat-path-onboarding-tracker-blocking.md +++ b/work/wiki/apple-browsers/chat-path-onboarding-tracker-blocking.md @@ -4,113 +4,92 @@ > **Branch stack:** `demo-tracker-blocking-onboarding` → `ui-polish` → `chat-path-dialog-polish` → `sr-feedback` → `uti-flow` > **Due:** 2026-05-15 -## Overview - -A/B experiment adding a tracker-blocking demo step to onboarding for users who pick Duck.ai (chat-path). After the Fire Onboarding step, users see: -1. "Try visiting a site!" dialog (address bar + toolbar hidden) -2. Trackers-blocked dialog after a site loads -3. "You've got this!" EOJ completion dialog -4. Subscription upsell ("Oh, before I forget...") - -**Cohorts:** Treatment A (address bar top) · Treatment B (address bar bottom) · Control (no change) -**Audience:** US only · iPhone only · Users who chose Duck.ai in onboarding, in A or B cohort - ---- - ## PR Stack | PR | Branch | Status | |---|---|---| -| [#4544](https://github.com/duckduckgo/apple-browsers/pull/4544) | `demo-tracker-blocking-onboarding` | Open — needs fixes | -| [#4591](https://github.com/duckduckgo/apple-browsers/pull/4591) | `demo-tracker-blocking-onboarding-ui-polish` | Approved — needs rebase | -| [#4664](https://github.com/duckduckgo/apple-browsers/pull/4664) | `demo-tracker-blocking-onboarding-chat-path-dialog-polish` | Open — needs fix | -| [#4668](https://github.com/duckduckgo/apple-browsers/pull/4668) | `demo-tracker-blocking-onboarding-uti-flow` | Open — needs fix | -| [#4855](https://github.com/duckduckgo/apple-browsers/pull/4855) | `demo-tracker-blocking-onboarding-sr-feedback` | Open — needs fixes | +| [#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 | --- ## Required Changes -### PR #4544 — main chat-path branch +### 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 -- [x] **Danger CI**: No `@UserDefaultsWrapper` usage remains. -- [x] **Mock refactor** (alessandroboron): `MockDaxDialogsSettings.chatPathPhase` is a plain stored property, directly settable in tests. -- [x] **Sync restore exclusion**: Uncommented `guard case .introDialog(isReturningUser: false) = introSteps.first` in `OnboardingIntroViewModel.insertExperimentStepIfNeeded()`. Excludes all returning users (including sync-restore) from experiment enrollment. -- [x] **`return .treatmentA` override**: Removed hardcoded early return from `resolveDuckAIQueryExperimentCohortID()`. Now routes through the feature flagger. -- [x] **Pixels**: `onboardingChatPathTryVisitSiteUnique` and `onboardingChatPathTrackersBlockedUnique` defined in `PixelEvent.swift` with matching `onboarding.json5` entries. No overlap with PR #4687. +### PR #4664 +- [x] Title scope fix (alessandroboron): `createSubsequentDialog` uses correct title per chat-path vs standard path -### PR #4664 — chat-path dialog polish +### PR #4668 +- [x] Dialog position, dismiss, UTI bar, completion path resolved +- [x] `.unifiedToggleInput` feature flag has no hardcoded `defaultValue: .enabled` -- [x] **Title scope** (alessandroboron): Fixed in commit `c15122a1b0` — `RebrandedNewTabDaxDialogFactory.createSubsequentDialog` uses the correct title per chat-path vs standard path. - -### PR #4668 — UTI onboarding flow fixes - -- [x] Dialog position, dismiss on navigation, UTI bar, completion path — all resolved. -- [x] **Hardcoded UTI override**: `FeatureFlag.swift` `.unifiedToggleInput` confirmed correct — `Config(source: .remoteReleasable(...))`, no `defaultValue: .enabled`. - -### PR #4855 — sr-feedback - -- [x] **Hide toolbar + address bar**: `NewTabPageViewController` now calls `chromeDelegate?.setBarsHidden(true/false, animated: false, customAnimationDuration: nil)` in the show block, `dismiss()`, and `dismissHostingController`. Replaces previous `setNavigationBarHidden` + `setChatPathVisitSiteControlsLocked` pair. -- [x] **Use delegate**: Added `newTabPageControllerCurrentTabIsLoading(_ controller:) -> Bool` to `NewTabPageControllerDelegate` (default `false`). Implemented in `MainViewController` as `currentTab?.isLoading == true`. All `(parent as? MainViewController)?` casts removed from `NewTabPageViewController`. -- [x] **Loading guard placement**: Folded into the outer `if` condition via the new delegate method. No orphaned lock possible. -- [x] **Revert Search Experience screen copy**: `UserText.swift` `searchAndDuckAIOption` reverted to `"Toggle between\nSearch and Duck.ai"`. All 26 lproj files updated. -- [x] **DuckAIQuery toggle copy**: `DuckAIQueryExperiment.toggleAILabel` = `"Ask AI"`. +### 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`) --- -## Privacy Config / Experiment Setup (TBD before shipping) +## Before Going Live -- [ ] Rename experiment in privacy config — create new experiment name, disable old one. -- [ ] Set `"targets": [{ "localeLanguage": "en", "localeCountry": "US" }]` in the experiment payload. -- [ ] Inform Pete in [O-N Live Onboarding Experiment Details](https://app.asana.com/1/137249556945/task/1214601039604921) once experiment name is confirmed. +### 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. -- **GJ3** — Hide address bar + toolbar for "Try visiting a site" step (chat-path only). -- **GJ2** — X button removed from chat-path dialogs (PR #4664). -- **GJ4** — Copy updated to "Next, try visiting a site!" after AI. -- **GJ8** — DuckAIQuery experiment toggle shows "Ask AI" (onboarding only; Search Experience screen keeps "Duck.ai"). -- **"Try fire tabs" flash** — Suppressed via `isStillOnboarding()` in `DaxDialogs` for chat-path users. -- **GJ7** — Returning users guarded from experiment enrollment. +- **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` --- -## Key Files +## Experiment Config (current) -| File | Purpose | -|---|---| -| `iOS/DuckDuckGo/DaxDialogs.swift` | Core onboarding dialog logic, chat-path phase state machine | -| `iOS/DuckDuckGo/OnboardingFlow/LinearOnboarding/OnboardingIntroViewModel.swift` | Experiment enrollment, step injection | -| `iOS/DuckDuckGo/NewTabPageViewController.swift` | Visit-site dialog presentation, bar hiding | -| `iOS/DuckDuckGo/MainViewController+DuckAIExperiment.swift` | Chat-path completion, EOJ dialog trigger | -| `iOS/Core/FeatureFlag.swift` | `onboardingDuckAIQueryExperiment` feature flag + cohorts | -| `iOS/DuckDuckGo/UserText.swift` | Onboarding copy strings | -| `iOS/DuckDuckGo/OnboardingFlow/LinearOnboarding/OnboardingView+DuckAIExperimentSearchContent.swift` | DuckAIQuery toggle + experiment UI | -| `iOS/DuckDuckGo/OnboardingFlow/ContextualOnboarding/Rebranding/RebrandedNewTabDaxDialogFactory.swift` | Chat-path dialog creation | - ---- - -## Copy Changes Summary - -| Location | Value | Status | -|---|---|---| -| `DuckAIQueryExperiment.toggleAILabel` (onboarding experiment toggle) | `Ask AI` | Done | -| `searchAndDuckAIOption` (Search Experience screen) | `Toggle between\nSearch and Duck.ai` | Done | - ---- - -## Experiment Config +Entry in `privacy-configuration/overrides/ios-override.json` under `aiChat` subfeatures: ```json -{ - "experimentName": "TBD", +"onboardingDuckAIQueryExperiment": { + "state": "enabled", "targets": [{ "localeLanguage": "en", "localeCountry": "US" }], - "cohorts": ["control", "treatmentA", "treatmentB"] + "cohorts": [ + { "name": "control", "weight": 1 }, + { "name": "treatmentA", "weight": 1 }, + { "name": "treatmentB", "weight": 1 } + ] } ``` > Feature flag: `FeatureFlag.onboardingDuckAIQueryExperiment` -> Cohort type: `FeatureFlag.DuckAIQueryExperimentCohort` (`.control`, `.treatmentA`, `.treatmentB`) +> Cohort type: `FeatureFlag.DuckAIQueryExperimentCohort`