Skip to content

Commit ea1688e

Browse files
committed
feat: add local portable archive CLI
1 parent aa42393 commit ea1688e

16 files changed

Lines changed: 1568 additions & 1 deletion

File tree

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
---
2+
title: Export and restore a portable archive
3+
description: Create, validate, and restore a verified PowerContext logical bundle.
4+
---
5+
6+
# Export and restore a portable archive
7+
8+
A portable archive is a `.pcb` file for moving or recovering complete PowerContext scopes. It is a logical archive:
9+
it preserves domain identities and immutable history rather than copying a SQLite file. Use it for a controlled local
10+
backup, an offline transfer, or a future backend migration.
11+
12+
This command is a local operator command. It opens the default SQLite database in the PowerContext user-data directory;
13+
it does not call a remote Server API. Run it only on a machine whose local PowerContext data you control.
14+
15+
## Prerequisites
16+
17+
Install the CLI from the same PowerContext revision that created the local data. The archive command uses the persistent
18+
SQLite database at `POWERCONTEXT_HOME/powercontext.db`; without `POWERCONTEXT_HOME`, PowerContext uses its operating
19+
system user-data directory.
20+
21+
```bash
22+
uv tool install "powercontext[cli] @ git+https://github.com/oceanbase/powercontext.git@master"
23+
export POWERCONTEXT_HOME="$HOME/.local/share/powercontext"
24+
```
25+
26+
The archive contains content and metadata needed for recovery. Store it in a protected location with access controls
27+
and retention appropriate for the underlying project data. The format deliberately omits credentials and configured
28+
provider secrets, but it does not encrypt the project content.
29+
30+
## Create and inspect an archive
31+
32+
Pass every complete scope to include. A scope cannot be selected by prefix or partially by record type.
33+
34+
```bash
35+
powercontext archive export \
36+
--scope-id project:payments \
37+
--output ./backups/payments.pcb
38+
39+
powercontext archive inspect ./backups/payments.pcb
40+
```
41+
42+
`export` writes JSON containing the bundle ID, record count, and checksum. `inspect` verifies the ZIP structure,
43+
per-record digests, total digest, record counts, and selected scopes without opening the target database. Keep the
44+
reported checksum with the backup inventory if an external backup system needs an independent verification record.
45+
46+
## Validate before a restore
47+
48+
Always validate the archive against the destination first:
49+
50+
```bash
51+
powercontext archive restore ./backups/payments.pcb --dry-run
52+
```
53+
54+
Dry-run performs no domain writes. It verifies checksums, required source and Artifact dependencies, and whether the
55+
configured Runtime can restore the archive's source types and Artifact families. A validation failure exits with code
56+
`2` and reports only a content-free reason; record bodies are not printed.
57+
58+
To perform the write, repeat the command with explicit confirmation:
59+
60+
```bash
61+
powercontext archive restore ./backups/payments.pcb --yes
62+
```
63+
64+
The result is JSON with `inserted`, `already_present`, and `projections_ready`. Treat the restore as ready for search
65+
only when `projections_ready` is `true`. The Runtime rebuilds portable Memory and Experience search projections after
66+
the authoritative rows have been restored.
67+
68+
## What the bundle preserves
69+
70+
Format version 1 carries the portable relational representation of these supported records:
71+
72+
| Preserved | Not portable |
73+
| --- | --- |
74+
| Source journal heads and Source records | Search projections and indexes |
75+
| Artifact Revisions, lineage, and heads | Source cursors and scheduler state |
76+
| Memory entry versions and heads | External Skill registrations and host-local installation state |
77+
| Candidate versions, decision heads, and their evidence references | Usage statistics, credentials, bearer tokens, and provider secrets |
78+
79+
The archive has a versioned manifest (`format_version`, producer version, scopes, counts, exclusions, and total
80+
checksum) plus NDJSON records. It is the authoritative round-trip format. CSV may be produced separately for bounded
81+
analysis, but it cannot preserve immutable revisions, lineage, or evidence references and must not be used for restore.
82+
83+
## Recovery and conflicts
84+
85+
Restore is idempotent. Replaying the same archive recognizes identical records as `already_present`. A different
86+
payload for an existing immutable identity never overwrites it: restore exits with code `3` and leaves the write
87+
transaction rolled back. Resolve the conflicting target data or choose a clean destination, then run the same restore
88+
command again.
89+
90+
If the command is interrupted before completion, do not claim recovery succeeded. Authoritative records are
91+
transactionally applied, so a failed write does not leave a successful-looking partial restore. Re-run the same archive
92+
against the same destination after the previous command has stopped.
93+
94+
## Current boundaries
95+
96+
Export streams database rows to a temporary NDJSON file. Validation stores only record identities in a temporary
97+
on-disk index, and restore replays dependency levels as streams, so aggregate archive payloads are not retained in
98+
process memory. The local CLI always opens the default SQLite database under `POWERCONTEXT_HOME` (or the operating
99+
system user-data directory); it is not a remote Server API and does not use Server authentication or non-SQLite
100+
database settings. For a live production database, use the database provider's coordinated backup procedures.

