# Update Notification & Library Migration — Feature Spec

> BrainDrive update system: notify users when a new version is available, provide update instructions, and migrate library files via AI-driven conversational flow.

**Status:** Draft
**Owner:** Dave W (UI) + Dave J (scripts/backend)
**Task:** T-458
**Related:** D137 (self-describing artifacts), D138 (to-do system as pattern), D109 (auto-update deferred), D148 (code vs file update architecture), T-412 (Watchtower research)

---

## Problem

BrainDrive is iterating fast. Users who installed via Docker have no way to know a new version exists. They assume whatever they installed is what BrainDrive is. Meanwhile, new features ship (to-do lists, digest, new AGENT.md templates) that require library file updates — not just a Docker image pull. Without a migration system, existing users miss new features entirely, and telling them to manually copy files doesn't scale.

Two problems, one spec:
1. **How does the user know there's an update?** (Notification)
2. **How do their library files stay current?** (Migration)

---

## User Stories

### US-1: Owner sees that an update is available
**As** a BrainDrive owner,
**I want** to see a clear indicator when a new version is available,
**So that** I know my BrainDrive can be improved without checking manually.

**Acceptance:**
- Indicator appears in the lower-left sidebar area (near owner name)
- Text is clear: "Update available" or similar
- Clicking the indicator navigates to BrainDrive Plus One, where the AI begins the update conversation
- Indicator is persistent until dismissed or update is applied
- Dismissing the indicator does not prevent it from reappearing on next version

### US-2: Owner updates their Docker image
**As** a BrainDrive owner,
**I want** to update by just telling the AI to do it,
**So that** I never have to open a terminal or run scripts myself.

**Acceptance:**
- Owner says "yes, update" (or clicks an update button)
- The AI (or backend) executes the update: pulls new Docker image, restarts containers
- Owner sees BrainDrive come back with the new version — no terminal, no scripts, no copy-paste
- **Fallback:** If the backend cannot execute host-level Docker commands (architecture limitation), show terminal instructions as a last resort. This fallback should be temporary — the goal is fully conversational updates.

### US-3: Owner gets new library features after updating
**As** a BrainDrive owner who just updated,
**I want** the AI to offer to set up new features that came with the update,
**So that** I get the full benefit of the new version without manually managing files.

**Acceptance:**
- On first conversation after an update, the AI reads the migration manifest
- AI tells the user what's new: "Your BrainDrive just updated. There's a new to-do feature — want me to set it up?"
- User confirms before any files are added or changed
- New files are created; existing files are merged (user customizations preserved)
- AI never silently drops user content

### US-4: Owner skips a migration
**As** a BrainDrive owner,
**I want** to decline a migration and not be asked again about the same one,
**So that** I'm not nagged about features I don't want.

**Acceptance:**
- User can say "no" or "skip" and the AI records that migration as declined
- AI does not re-offer the same migration in subsequent conversations
- User can later ask "what updates are available?" to see declined migrations

### US-5: Owner who skipped multiple versions updates
**As** a BrainDrive owner who hasn't updated in weeks,
**I want** updating to work in one step regardless of how many versions I skipped,
**So that** I don't have to apply updates sequentially.

**Acceptance:**
- Migration manifest is cumulative (covers all changes from initial version to current)
- A single update from any prior version brings the library fully current
- No intermediate steps required

---

## Scope

### In Scope
- Version check against GitHub Releases API
- Sidebar update indicator (lower-left, near owner name)
- Update instructions referencing Dave J's existing scripts
- Migration manifest format and storage (`system/updates/`)
- AI-driven migration flow (read manifest → ask user → apply changes)
- AI merge strategy for conflicting files (preserve user customizations)
- Cumulative manifest design (any version → latest)

