# K2 Rebrand & Repo Migration Plan — K2SO → K2 (0.39.48 bridge → 0.40.0)

**Status:** PLAN for Rosson review (2026-06-10). Repo `Alakazam-211/K2` is
LIVE (public) with FSL-1.1-Apache-2.0 + draft Hosting Grant + draft
Trademark policy + pre-0.40 README.
**Brand:** "K2" (uppercase) publicly; `k2` lowercase for CLI/machine-facing;
"K2 by Alakazam Labs" composite brand (per the §2(d) house-mark decision).
**Related:** `k2-licensing-strategy.md`, GH #613 (rename), memory
`project_k2_product_taxonomy`.

---

## 0. The two insights that shape the whole plan

### A. The updater redirect lives in a MANIFEST, not in a client release
Installed apps poll a URL **baked into their tauri.conf**:
`github.com/Alakazam-211/K2SO/releases/latest/download/latest.json`.
The manifest's platform `url` field is **absolute** — it can point at an
asset on ANY repo. So the cross-repo jump is: publish a final release on
the OLD repo whose `latest.json` says `version: 0.40.0` with
`url: …/Alakazam-211/K2/releases/download/v0.40.0/K2.app.tar.gz`, signed
with the SAME updater key. Old apps follow it automatically. 0.39.48 is
therefore NOT strictly required for the redirect — but it IS required for
other reasons (§3).