‎docs/en/docs/index.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ overview:
4848
- title: Create a managed Skill
4949
description: Generate and review a managed Skill, then export one exact Revision to Codex.
5050
href: en/docs/how-to/create-and-export-skill/
51+
- title: Portable archive
52+
description: Create a verified local logical backup, validate it, and restore complete scopes.
53+
href: en/docs/how-to/portable-archive/
5154
- title: Troubleshoot
5255
description: Diagnose connection, configuration, and integration problems.
5356
href: en/docs/how-to/troubleshoot/
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
---
2+
title: 导出和恢复可移植归档
3+
description: 创建、验证并恢复经过校验的 PowerContext 逻辑归档。
4+
---
5+
6+
# 导出和恢复可移植归档
7+
8+
可移植归档是用于迁移或恢复完整 PowerContext scope 的 `.pcb` 文件。它是逻辑归档:保存领域 identity 和不可变历史,
9+
而不是复制 SQLite 文件。它适用于受控的本地备份、离线传输,以及未来的后端迁移。
10+
11+
这是一个本地运维命令。它直接打开 PowerContext 用户数据目录中的默认 SQLite 数据库,不调用远程 Server API。只应在
12+
你能够控制本机 PowerContext 数据的环境中运行。
13+
14+
## 前提条件
15+
16+
从创建本地数据的同一个 PowerContext revision 安装 CLI。归档命令使用
17+
`POWERCONTEXT_HOME/powercontext.db` 中持久化的 SQLite 数据库;未设置 `POWERCONTEXT_HOME` 时,PowerContext
18+
会使用操作系统用户数据目录。
19+
20+
```bash
21+
uv tool install "powercontext[cli] @ git+https://github.com/oceanbase/powercontext.git@master"
22+
export POWERCONTEXT_HOME="$HOME/.local/share/powercontext"
23+
```
24+
25+
归档包含恢复所需的内容和元数据。应按项目数据的访问控制和保留要求,将它放在受保护的位置。格式会排除凭据和已配置的
26+
provider secret,但不会加密项目内容。
27+
28+
## 创建并检查归档
29+
30+
传入每一个需要包含的完整 scope。不能用前缀选择 scope,也不能只导出某一种 record。
31+
32+
```bash
33+
powercontext archive export \
34+
--scope-id project:payments \
35+
--output ./backups/payments.pcb
36+
37+
powercontext archive inspect ./backups/payments.pcb
38+
```
39+
40+
`export` 会输出 JSON,其中包括 bundle ID、record 数和 checksum。`inspect` 不打开目标数据库,只校验 ZIP 结构、
41+
单 record digest、总 digest、record 数和所选 scope。若外部备份系统需要独立校验记录,请把输出的 checksum 一并保存。
42+
43+
## 在恢复前验证
44+
45+
恢复前始终先针对目标环境验证:
46+
47+
```bash
48+
powercontext archive restore ./backups/payments.pcb --dry-run
49+
```
50+
51+
dry-run 不会写入领域数据。它会校验 checksum、必需的 Source 和 Artifact 依赖,以及已配置 Runtime 是否支持归档中的
52+
source type 和 Artifact family。验证失败会以退出码 `2` 结束,只输出不含内容的原因,不会打印 record body。
53+
54+
要执行写恢复,必须显式确认:
55+
56+
```bash
57+
powercontext archive restore ./backups/payments.pcb --yes
58+
```
59+
60+
结果为 JSON,包含 `inserted`、`already_present` 和 `projections_ready`。只有 `projections_ready` 为 `true`
61+
时才能宣称搜索已就绪。Runtime 会在恢复权威数据后重建可移植的 Memory 和 Experience 搜索 projection。
62+
63+
## 归档保留的内容
64+
65+
格式版本 1 支持以下可移植关系记录:
66+
67+
| 会保留 | 不可移植 |
68+
| --- | --- |
69+
| Source journal head 和 Source record | 搜索 projection 和 index |
70+
| Artifact Revision、lineage 和 head | Source cursor 和 scheduler state |
71+
| Memory entry version 和 head | External Skill registration 和 host-local installation state |
72+
| Candidate version、decision head 及其 evidence reference | Usage statistic、credential、bearer token 和 provider secret |
73+
74+
归档包含带版本的 manifest(`format_version`、producer version、scope、数量、排除项和总 checksum)以及 NDJSON record。
75+
它是权威的 round-trip 格式。CSV 可以单独用于有边界的分析,但无法保留不可变 revision、lineage 或 evidence reference,
76+
不得用于恢复。
77+
78+
## 恢复和冲突处理
79+
80+
恢复是幂等的。重复回放同一归档时,内容相同的 record 会计入 `already_present`。已有不可变 identity 对应不同 payload
81+
时,恢复绝不会覆盖它:命令以退出码 `3` 结束,并回滚本次写 transaction。解决目标数据冲突,或选择一个干净的目标后,
82+
再次运行同一个恢复命令。
83+
84+
如果命令在完成前中断,不能宣称恢复已成功。权威 record 会在 transaction 中写入;失败的写入不会留下看似成功的部分
85+
恢复。先确认上一次命令已经停止,再对同一目标重新运行同一个归档。
86+
87+
## 当前边界
88+
89+
导出会把数据库 row 流式写到临时 NDJSON 文件。验证只在临时磁盘 index 中保存 record identity,恢复则按依赖层流式
90+
回放,因此归档的聚合 payload 不会常驻进程内存。本地 CLI 始终打开 `POWERCONTEXT_HOME`(或操作系统用户数据目录)
91+
下的默认 SQLite 数据库;它不是远程 Server API,也不会读取 Server 认证或非 SQLite 数据库配置。生产数据库仍应使用
92+
数据库 provider 的协调备份流程。