### Out of Scope (but acknowledged as future directions)
- Automatic Docker updates (Watchtower replacement — T-412, D109)
- Native installer updates (future)
- Managed hosting updates (handled server-side)
- Rollback to previous versions
- Version-specific changelogs in the UI (release notes stay on GitHub)
- **Code update modularity** — when owners have custom interfaces, code updates will need the same review flow as file updates. Requires self-evolving code capabilities. Acknowledged by both Daves as eventually necessary.
- **Third-party updates** — community members or third parties pushing updates (new pages, features). The AI would review for security vulnerabilities and conflicts before presenting to the owner. Mentioned by Dave W as a natural extension.
- **Model recommendation per update** — updates are tested against a specific model (currently Haiku). Conveying "this update was tested with [model]" helps owners get maximum adherence.

---

## Technical Approach

### Part 1: Version Check & Notification

**Version source (current):**
- A version file (e.g., `system/version.json`) ships with the Docker image and starter pack
- Contains: `{ "version": "28.4.16", "released": "2026-04-16", "channel": "stable" }`
- Both the React frontend and the AI can read this file
- Dave J's build pipeline stamps the version and channel at build time

**Release channels:**

BrainDrive has two release tracks (D89, D119):

1. **Stable** — the Monday Docker image. This is what users run. Update notifications apply to this channel only.
2. **Dev** — Friday dev builds and any intermediate builds. Used by the team for weekend testing ahead of the Monday release. Users should never see notifications for dev releases.

The version check must filter by channel. GitHub Releases supports this via the `prerelease` flag — dev builds are marked as pre-releases, stable Monday builds are full releases. The `/releases/latest` endpoint already skips pre-releases by default, which gives us the right behavior for free. Dave J's build pipeline (T-441) needs to:
- Tag Friday/dev builds as **pre-release** on GitHub
- Tag Monday stable builds as **full release** on GitHub
- Set `"channel": "stable"` or `"channel": "dev"` in `system/version.json`