### B. The old repo becomes a PUBLIC SHELL — binaries + bridge, no source
(Decision updated 2026-06-10 after Rosson: "I don't want the code under
MIT anymore.") The baked-in manifest URL forces the repo to stay PUBLIC in
some form — private = stragglers stranded + dead DMG links. But it need
not contain source. **The shell maneuver:**
1. publish the final bridge release;
2. create an orphan stub commit (pointer README only);
3. FORCE-MOVE every release tag onto the stub + force-push main to it,
   delete other branches → releases keep serving assets (bound to tag
   NAMES) and auto source-zips regenerate FROM THE STUB; the old history
   becomes unreachable (no forks pin it) and falls to GitHub GC (support
   ticket hastens);
4. retro-edit every old release's NOTES with a "K2SO is now K2 →" banner
   (gh release edit --notes);
5. archive the shell read-only.

**HARD GATE:** deleting a tag drafts its release (bridge-fatal); MOVING a
tag is the safe variant — verify the full sequence on a SACRIFICIAL repo
(tag move → release still published → latest/download alias serves →
source-zip = stub) before running it on K2SO.

Legal honesty, stated once: this stops Alakazam DISTRIBUTING the MIT
source; it cannot revoke MIT on copies already out there (560 unique
cloners in the last 14 days alone; third-party archives like Software
Heritage mirror public repos). The forward-looking protection is FSL +
trademark + the never-published control plane. Optional later stage: once
update telemetry shows the fleet has crossed, the shell can be privated
entirely (strands stragglers — decide with data, months out).

## 1. Rename surface inventory (compat policy per class)

| Class | Today | 0.40.0 | Compat |
|---|---|---|---|
| Public brand / UI strings | K2SO | **"K2 by Alakazam Labs"** wherever it fits (Rosson 2026-06-10: "anywhere that it can exist as K2 by Alakazam Labs, we should"): Settings header, About, onboarding/connection screens, update dialogs, DMG, site. Plain "K2" only where space genuinely forbids the composite (menu bar, tab chrome, toasts mid-sentence) | none needed |
| CLI binary | `k2so` | **`k2`** | `k2so` shim delegates + prints one-line deprecation warning (Rosson-specified) |
| App bundle | K2SO.app / com.alakazamlabs.k2so | K2.app / **dev.k2.app** (pending Q1) | updater rename rig decides mechanics (§2) |
| Daemon binary | k2so-daemon | k2-daemon | old name symlink for launchd transition window |
| Crates | k2so-core, k2so-daemon | k2-core, k2-daemon | internal — rename freely |
| launchd labels | com.k2so.k2so-daemon, com.k2so.agent-heartbeat, com.k2so.claude-auth-refresh | dev.k2.daemon, dev.k2.heartbeat, dev.k2.claude-auth (pending Q1) | 0.40.0 first-boot migration: bootout old, bootstrap new |
| Home dir | ~/.k2so (db, ports, tokens, logs, frpc) | **~/.k2** | first-boot move + `~/.k2so` → symlink to `~/.k2` for external tooling |
| Per-workspace dir | `.k2so/` (in USERS' repos: agents, inbox, prds, skills) | **keep `.k2so/` for 0.40** (Q2) | touching users' repos is the riskiest rename; defer to a later dual-read `.k2/` phase |
| Env vars | K2SO_PROJECT_PATH, K2SO_PANE_ID, … | K2_* emitted | K2SO_* still READ (dual-read) for ≥2 minor versions |
| TERM_PROGRAM / banners / pane ids | K2SO / k2so-daemon / alacritty-v2-* | K2 / k2-daemon | renderer + heuristics updated in lockstep |
| HTTP surface | /cli/* routes, daemon.port files | unchanged | wire compat is sacred (remote clients on older versions) |
| npm / package names | (none published; taxonomy says @alakazamlabs/k2) | claim **@alakazamlabs/k2** | Q4 |
| Skill files (SKILL.md regen, AGENT.md templates) | `k2so …` commands | `k2 …` | regen on 0.40 first boot; old text still works via shim |
| Keychain (K2 Connect login) | held for 0.40 per memory | dev.k2.* | migration copies/re-mints tokens |

## 2. Phase R1 — the decisive experiment (BEFORE anything ships)

**Updater rename rig:** install current K2SO.app in a VM/sacrificial user,
feed it a signed update bundle whose inner app is `K2.app` with a NEW
bundle identifier. Determine:
- does tauri-plugin-updater install it over /Applications/K2SO.app? as
  K2.app? leave both? fail signature/identifier checks?
- do macOS permission grants (notifications etc.) survive?

**VERDICT (2026-06-10, rig executed end-to-end): CLEAN RENAME ✅.**
Live test on this machine: installed rig K2SO.app (0.39.47, local
manifest endpoint) → updater fetched the manifest, downloaded the
signed K2.app bundle (identifier dev.k2.app, v0.40.0), staged it
("ready to install / app will restart"), Install & Relaunch
REPLACED THE BUNDLE CONTENTS IN PLACE and relaunched successfully:
CFBundleIdentifier=dev.k2.app, version=0.40.0, CFBundleName/
DisplayName="K2" (dock/menu show K2). The bundle DIRECTORY keeps its
old on-disk name (K2SO.app) for auto-updated users — cosmetic only;
fresh DMG installs get K2.app. → **0.39.48 needs NO updater shim**
(announcement + license disclosure + k2 CLI teaser only).
Rig footnotes for posterity: (a) tauri updater refuses http
endpoints without dangerousInsecureTransportProtocol (test-only);
(b) RIG OBSERVATION (Rosson): the relaunched 0.40.0 app did NOT
reconnect to the daemon — expected in the rig (dev-box plist points at
target/release; Build B's bundled daemon was version-skewed by
construction; no migration module yet) but it makes the ACCEPTANCE
GATE explicit: **after a cross-rename update, first boot MUST converge
app↔daemon unaided** — lockstep-versioned bundled daemon, plist healed
to the RENAMED binary path (k2-daemon; DAEMON_BINARY_NAME constant +
'recorded binary missing' heal covers it), launchd LABEL migrated
(bootout com.k2so.*, bootstrap dev.k2.*). R2 ships a first-boot
migration test for this; R4's release rig re-verifies end-to-end
before the bridge manifest is published.
(c) updater refuses to run from a path containing a SYMLINK
("StartingBinary found current_exe() that contains a symlink" — /tmp
→ /private/tmp tripped it; ~/dir worked). Neither affects production
(https + /Applications).

Outcomes → 0.39.48 scope (historical pre-verdict analysis):
- **Clean rename:** 0.39.48 is cosmetic (announcement + `k2` CLI teaser).
- **Updater can't rename:** choose between (a) 0.39.48 ships a custom
  install hook that performs app-swap (download new, bless, remove old,
  relaunch), or (b) 0.40.0 keeps `com.alakazamlabs.k2so` identifier +
  K2SO.app bundle name with full K2 *branding inside*, and the file-level
  bundle rename happens via fresh DMG installs only (auto-updated users
  rename at 0.41 or never — display name is what users see anyway).
  Option (b) is the lowest-risk fallback and is fully acceptable.

## 3. Phase plan

**R0 — done 2026-06-10:** `Alakazam-211/K2` public with LICENSE.md (canonical
FSL text + Alakazam Labs notice), COMMERCIAL_HOSTING_GRANT.md (DRAFT),
TRADEMARKS.md (DRAFT), README. Open decisions Q1–Q5 below.

**R1 — updater rename rig** (§2). Nothing else proceeds to ship before
this answers.

**R2 — the rename work** (current repo, feature branch, big but mechanical):
crates/binaries/CLI/env/banners/UI per §1 table; `k2` CLI + `k2so` shim;
~/.k2so→~/.k2 migration module + launchd label migration (runs at 0.40.0
first boot, idempotent, logged); release.sh parameterized for new repo +
asset names; tauri.conf: productName K2, identifier per Q1, updater
endpoint → `Alakazam-211/K2` manifest. Full test suite + a migration
integration test (fake ~/.k2so fixture → boot → assert moved+symlinked).

> **R2 STATUS: CODE-COMPLETE (2026-06-10, branch `rebrand-k2`, 7 commits
> 557146a…b17110c).** Stages: (1+2) crates k2-core/k2-daemon + `k2` CLI
> with deprecation shim; (3) K2_* env dual-emit/dual-read; (4) renderer
> prose + "K2 by Alakazam Labs" anchors; (5a) ~/.k2 home migration module
> (move + compat symlink, 4 tests); (5b) dev.k2.* launchd labels +
> keychain services + `k2-daemon` binary + boot-time launchd sweep with
> eager heartbeat/claude-auth re-ensure + keychain copy-on-read for all 3
> connect services; (6) workspace dot-dir dual-compat
> (`workspace_dot_dir()`: .k2/ preferred, .k2so/ default — Q2) across
> ~50 Rust sites + CLI `_ws_dot_dir`/`K2_HOME` + CLI label fallback;
> (7) productName K2 / dev.k2.app / brand icons / release.sh
> RELEASE_REPO param (default Alakazam-211/K2; K2_RELEASE_REPO override
> for bridge releases) — stage 8 folded into 7.
> Tests: 857 k2-core + all k2-daemon targets green; renderer at known
> baseline (#41); clone heartbeatEnabled failure is pre-existing → #44.
> `tauri build` verification: PASSED (K2.app bundles with dev.k2.app /
> "K2" / `k2` executable / brand icon / both CLIs incl. shim).
> **CONVERGENCE RIG: PASSED after 3 fixes (commit 95f60a1)** — fixture
> 0.39.x home + old plist booted under the 0.40 app/daemon. Caught and
> fixed: (a) db::init_database() ran before the home migration, creating
> an empty ~/.k2 and forcing Conflict; (b) plist install resolved the
> bundled daemon by the stale "k2so-daemon" name; (c) the autostart
> NotInstalled arm deferred to install_daemon_plist_v1 (already applied
> on every updated machine) so the swept plist never reinstalled —
> machine left daemonless. Now self-heals every boot.
> Rig caveat for repeats: launchd does NOT inherit a fake $HOME — a
> heal-bootstrapped dev.k2.daemon runs against the REAL home (it swept
> the real com.k2so plist on the dev box; restored). Headless-daemon rig
> covers the post-migration daemon half safely.

**R3 — 0.39.48 bridge release (old repo, last K2SO-branded build):**
- In-app rebrand announcement (WHATS_NEW): name change, new home, and the
  LICENSE CHANGE disclosure (0.40+ is Fair Source/FSL; 0.39.x stays MIT) —
  users crossing an auto-update license boundary deserve explicit notice.
- Ship the `k2` CLI alias early (with `k2so` still primary) as a teaser.
- Any updater shim R1 demands.

**R4 — code lands in the new repo:**
- **FRESH-HISTORY import** (corrected 2026-06-10): the public K2 repo
  starts from a single squashed commit ("Imported from K2SO at 0.39.x")
  under FSL. Pushing full history would RE-PUBLISH the entire MIT-era
  source (any old commit is checkout-able and MIT-licensed at that
  commit) — defeating the shell maneuver. Full history is preserved in a
  PRIVATE mirror (`Alakazam-211/K2-history` or local) for blame and
  archaeology; this also disposes of the PRD-privacy question entirely
  (no history → no PRDs ever public on the new repo).
- Internal-docs policy (Q5, hardened 2026-06-10 — "don't give away the
  roadmap"): the R4 import is a CURATED tree. Public repo `.gitignore`s
  `.k2so/` AND `.k2/` wholesale (agents, PRDs, inbox, notes, skills).
  `docs/` is curated: user-facing docs only — the design-review HTMLs
  (e.g. final-creature-comforts-review.html), research notes
  (terminal-scrolling-research.md), and any roadmap-bearing material
  stay internal (private mirror). Also exclude stray working files
  (build logs, .harness-fanout-enabled). Import checklist runs a final
  `git ls-files | grep -iE 'prd|roadmap|review|research'` sweep before
  the first public push. Honest-shift framing stays: README presents
  the K2SO→K2 transition and MIT history openly; we just don't publish
  strategy docs.
- CONTRIBUTING.md with DCO sign-off (layer 5 of licensing strategy).
- **Lawyer-pass gate** on LICENSE/GRANT/TRADEMARKS before the first
  release is published here.
- 0.40.0 released on the NEW repo via updated release.sh.

**R5 — the cutover (one afternoon, ordered):**
0. ✅ DONE EARLY (2026-06-10): **private full backup exists** —
   `Alakazam-211/k2so-backup` mirrors all 210 tags + 9 branches + full
   history (main SHA verified identical). Release ASSETS intentionally
   stay on the shell repo (that's its job); the backup protects the git
   side before anything destructive. NEVER make it public (MIT-era
   source + internal PRDs). RE-SYNC the mirror immediately before
   executing the shell maneuver — commits keep landing on K2SO until
   then (one-liner: git clone --mirror … && git push --all/--tags).
1. 0.40.0 live + verified on new repo (fresh-install DMG path tested).
2. Publish on the OLD repo the final bridge release: `latest.json`
   (version 0.40.0, url → new-repo asset, same signing key) +
   `daemon-latest.json` equivalents for the P3 headless self-update.
3. Verify an existing 0.39.x install auto-updates across repos cleanly
   (and a headless daemon self-updates).
4. Old repo: run the SHELL MANEUVER (§0.B — stub commit, tag force-move,
   branch deletion, retro-edited release notes), then **Archive (public,
   read-only)**. PRD scrub is subsumed — the stub removes the whole tree.
5. k2.dev: copy + download links + Fair Source page + hosting-grant page.

**R5.5 — trademark filing — DEFERRED (Rosson, 2026-06-10):** no USPTO
filing for now; registration costs money and the software has no revenue
yet. We roll on COMMON-LAW rights: TRADEMARKS.md asserts the composite
"K2 by Alakazam Labs" mark (™ posture, never ®), and the composite-only
usage discipline is the protection. Revisit when revenue starts — use in
commerce since 2026 strengthens a later application. Original plan kept
below for that day:

**R5.5 (original) — trademark filing (lawyer task, time with the 0.40.0 launch):**
file USPTO application(s) for the composite mark "K2 by Alakazam Labs"
(word mark + the logo). Intent-to-use filing is possible BEFORE launch;
use-based once 0.40.0 ships under the brand. Until registration: rely on
common-law rights from use in commerce, use ™ (never ®), keep the
composite mark consistently in commerce (README hero, About, DMG, site).
File the COMPOSITE + logo ONLY — never bare "K2" (Nintex Reg. 4869089,
Class 042, live + renewed; ~90-95% refusal on bare K2). Goods recital
VERBATIM (locked, Rosson): "agent server software — a server where AI
agents run" — explicitly NOT business-process orchestration. Required
per the analysis: 30-min likelihood-of-confusion consult BEFORE
app-store/marketing spend; also put to counsel: dock/menu showing bare
"K2" with composite-branded chrome (About/DMG/site). The kimi-k2 §2(d)
memory is the full prior-art landscape to hand the attorney.

**R6 — aftermath:** close #613; claim @alakazamlabs/k2 (Q4); update
memories (project_vision "MIT" reference, taxonomy); monitor old-repo
traffic for stragglers; bridge manifest stays frozen forever.

## 4. "Nobody gets stuck" guarantees (the worry, answered)

- Anyone on **0.39.x**: their app polls the old manifest forever; the
  bridge manifest hands them 0.40.0 from the new repo whenever they
  update — months or years later. Works because old repo = archived
  PUBLIC.
- Anyone wanting an **old version**: every historical release/DMG stays
  downloadable on the archived repo.
- **Headless daemons** (P3 self-update): same bridge treatment via
  daemon-latest.json.
- Anyone offline through the whole era: fresh DMG from k2.dev/new repo;
  0.40.0's first-boot migration handles their ~/.k2so data regardless of
  which version it came from.

## 5. Decisions — ANSWERED (Rosson, 2026-06-10) + verification results

1. **Internal IDs: YES `dev.k2.*`** — bundle `dev.k2.app`, launchd
   `dev.k2.daemon`/`dev.k2.heartbeat`/`dev.k2.claude-auth`, keychain
   `dev.k2.*`.
2. **`.k2so/` workspace dirs: DUAL-COMPATIBLE in 0.40** — `.k2/` preferred
   when present, `.k2so/` fully works; user-facing deprecation notice
   (release notes + docs + gentle CLI note) that `.k2so/` phases out and
   everything migrates under `.k2/` BEFORE 1.0.0.
3. **Entities:** Alakazam Labs OWNS the IP (© lines = Alakazam Labs);
   LZTEK, LLC hosts/operates K2 Connect AS A SERVICE for Alakazam Labs
   (grant wording: "operated by or on behalf of Alakazam Labs").
4. **npm: claim BOTH** `@alakazamlabs/k2` and `@lztek/k2` (org already has
   @lztek/k2so). BLOCKED on npm auth — token stale (E401); needs
   interactive `npm login`, then publish placeholders.
5. **Old repo: GREENLIT for the shell maneuver + archive** at R5.
   Destructive step deliberately HELD until after 0.40.0 + bridge exist
   (it's our active dev repo until then).

**LICENSE GREENLIT** (lawyer OK per Rosson): DRAFT banners removed from
GRANT + TRADEMARKS on Alakazam-211/K2; final wording tweaks applied
(on-behalf-of operator language; MIT-era note).

**Versioning:** rebrand ships as **0.40.0**; **1.0.0** comes later, after
post-rebrand stabilization + remaining polish (incl. the `.k2so/`→`.k2/`
workspace-dir migration completing pre-1.0.0).

**SHELL MANEUVER VERIFIED (2026-06-10, sacrificial repo):** after tag
force-move to an orphan stub + force-push: release stayed published (not
drafted), `releases/latest/download/<asset>` served anonymously (200,
correct bytes), tag-pinned download path served, auto source-zip
regenerated FROM THE STUB, and the original commit was not even fetchable
by SHA immediately. The earlier 404 was visibility-flip propagation only.
Gate: PASSED — R5 §0.B is safe to execute when its time comes.
(Test repo `shell-maneuver-test` set back to private; delete needs
`gh auth refresh -s delete_repo` or the web UI.)

