Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 55 additions & 35 deletions docs/en/docs/operate/managed-local-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,42 +91,62 @@ Preflight does not create a configuration file, data directory, or database.

## Database compatibility boundary

Database inventory does not construct a Server runtime, connect to SQLite, initialize tables, change WAL settings, or
apply migrations. It observes the selected file and recovery sidecars and binds that observation to the exact target
Server version. Ops' own package version cannot prove compatibility with the target Server.

Program-only repair binds the existing database's file identity and target version, allowing normal writes and WAL
checkpointing while resources are prepared. Replacing the database invalidates the plan. This repair observation does
not authorize startup; installation and startup retain strict database and recovery-sidecar observations.

| Observation | Installer behavior |
Passive inspection inventories the selected SQLite file and recovery sidecars without opening SQLite or starting a
target process. Existing files remain `existing_unknown` in ordinary status. Program-only repair binds the file
identity and target version, allows normal writes and WAL checkpointing during resource preparation, and completes
with the service stopped. Replacing the database invalidates its repair plan.

Operations that can start the managed service perform a separate admission check: `start`, `restart`, registration,
and configuration changes that actually restart an active service. Ops verifies the owned target resource against its
fixed manifest, then invokes that bundle's Server admission entry with isolated Python (`-I -B`). Windows uses the
manifest's console Python from the same bundle. The child checks its installed package version against the selected
Server version. An older target without this entry remains unsupported; the Ops package version or a previous
successful startup cannot replace target admission.

The target checks the complete Server schema and indexes, supported revision history, configured domains and
embedding profile, SQLite integrity, original-path maintenance evidence, and unfinished archive restores. It reads a
private copy of the main database and WAL, including committed data not yet checkpointed into main. The original
database is never opened by SQLite during admission; its SHM is neither copied nor changed, and no original sidecars
are created or removed. File identities and modification evidence must remain stable while copying and checking.
Admission performs no initialization, migration, restoration, model call, HTTP startup, or worker startup.

| Observation | Startup behavior |
| --- | --- |
| Database and SQLite recovery sidecars are absent | Classify as `new`; the approved target Server may initialize a new database during startup. |
| An existing SQLite file, including an empty file | Classify as `existing_unknown`; do not automatically start or restart against it. |
| An existing file has an unsupported database header | Classify as `incompatible`; preserve it and block startup. |
| Orphan sidecars, a linked or unverified location, an unreadable file, or a changing observation | Classify as `unknown`; preserve the files and block startup. |

The current public maintenance checks cover individual domains, not complete Server schema, indexes, persisted task
formats, and all configured capabilities. A Dream or processing check, an Atomic Memory verification, or a migration
bundle reporting `ready` therefore cannot lift the installer gate. A `pc_schema_revision` marker does not establish
whole-Server readiness. The installer does not create one for new databases.

For existing data without a qualified whole-database check for the fixed target version, keep the service stopped and
preserve the database. Same-version program repair can complete while the database remains `existing_unknown`; that
does not authorize startup. There is no general maintenance command that this installer can recommend to make every
such database compatible. Consult [Database migrations](database-migrations.md) for the actual supported bundle
boundary, and wait for a maintenance release supporting the specific database before attempting a data transition.
Do not repeatedly run a partial migration as an automatic repair.

This also limits normal operation today: after first startup creates a database, subsequent `start`, `restart`, and
`config_apply` with `restart=true` when it would restart an active service are rejected through the managed entry while
whole-database compatibility remains unknown. An already stopped service stays stopped during configuration changes,
including when `restart=true` is supplied. A previous successful startup or the installation manifest does not bypass
this gate. Inspection, stopping,
configuration changes without restart, and same-version program repair remain available. Repeating `install` for an
owned current installation only reports facts. This implementation therefore does not yet provide a complete daily
restart workflow; qualified whole-database checks are still required. The separate prepared-runtime operator binding
retains its existing contract and is not evidence that the managed database is compatible.
| Database and recovery evidence are absent | `new`; only the approved Server startup may initialize storage. |
| Existing storage passes the exact target's complete check | `existing_ready` for that explicit admission; same-version startup and restart require unchanged storage through apply. |
| Unknown schema, empty existing file, older layout, future revision, unsupported profile, or missing target helper | Block startup and preserve storage. |
| Interrupted maintenance/restore, rollback journal, active maintenance lock, orphan sidecars, unsafe location, or changing source | Block startup and preserve recovery evidence. |

A revision marker or a partial domain check is insufficient. Required migrations and recovery remain explicit
operator work under [Database migrations](database-migrations.md). `database_migration_required`,
`database_recovery_required`, and `database_configuration_mismatch` identify those boundaries;
`database_compatibility_unknown` means the exact target could not establish compatibility. Repair changes programs
only and does not remove these requirements.