A user running a dev image (e.g., a team member testing) should not get update notifications for stable releases that are older than their dev build. The version check should compare channel-aware: dev users see nothing (they're ahead of stable), stable users only see stable releases.

**Version check (remote):**
- On first load of each day, the frontend calls the GitHub Releases API:
  `GET https://api.github.com/repos/BrainDriveAI/braindrive/releases/latest`
- This endpoint returns the latest **non-prerelease** — i.e., the latest stable Monday build
- Compare `tag_name` from the response to the local version
- If local `channel` is `"dev"`, skip the notification (dev users are testing ahead of stable)
- Cache the result for 24 hours (localStorage or similar)
- If the call fails (no internet, API down), silently skip — no error, no notification
- No authentication required (public repo)

**Notification UI:**
- Lower-left sidebar, near the owner name area
- Text: "Update available" (or a small badge/indicator)
- Clicking navigates to BrainDrive Plus One (the default AI project), which begins the update conversation
- Dismissible — but reappears if a newer version is detected

**Update execution (primary path — AI-driven):**
- The AI (or a backend endpoint) executes Dave J's existing update scripts
- Pulls the new Docker image, restarts the containers
- The owner just says "update" or clicks the button — no terminal involved
- After restart, the AI picks up with the library migration conversation
- **Requires:** backend ability to execute host-level Docker commands (see OQ-4)

**Update execution (fallback — terminal instructions):**
- If the backend cannot execute host Docker commands, show copy-pasteable instructions
- This is a temporary fallback, not the target UX
- Goal: eliminate this path entirely so the owner never touches a terminal for updates

### Two Update Types (D148)

Updates split into two categories with different flows:

1. **Code updates** (Docker image, backend, frontend) — push through automatically. No user customization to conflict with. The Docker pull + restart handles this entirely.
2. **File/onboarding updates** (library files, AGENT.md, starter pack content) — go through AI-mediated review. These may conflict with owner customizations and require the conversational flow described in Part 2 below.

This separation means: when a new Docker image lands, the code is already updated. The AI then handles just the file migration — comparing the owner's current library state vs. the new version's starter pack, identifying conflicts, and presenting options. Dependencies between skipped updates should be flagged (e.g., "you skipped the to-do update, which a later feature builds on").

> **Design Principle: Stateless Comparison**
>
> The AI analyzes updates by comparing the owner's current library files against the new version's files — nothing else. No change history, no intermediate versions, no tracking of sequential diffs. Just: what exists now vs. what's new. The `applied.json` tracks what was declined/applied (metadata), but the AI's actual analysis is always a fresh current-state-vs-target-state comparison. This keeps the system simple and plays to the AI's strengths — understanding context and resolving conflicts — rather than requiring deterministic change tracking that scales poorly.

**Future: code update modularity.** Currently, code updates always push through as a unit. Eventually, as owners build custom interfaces and dashboards, code updates will need the same modular review treatment as file updates. This requires significant refactoring and is deferred until self-evolving code is a reality — for now, self-evolving files are the frontier.

### Part 2: Library File Migration

**Migration manifest:**
- Location: `system/updates/manifest.md`
- Ships with each new Docker image inside the starter pack
- The starter pack is the source of truth for what the latest library files should look like
- Cumulative: lists ALL changes from v1 to current, organized by version

**Manifest format:**

Each version entry includes a `### What's New (AI Briefing)` section — natural language context that the AI reads to understand what changed, why it matters, and how to explain it to the owner. This is what makes the migration conversational rather than mechanical: the AI isn't just applying file diffs, it's briefing the owner on what's new and helping them decide what to adopt.

```markdown
# BrainDrive Update Manifest

> Read by the AI after a Docker image update to migrate the owner's library.
> Each version section includes:
> 1. **What's New (AI Briefing)** — context for the AI: what changed, why,
>    and how to explain it to the owner. This is your script.
> 2. **File changes** — specific files to add, modify, or remove.
>
> Apply all sections where version > owner's last-applied version.

## How to Use This File

When you detect that the owner's library version (in `system/version.json`)
is older than the Docker image version, read the AI Briefing sections for
all pending versions. Use that context to have an informed conversation
with the owner about what's new. Present changes conversationally — explain
what each update does and why they might want it. The owner decides what
to accept, decline, or merge.

Track which migrations have been applied in `system/updates/applied.json`.

---

## v28.4.16

### What's New (AI Briefing)

This update adds the **to-do list feature** — a way for owners to track
tasks conversationally. The to-do file uses the self-describing artifact
pattern (D137): the file itself contains the instructions for how the AI
should work with it, so you don't need to learn anything new. The owner
just says "add X to my to-do list" and you handle it.

This is the first feature built on the pattern that all future features
will follow (D138) — prompt-driven, not code-driven. The owner can
customize how to-dos work by editing the instructions in the file itself,
or by asking you to change them.

**How to talk about it with the owner:**
- Lead with what it does: "You can now track to-dos in BrainDrive. Just
  tell me what you need to do and I'll manage the list."
- If they already use a to-do system: "This works alongside whatever you
  already use — it's just a simple list I can help you manage."
- If they ask how it works: "It's a file in your library with instructions
  I follow. You can change those instructions anytime."

### New Files
- `me/todo.md` — To-do list seed file with inline instructions
  - Source: `system/starter-pack/me/todo.md`
  - Action: Create if not exists. If user already has a todo.md, show what's different and let them decide.

### Changed Files
- `AGENT.md` — Added one-line pointer to todo.md
  - Change: Add `- **To-dos:** See [me/todo.md](me/todo.md)` to the navigation section
  - Action: Show the change, apply if user confirms
```

**Applied migrations tracking:**
- `system/updates/applied.json` records which migrations the owner has applied or declined:
```json
{
  "last_applied": "28.4.15",
  "declined": ["v28.4.14-digest-feature"],
  "applied": ["v28.4.16-todo-list"]
}
```

**AI migration flow:**
1. AI detects version mismatch: `system/version.json` (Docker image version) > `applied.json` `last_applied`
2. AI reads `manifest.md` for all sections newer than `last_applied`
3. **Impact analysis:** Before presenting options, the AI reads the owner's current library files and compares them against the manifest's changes. It flags:
   - Which items are clean (new files, no conflicts)
   - Which items touch files the owner has customized — and what specifically would change
   - Any potential issues (e.g., "this update replaces the interview instructions you modified")
4. AI presents the full list with the impact analysis:
   - "Your BrainDrive just updated to v28.4.18. Here's what's new:"
   - "1. **To-do list** — track tasks conversationally (new file: me/todo.md) ✓ clean"
   - "2. **AGENT.md update** — adds a pointer to the to-do file ⚠️ you've customized this file — the update adds one line, your other changes are unaffected"
   - "3. **Digest feature** — daily summary of what happened (new file: me/digest.md) ✓ clean"
   - "Items 1 and 3 are safe to apply with no conflicts. Item 2 touches a file you've changed — I can show you the details. You can accept all, or we can go through them."
5. The owner chooses how to proceed:
   - **"Accept all"** — AI applies everything at once. Fast path for owners who trust the update.
   - **"Let's discuss"** — AI walks through each item individually with full context from the briefing. Owner decides per item (accept, skip, or merge).
   - **"Skip all"** — Decline everything. Recorded in applied.json.
   - **Cherry-pick** — Owner names specific items: "Do 1 and 3 but skip 2." AI applies only those.
6. For each accepted item, the AI:
   - **New files:** Creates the file from the starter pack source. If the user already has the file, shows what's different and lets them decide.
   - **Changed files:** Shows what will change. Applies if confirmed (including overwrites). **Data migration:** If the update changes the format of an existing file (e.g., adding priority fields to to-dos), the AI also updates the owner's existing data to match — not just the instructions. Example: if the to-do update adds priorities, the AI adds a default priority (e.g., P0) to each existing to-do item so the file stays well-formed for the updated instructions.
   - **Removed files:** Flags and asks before deleting.
7. After applying (or declining), updates `applied.json`
8. Does NOT re-offer declined migrations unprompted — with one exception: **dependency-aware re-surfacing.** If the owner is trying to do something that depends on a declined update, or if a later update builds on a declined one, the AI should proactively flag it: "I know you passed on the to-do feature, but the calendar update you're interested in builds on it. Want to revisit?" This is not nagging — it's context-aware guidance. The AI only re-surfaces a declined item when (a) there's a concrete dependency, or (b) the owner's actions suggest the declined feature would help them. Otherwise, declined means declined.

**Change presentation:**
- The AI reads the user's current file and the manifest's intended change
- Presents changes clearly: "This update changes your AGENT.md to add a to-do pointer. Here's what will change: [description]. Want me to apply it?"
- **If the user says yes:** apply the change, including overwrites. The user made an informed decision.
- **If the user says no:** skip it, record as declined.
- **If the user wants a merge:** AI merges intelligently, combining the update with the user's customizations.
- For simple changes (adding a line), the AI can summarize briefly. For substantial changes (rewritten instructions), show more detail so the user can make a good decision.
- Git backup provides a safety net — changes are recoverable.

---

## Invariants

These must ALWAYS be true:

1. **No silent changes.** The AI always shows what will change before modifying any file. The user makes an informed decision — including approving overwrites.
2. **User can always dismiss.** The update notification can be dismissed. No forced updates.
3. **Update is always optional.** The owner can decline any migration and continue using BrainDrive normally.
4. **Changes are recoverable.** Git backup provides a safety net. If the user regrets an overwrite, they can restore from backup.
5. **Any version can update to latest.** Cumulative manifest ensures no sequential dependency.

---

## Security Considerations

- **Version check:** Unauthenticated GET to GitHub's public API. No user data sent. IP exposure to GitHub is acceptable (same as any GitHub page visit).
- **Migration manifest:** Ships inside the Docker image — trusted source. Not fetched from the network at runtime.
- **File operations:** AI only creates/modifies files within the owner's library directory. No system-level file access.
- **Update script execution:** The update script runs Dave J's existing, trusted code from the Docker image. It only pulls from Docker Hub and restarts containers — no arbitrary code execution. The script is part of the shipped image, not downloaded at runtime.
- **Library migration:** Migration manifest describes file changes in natural language. The AI applies changes using its normal file tools — no arbitrary code execution.

---

## Dependencies

- Dave J's existing update scripts in `installer/docker/scripts/`
- Dave J's build pipeline (T-441) — stamps version, creates GitHub releases
- GitHub Releases API (public, no auth)
- React frontend (sidebar component)
- BrainDrive backend or frontend proxy for API call (or direct from client)

---

## Open Questions

### OQ-1: Can the backend execute host-level Docker commands?
**Owner:** Dave J
**Context:** For AI-driven updates (no terminal), the BrainDrive backend needs to execute `docker pull` + `docker compose restart` on the host. This requires either Docker socket access from inside the container or a sidecar/agent process on the host that the backend can signal. This is the critical question — if yes, fully conversational updates. If no, we fall back to terminal instructions (temporary).

### OQ-2: Exact update script command
**Owner:** Dave J
**Context:** Dave J has update scripts in the repo. Need the exact command — whether it's invoked by the backend (primary) or shown to the user (fallback). May be as simple as `./scripts/update.sh` or a Docker compose command.

### OQ-3: Version format and release channel tagging
**Owner:** Dave J
**Context:** Dave J uses date-based versioning (e.g., 28.4.13). Need to confirm: (1) the exact format and how it maps to GitHub release tags, (2) that the build pipeline tags Friday/dev builds as GitHub pre-releases and Monday stable builds as full releases, and (3) that `system/version.json` includes a `"channel"` field (`"stable"` or `"dev"`). The `/releases/latest` API endpoint already skips pre-releases, so if the pipeline tags correctly, the version check works automatically.

### OQ-4: Script restart reliability
**Owner:** Dave J
**Context:** Can the update script reliably restart Docker containers after pulling the new image? The container running BrainDrive will go down during restart — does it come back cleanly? Does the owner need to refresh their browser, or does it reconnect automatically?

---

## Decisions Made During Interview

| # | Decision | Rationale |
|---|----------|-----------|
| 1 | Scope covers both notification AND library migration | They're two halves of the same user need — knowing about an update is useless without getting the new features |
| 2 | Hybrid architecture: code for version check, AI for migration | Version check needs an API call (code). Migration benefits from conversational intelligence (AI). Aligns with D137. |
| 3 | GitHub Releases API for version check | Free, public repo, gives release notes, aligns with T-441 build pipeline. No extra infra. |
| 4 | Daily check, cached | Once per day on first load. No background polling. Cached in localStorage. |
| 5 | Lower-left sidebar indicator | Near owner name. Persistent but not intrusive. Clear text: "Update available." |
| 6 | AI-driven migration with cumulative manifest | AI reads manifest, asks user before applying. Cumulative so any version → latest works. |
| 7 | AI presents changes, user decides (including overwrites) | AI shows what will change. User can accept (overwrite), keep theirs, or merge. Informed consent, not blind protection. |
| 8 | Always ask before applying migrations | "Want me to set up the new to-do feature?" — never silently modify the library. |
| 9 | Require internet for version check | No offline support needed. If offline, silently skip. |
| 10 | No privacy concerns with GitHub API | Public unauthenticated GET. Acceptable. |
| 11 | Feature lives in braindrive-repo, not its own project | Core product feature tracked under T-458. |
| 12 | Update notifications only for stable (Monday) releases — not dev builds | Users run the stable Monday image (D89). Dev/Friday builds (D119) are for team testing. GitHub pre-release flag provides the filtering mechanism. Dev channel users see no notifications. |

---

## Changelog

| Date | Change | Reason |
|------|--------|--------|
| 2026-04-16 | Release channels: stable (Monday) vs dev (Friday) — users only notified for stable releases. GitHub pre-release flag for filtering. Channel field in version.json. OQ-3 expanded. Decision 12 added. | Dave W spec review |
| 2026-04-16 | Transcript review: BD+1 as update target (not modal), stateless comparison design principle, dependency-aware re-surfacing of declined updates, data migration for format changes, future directions (code modularity, third-party updates, model recommendation) | Reviewed 2026-04-16 dev call transcript against spec |
| 2026-04-16 | D148: Added "Two Update Types" section — code updates push through, file updates go through AI-mediated review. Added D148 to Related. | D148 reconciliation |
| 2026-04-16 | Spec created | Interview conducted, all questions resolved |