‎docs/zh/docs/index.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ overview:
4848
- title: 创建 managed Skill
4949
description: 生成并审核 managed Skill,再将一个精确 Revision 导出给 Codex。
5050
href: zh/docs/how-to/create-and-export-skill/
51+
- title: 可移植归档
52+
description: 创建经过校验的本地逻辑备份,验证后恢复完整 scope。
53+
href: zh/docs/how-to/portable-archive/
5154
- title: 排查问题
5255
description: 诊断连接、配置和集成问题。
5356
href: zh/docs/how-to/troubleshoot/

‎pyproject.toml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ tracing-otlp = [
7272
]
7373
cli = [
7474
"platformdirs>=4,<5",
75+
"powercontext[builtin]",
7576
"powercontext[client]",
7677
"typer>=0.16,<1",
7778
]
@@ -83,6 +84,7 @@ powercontext = "powercontext.cli.app:main"
8384
doctor = "powercontext.cli.system:doctor_app"
8485
server = "powercontext.server.cli:app"
8586
setup = "powercontext.cli.system:setup_app"
87+
archive = "powercontext.cli.archive:archive_app"
8688

8789
[project.urls]
8890
Homepage = "https://github.com/oceanbase/powercontext"
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
"""Versioned logical export and restore for built-in relational data."""
2+
3+
from powercontext.builtin.portability.bundle import (
4+
BundleConflictError,
5+
BundleFormatError,
6+
BundleInspection,
7+
BundleReceipt,
8+
PortableBundleService,
9+
)
10+
11+
__all__ = [
12+
"BundleConflictError",
13+
"BundleFormatError",
14+
"BundleInspection",
15+
"BundleReceipt",
16+
"PortableBundleService",
17+
]

0 commit comments

Comments
 (0)