Admission copies and hashes the complete main file and WAL, then scans the snapshot using Server validators. Each
preflight and apply revalidation repeats this work; it is not an incremental or cached check. The combined main/WAL
limit is **8 GiB**, the temporary filesystem needs their combined size plus **32 MiB** free, and copying plus target
validation has a **120-second** deadline. Oversize, insufficient space, and timeout return
`database_snapshot_too_large`, `database_snapshot_space_insufficient`, and `database_admission_timeout`. Recovery
journals are limited to 4 MiB each. Large or busy databases require an operator-controlled maintenance workflow;
raising a limit does not establish compatibility. Temporary copies are removed after the check.

Normal writes also invalidate approved database evidence. If the running Server keeps writing, or data changes
between preflight and apply, stop it through Ops, obtain a fresh `start` plan after writes have stopped, and approve
that plan. A rejected restart leaves the running service unchanged. Admission does not automatically stop writers or
relax the approved database identity; other processes writing the same database must also be quiescent.

A local macOS arm64 / CPython 3.12.15 measurement with 2,000 public Memory records, 4,000 revisions and a 168.4 MiB
SQLite main file took 3.78–3.86 seconds per admission across three runs; copying and hashing took 0.074–0.075 seconds.
Source hashes remained unchanged. This measurement excludes resource-manifest verification and native service
commands and does not qualify other machines, WAL sizes, or databases near the limit.

Apply repeats admission and compares the approved plan's database, configuration, target-resource and recovery
evidence. Changed evidence rejects the old plan before a service command. The running Server still owns its normal
startup checks. Inspection, stopping, registration removal, and stopped program repair remain available when the
target interpreter is damaged or absent. A stopped service stays stopped
when configuration changes request `restart=true`. The independent prepared-runtime operator binding retains its
existing contract.

## Startup and connection handoff

Expand Down
26 changes: 16 additions & 10 deletions docs/zh/docs/operate/managed-local-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,22 +57,28 @@ description: 安装或修复固定版本的个人 Server 运行环境,并保

## 数据库兼容边界

数据库检查不构造 Server runtime,不连接 SQLite,不初始化表、不修改 WAL 设置,也不执行迁移。它只观察选定文件及恢复侧文件,并将观察结果绑定到精确目标 Server 版本。Ops 自身的包版本不能证明目标 Server 的数据库兼容性。
普通检查只观察选定的 SQLite 文件及恢复侧文件,不打开 SQLite,也不启动目标进程;状态中的已有文件仍标记为 `existing_unknown`。只修复程序时,计划绑定数据库文件身份和目标版本,允许准备资源期间正常写入及 WAL checkpoint,修复完成后保持服务停止。替换数据库会使修复计划过期。

只修复程序时,计划绑定已有数据库的文件身份和目标版本,允许准备资源期间正常写入及 WAL checkpoint;替换数据库会使计划过期。这种修复观察不授予启动许可,安装和启动仍使用严格的数据库及恢复侧文件观察。
可能启动受管服务的操作会另外执行准入检查,包括 `start`、`restart`、服务注册,以及会实际重启运行中服务的配置修改。Ops 先按照固定清单核验自有目标资源,再使用该包中的隔离 Python(`-I -B`)调用 Server 准入入口。Windows 使用同一资源清单中的控制台 Python。子进程核对已安装包版本是否与选定的 Server 版本完全一致。缺少该入口的旧目标仍不受支持;Ops 自身版本和历史启动成功都不能替代目标准入。

| 观察结果 | 安装器处理 |
目标检查完整 Server schema 与索引、受支持的版本历史、配置对应的领域和 Embedding profile、SQLite 完整性、原数据库身份对应的维护证据,以及未完成的归档恢复。检查读取主库和 WAL 的私有副本,包含尚未 checkpoint 到主库的已提交数据。准入期间 SQLite 不打开原库;不复制或改动原 SHM,也不创建或删除原侧文件。复制和检查期间,源文件身份和修改证据必须保持稳定。准入不初始化、迁移或恢复数据,不调用模型,也不启动 HTTP 或 worker。

