Files
memind/docs/mindspace-seamless-migration-runbook.md

328 lines
11 KiB
Markdown

# MindSpace Seamless Migration Runbook
## Scope
This runbook defines the no-loss migration path for extracting MindSpace from the Memind monolith.
Current production status:
- 103 already runs standalone MindSpace Service from `/Users/john/MindSpace`.
- The service is `cn.tkmind.mindspace-service` on `127.0.0.1:8082`.
- Portal live root remains `/Users/john/Project/Memind`.
- `/Users/john/Project/Memind/MindSpace` is legacy compatibility/storage context only, not the current MindSpace Service root.
Historical/local Phase A notes remain below for implementation context. For current 103 production truth, use [103 runtime topology](./103-runtime-topology.md).
## Invariants
- Existing Memind local behavior remains the baseline.
- `local` and `remote` adapter modes must stay switchable through env only.
- User-facing functionality must not regress when `remote` points to the local standalone service.
- Production release rules stay unchanged: merge to `main`, pass `bash scripts/check-release-ready.sh`, release from verified `main`.
## Phase A Goal
Run MindSpace as a standalone local service while Memind uses `MINDSPACE_SERVER_ADAPTER=remote`, with no intentional feature loss versus the current local adapter path.
Phase A is complete when:
- standalone MindSpace service uses `/Users/john/MindSpace` as the production service root on 103
- Memind can use `MINDSPACE_SERVER_ADAPTER=remote` against the standalone service
- `npm run verify:phase-a-local` passes for a real user with existing data
- Memind remote-mode HTTP page list, page create, and page delete pass through the standalone service
- temporary verification data and login sessions are cleaned up
- remaining Memind-local responsibilities are documented instead of hidden
## Current data-root policy
- Production standalone service root on 103: `/Users/john/MindSpace`
- Old `/Users/john/Project/Memind/MindSpace` paths are migration source, rollback source, or legacy compatibility only
- Old Memind directories are treated as migration source and rollback source
- Data-root migration is executed by script, not by ad hoc manual copying
## Phase A Components
### Memind
- Shared adapter contract
- Local and remote adapter selection
- Remote transport with auth token, timeout, and configurable operation path
- Remote mode skips Memind-side generated-page workspace sync; background jobs stay on the standalone MindSpace runtime
### Standalone MindSpace service
Path:
- `/Users/john/MindSpace` on 103 production
Responsibilities:
- bootstrap DB-backed local MindSpace services
- expose `POST /mindspace/v1/adapter/:binding/:method`
- expose `/health` and `/mindspace/v1/contract`
- manage publication cleanup
- manage optional workspace maintenance
- manage optional agent worker
- read existing session snapshots for conversation-package public-html hydration
### Standalone data-root overrides
Use these when you intentionally want a runtime root other than the production default `/Users/john/MindSpace`:
- `MINDSPACE_SERVICE_H5_ROOT`
- `MINDSPACE_STORAGE_ROOT`
- `H5_USERS_ROOT`
## Start Order
### 1. Start standalone MindSpace service
```bash
cd /Users/john/MindSpace
npm run migrate:data-root -- --yes
MINDSPACE_MEMIND_ROOT=../Memind \
MINDSPACE_REMOTE_AUTH_TOKEN=local-dev-token \
MINDSPACE_SERVICE_PORT=19081 \
MINDSPACE_SERVICE_AGENT_WORKER_ENABLED=true \
node server.mjs
```
### 1b. Start standalone service against a new data root
```bash
cd /Users/john/MindSpace
MINDSPACE_MEMIND_ROOT=/Users/john/Project/Memind \
MINDSPACE_SERVICE_H5_ROOT=/Users/john/MindSpace \
MINDSPACE_STORAGE_ROOT=/Users/john/MindSpace/data/mindspace \
H5_USERS_ROOT=/Users/john/MindSpace/users \
MINDSPACE_REMOTE_AUTH_TOKEN=local-dev-token \
MINDSPACE_SERVICE_PORT=19081 \
MINDSPACE_SERVICE_AGENT_WORKER_ENABLED=true \
node server.mjs
```
### 2. Point Memind at the standalone service
```bash
export MINDSPACE_SERVER_ADAPTER=remote
export MINDSPACE_REMOTE_BASE_URL=http://127.0.0.1:19081
export MINDSPACE_REMOTE_AUTH_TOKEN=local-dev-token
```
### 3. Start Memind normally
Use the standard local startup flow already used in this repo.
## Validation
### Phase A local gate
```bash
cd /Users/john/MindSpace
MINDSPACE_LOOPBACK_USER_ID=<user-id> \
MINDSPACE_REMOTE_BASE_URL=http://127.0.0.1:19081 \
MINDSPACE_REMOTE_AUTH_TOKEN=local-dev-token \
npm run verify:phase-a-local
```
Expected result:
- standalone service is healthy, either reused if already running or started by the verifier
- RPC unit tests pass
- infra smoke, read parity, page write parity, asset upload parity, and conversation package parity all pass
- Memind remote-mode HTTP page list, page create, and page delete pass
- final read parity still reports no drift after write-path validation
- any service started by the verifier is stopped before exit
Current verified local user:
- `1c99b83b-0454-474f-a5d2-129d34506a32`
Latest verified totals from the Phase A gate:
- pages: `302 / 302`
- assets: `100 / 100`
- jobs: `0 / 0`
- drift counters: `onlyLocal = 0`, `onlyRemote = 0`, `changed = 0`
### Memind remote-mode HTTP gate
```bash
cd /Users/john/MindSpace
MINDSPACE_LOOPBACK_USER_ID=<user-id> \
MINDSPACE_REMOTE_BASE_URL=http://127.0.0.1:19081 \
MEMIND_REMOTE_MODE_BASE_URL=http://127.0.0.1:18082 \
MINDSPACE_REMOTE_AUTH_TOKEN=local-dev-token \
npm run verify:memind-remote-mode
```
Expected result:
- standalone MindSpace service is healthy
- Memind starts with `MINDSPACE_SERVER_ADAPTER=remote`
- a short-lived local login session can access Memind `/auth/status`
- Memind HTTP page list, page create, and page delete succeed through the remote adapter
- temporary login session is revoked and temporary page is deleted before exit
### Infra smoke
```bash
cd /Users/john/MindSpace
node scripts/loopback-smoke.mjs
```
### User-scoped smoke
```bash
cd /Users/john/MindSpace
MINDSPACE_LOOPBACK_USER_ID=<user-id> \
MINDSPACE_REMOTE_AUTH_TOKEN=local-dev-token \
node scripts/loopback-smoke.mjs
```
Expected result:
- `asset count`, `page count`, `job count` return real values for a user with existing MindSpace data
- empty collections are acceptable only when the chosen user truly has no stored data
### Local vs remote comparison
```bash
cd /Users/john/MindSpace
MINDSPACE_LOOPBACK_USER_ID=<user-id> \
MINDSPACE_REMOTE_BASE_URL=http://127.0.0.1:19081 \
node scripts/compare-local-remote.mjs
```
Expected result:
- page totals match
- asset totals match
- job totals match
- `onlyLocal`, `onlyRemote`, `changed` all stay `0` for stable read surfaces
### Write-path parity
```bash
cd /Users/john/MindSpace
MINDSPACE_LOOPBACK_USER_ID=<user-id> \
MINDSPACE_REMOTE_BASE_URL=http://127.0.0.1:19081 \
node scripts/compare-write-local-remote.mjs
```
Expected result:
- temporary local and remote pages are both created successfully
- `create -> publish -> offline -> delete` produces no semantic diff between local and remote comparisons
- temporary validation data is cleaned up before the script exits
### Asset upload parity
```bash
cd /Users/john/MindSpace
MINDSPACE_LOOPBACK_USER_ID=<user-id> \
MINDSPACE_REMOTE_BASE_URL=http://127.0.0.1:19081 \
node scripts/compare-asset-local-remote.mjs
```
Expected result:
- temporary local and remote text uploads both complete successfully
- `createUpload -> writeUploadContent -> completeUpload -> readAsset -> deleteAsset` produces no semantic diff
- temporary validation assets are deleted before the script exits
### Conversation package parity
```bash
cd /Users/john/MindSpace
MINDSPACE_LOOPBACK_USER_ID=<user-id> \
MINDSPACE_REMOTE_BASE_URL=http://127.0.0.1:19081 \
node scripts/compare-conversation-package-local-remote.mjs
```
Expected result:
- temporary local and remote packages are both created successfully
- object write, artifact registration, manifest write, manifest file contents, and prepare-read outputs produce no semantic diff
- temporary validation package rows and storage objects are removed before the script exits
### Manual UX validation
- asset list and upload
- page list and page render
- page publish and public page access
- agent job create, run, and completion
- conversation package read for sessions that already have snapshots
## Phase A Boundary Audit
The following MindSpace surfaces are now covered by the standalone service adapter and Phase A gate:
- page list/read/create/publish/offline/delete
- asset list/upload/write/complete/read/delete
- conversation package object write, artifact registration, manifest write, and prepare-read
- remote RPC transport including JSON-serialized `Buffer` arguments
- Memind HTTP page list/create/delete while `MINDSPACE_SERVER_ADAPTER=remote`
The following responsibilities intentionally remain Memind-local in Phase A:
- user auth, wallet/quota/category APIs, audit writes, and subscription integration still run in Memind
- public route HTTP serving is still mounted by Memind, although publication resolution and page rendering use MindSpace service APIs
- chat Finish public HTML materialization still writes to the Memind workspace path to preserve the verified `edit_file` regression guard
- chat-save preview/thumbnail flows still read workspace HTML from the Memind workspace path
- Goose/session workspace capability is still issued from Memind user auth and exposes the local workspace path plus `workspaceRef`
Remote-mode guardrails added during Phase A:
- Memind remote mode no longer runs local generated-page workspace sync before page listing
- remote adapter background jobs stay on the standalone MindSpace runtime
- Phase A verification uses short-lived login sessions and revokes them before exit
Known Phase A residual risks:
- real browser UI coverage is still manual; the automated HTTP gate covers Memind API behavior, not a full browser session
- full agent job execution and Goose workspace writes are not yet a standalone-service-only contract
- complete production separation still needs process supervision, TLS/domain routing, monitoring, and deployment rollback work in later phases
## Rollback
If any remote-path issue appears locally:
```bash
unset MINDSPACE_SERVER_ADAPTER
unset MINDSPACE_REMOTE_BASE_URL
unset MINDSPACE_REMOTE_AUTH_TOKEN
```
Memind will fall back to the local adapter path.
## Remaining Phase A hardening
- add browser-level remote-mode smoke once UI automation credentials are available
- add a full agent job execution smoke that verifies workspace writes against the intended service runtime
- decide when chat Finish public HTML materialization moves from Memind to the standalone service
## Data migration outline
When you decide to move local data into the standalone root, use this order:
1. Stop local writes or switch Memind back to `local`
2. Run `npm run migrate:data-root -- --yes`
3. Start standalone service
4. Run
- `npm run smoke:loopback`
- `MINDSPACE_LOOPBACK_USER_ID=<user-id> npm run compare:local-remote`
- `MINDSPACE_LOOPBACK_USER_ID=<user-id> npm run compare:write-local-remote`
- `MINDSPACE_LOOPBACK_USER_ID=<user-id> npm run compare:asset-local-remote`
- `MINDSPACE_LOOPBACK_USER_ID=<user-id> npm run compare:conversation-package-local-remote`
- `MINDSPACE_LOOPBACK_USER_ID=<user-id> npm run verify:memind-remote-mode`
5. Only keep the new root if parity remains clean
Rollback:
- stop standalone service
- point Memind back to `local` or stop the standalone service
- if needed for rollback/compatibility, start standalone with an explicit legacy root; do not assume `/Users/john/Project/Memind/MindSpace` is the current production service root
- old Memind data root becomes active again immediately
## Deferred
- Phase C `105` integration
- Phase D production cutover