328 lines
11 KiB
Markdown
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
|