| 观察结果 | 启动处理 |
| --- | --- |
| 数据库及 SQLite 恢复侧文件均不存在 | 分类为 `new`,确认后的目标 Server 可以在启动时初始化新库。 |
| 已有 SQLite 文件,包括空文件 | 分类为 `existing_unknown`,不自动启动或重启。 |
| 已有文件的数据库头不受支持 | 分类为 `incompatible`,保留文件并阻止启动。 |
| 孤立侧文件、链接或未核验位置、不可读文件、观察过程中发生变化 | 分类为 `unknown`,保留文件并阻止启动。 |
| 数据库及恢复证据均不存在 | `new`;只有确认后的 Server 启动可以初始化存储。 |
| 已有存储通过精确目标版本的完整检查 | 本次明确准入为 `existing_ready`;同版本启动和重启要求存储在 apply 前保持不变。 |
| 未知 schema、已有空文件、旧布局、未来版本、不支持的 profile 或缺少目标检查入口 | 阻止启动并保留存储。 |
| 未完成的维护或恢复、回滚日志、正在持有的维护锁、孤立侧文件、不安全路径或源文件发生变化 | 阻止启动并保留恢复证据。 |

版本标记或局部领域检查不能证明整库可用。所需迁移和恢复仍须按照[数据库迁移](database-migrations.md)显式执行。`database_migration_required`、`database_recovery_required` 和 `database_configuration_mismatch` 分别提示这些边界;`database_compatibility_unknown` 表示精确目标未能证明兼容性。程序修复不会取消这些要求。

准入复制并计算完整主库与 WAL 的摘要,再由 Server 验证器扫描副本。每次预检和 apply 重新核验都会重复这些工作,不是增量检查,也不复用缓存。主库与 WAL 合计上限为 **8 GiB**;临时文件系统需要其合计大小加 **32 MiB** 的可用空间;复制和目标验证共用 **120 秒**时限。超出大小、空间不足或超时分别返回 `database_snapshot_too_large`、`database_snapshot_space_insufficient`、`database_admission_timeout`。每个恢复日志上限为 4 MiB。大型或持续写入的数据库需要由操作者安排维护流程,单纯提高限制不能证明兼容。检查结束后删除临时副本。

当前公开维护检查只覆盖部分领域,不能证明完整 Server 的 schema、索引、持久任务格式及全部配置能力可用。Dream 或 processing 检查、Atomic Memory 验证、迁移 bundle 的 `ready` 都不能解除安装器的启动阻断。`pc_schema_revision` 标记也不代表整库可用,安装器不会为新库创建该标记。
正常业务写入也会使已批准的数据库证据过期。如果运行中的 Server 持续写入,或预检与 apply 之间数据发生变化,应先通过 Ops 停止服务,待写入停止后重新获取并批准 `start` 计划。被拒绝的重启不会改变正在运行的服务。准入不会自动停止写入方或放宽已批准的数据库身份;其他进程对同一数据库的写入也必须暂停。

已有数据缺少固定目标版本的合格整库检查时,应保持服务停止并保留数据库。同版本程序修复可以完成,而数据库继续标记为 `existing_unknown`;修好程序不授予启动许可。当前没有一条能让所有这类数据库变得兼容的通用维护命令。请参阅[数据库迁移](database-migrations.md)了解实际支持的 bundle 边界,并等待支持该数据库的维护版本后再执行数据转换。不要把反复执行局部迁移当成自动修复。
一次本地 macOS arm64 / CPython 3.12.15 测量使用公开 Memory 接口创建 2,000 条记录、4,000 个修订版本,SQLite 主库为 168.4 MiB。三次准入各耗时 3.78–3.86 秒,其中复制及计算摘要耗时 0.074–0.075 秒;源文件摘要保持不变。该测量不包含资源清单核验和原生服务命令,不能证明其他机器、WAL 大小或接近上限的数据库具有同样性能。

这也限制了当前的日常操作:首次启动创建数据库后,只要整库兼容性仍为未知,受管入口后续的 `start`、`restart`,以及会实际重启运行中服务的 `config_apply(restart=true)` 都会被拒绝。原本停止的服务在配置修改后仍保持停止,即使传入 `restart=true` 也不会启动。历史启动成功或安装清单不能绕过该检查。检查、停止、不重启的配置修改和同版本程序修复仍可执行。对自有当前安装重复执行 `install` 只返回事实。因此,这一实现尚不具备完整的日常重启流程,仍需补齐合格的整库检查。独立的已备妥 runtime 操作者绑定保留既有契约,也不能用它证明受管数据库兼容。
Apply 会重新执行准入,并比较获批计划中的数据库、配置、目标资源及恢复证据;证据变化会在派发服务命令前拒绝旧计划。实际 Server 启动仍执行自己的启动检查。即使目标解释器损坏或缺失,检查、停止、移除注册和保持停止的程序修复仍可使用。原本停止的服务在配置修改后仍保持停止,即使传入 `restart=true` 也不会启动。独立的已备妥 runtime 操作者绑定保留既有契约。

## 启动与连接交接

Expand Down
Loading
Loading