YaronKoresh/pakem
GitHub: YaronKoresh/pakem
pakem 是一个将源代码仓库序列化为可移植制品的打包系统,支持多种输出格式、增量差异、云存储及 LLM 索引集成。
Stars: 0 | Forks: 0
# pakem
`pakem` 是一个仓库打包系统,旨在将源代码树转换为可移植的制品,用于分析、索引、共享和恢复工作流。
它支持面向文档的输出(`xml`、`json`、`proto`)和二进制存档格式(`pakem`),并提供可选的压缩、可逆加密、分割输出、增量状态跟踪和差异报告功能。
## 目录
1. [使命与范围](#mission-and-scope)
2. [功能矩阵](#capability-matrix)
3. [系统架构](#system-architecture)
4. [数据流与控制流](#data-flow-and-control-flow)
5. [安装与运行环境](#installation-and-environment)
6. [CLI 参考](#cli-reference)
7. [输出格式与文件规范](#output-formats-and-file-specifications)
8. [状态、差异与恢复语义](#state-delta-and-restore-semantics)
9. [安全与信任模型](#security-and-trust-model)
10. [性能与可扩展性调优](#performance-and-scalability-tuning)
11. [验证与质量门禁](#validation-and-quality-gates)
12. [Python API 用法](#python-api-usage)
13. [运维手册](#operational-playbooks)
14. [故障排除](#troubleshooting)
15. [模块内部原理](#module-by-module-internals)
16. [贡献与发布工作流](#contributing-and-release-workflow)
17. [术语表](#glossary)
18. [许可证](#license)
## 使命与范围
`pakem` 的存在是为了很好地解决一个问题:
- 确定性地扫描仓库。
- 分析文本源代码文件。
- 序列化规范化的元数据和内容。
- 可选地跟踪历史状态,以进行面向差异的操作。
- 可选地生成二进制制品,以便日后恢复。
### 主要用例
| 用例 | 输入 | 输出 | 典型消费者 |
|---|---|---|---|
| LLM 上下文打包 | 源代码仓库 | XML/JSON/Proto/LLM Prompt | Prompt pipeline、RAG 预处理器 |
| 增量仓库快照 | 源代码 + 状态文件 | XML/JSON/Proto/Pakem + 更新后的状态 | CI 和定时任务 |
| 仅变更制品生成 | 源代码 + 先前状态 + `--delta` | 差异子集 + diff 清单 | 审查与同步自动化 |
| 归档和恢复工作流 | 源代码 | `.pakem`(单文件或分割文件) | 备份、传输、迁移 |
| 归档间变更分析 | 两个制品 | 新增/修改/删除报告 | 回归分类和发布验证 |
| 云端制品传输 | 本地源代码 + 云 URI(`s3://`、`gs://`、`az://`) | 通过对象存储读写制品 | 远程备份和 pipeline 自动化 |
| 归档检查与报告 | 现有制品 | TUI/纯文本浏览器和 HTML 差异报告 | 发布工程和审计 |
| 生态系统加载器 | 现有制品 | LangChain 文档 / LlamaIndex 节点 | RAG 和索引服务 |
| 忽略规则诊断 | 源代码 + 忽略模式/文件 | 打印被忽略的列表 | 构建工程和 DevEx |
## 功能矩阵
| 功能 | xml | json | proto | pakem | llm-prompt |
|---|---:|---:|---:|---:|---:|
| 完整仓库元数据 | 是 | 是 | 是 | 是 |
| 文件行级内容 | 是 | 是 | 是 | 打包的 payload | 结构化 prompt 块 |
| 增量状态跟踪(`--state`) | 是 | 是 | 是 | 是 |
| 差异模式(`--delta`) | 是 | 是 | 是 | 是 |
| Diff 清单输出(`diff --diff-out`) | 是 | 是 | 是 | 是 |
| HTML 差异报告(`--html-diff-out` / `archive-diff --html-out`) | 是 | 是 | 是 | 是 |
| 可选压缩(`--compress zlib/zstd/lz4`) | 否 | 否 | 否 | 是 |
| 可选可逆加密(`--encrypt-key`) | 否 | 否 | 否 | 是 |
| 可选分割输出(`--split-size`) | 否 | 否 | 否 | 是 |
| 块级去重(`--dedup-chunks`) | 否 | 否 | 否 | 是 |
| 恢复支持(`restore`) | 否 | 否 | 否 | 是 | 否 |
| 语义分块(`--semantic-chunking`) | 是 | 是 | 是 | 是 | 是 |
| Git 跟踪文件模式(`--tracked-files`) | 是 | 是 | 是 | 是 | 是 |
| 分布式分片过滤(`--distributed-shards` + `--distributed-index`) | 是 | 是 | 是 | 是 | 是 |
| 分析缓存模式(`--cache-mode`) | 是 | 是 | 是 | 是 | 是 |
| 云 URI 输出/输入(`s3://`、`gs://`、`az://`) | 是 | 是 | 是 | 是 | 是 |
## 系统架构
### 高层模块拓扑
```
flowchart TB
CLI[cli.py] --> CMD[commands.py]
CMD --> PACKER[packer.py]
PACKER --> FS[fs.py]
PACKER --> ANALYZE[analyze.py]
PACKER --> STATE[state.py]
PACKER --> SERIALIZE[serialize.py]
PACKER --> VALIDATE[validation.py]
ANALYZE --> TOKEN[tokenizer.py]
FS --> IGNORE[ignore.py]
```
### 命令分发模型
```
flowchart LR
A[argv] --> B{normalize argv}
B -->|no subcommand| C[prepend pack]
B -->|has subcommand| D[keep argv]
C --> E[argparse subparsers]
D --> E[argparse subparsers]
E --> F{command}
F -->|pack| G[PackCommand.execute]
F -->|diff| H[DiffCommand.execute]
F -->|restore| I[RestoreCommand.execute]
F -->|archive-diff| J[ArchiveDiffCommand.execute]
F -->|explore| K[ExploreCommand.execute]
F -->|setup-precommit| L[SetupPrecommitCommand.execute]
```
### 打包执行 Pipeline
```
flowchart TD
START[RepoPacker.pack] --> SR[start_repository]
SR --> WALK[walk file tree]
WALK --> FILTER[ignore + binary filter]
FILTER --> ANALYSIS[parallel analyze_entry]
ANALYSIS --> STATEUPD[update current state]
STATEUPD --> SERIAL[serializer.add_file]
SERIAL --> PAYLOAD[optional pakem payload transforms]
PAYLOAD --> ENDREP[end_repository]
ENDREP --> TOTALS[update totals]
TOTALS --> WRITE[serializer.write_to]
WRITE --> SAVE[state save if configured]
SAVE --> DONE[exit code 0]
```
## 数据流与控制流
### pack 命令数据契约
| 阶段 | 输入 | 输出 | 不变量 |
|---|---|---|---|
| 参数解析 | CLI 选项 | `Namespace` | 子命令为 `pack`、`diff`、`restore`、`archive-diff`、`explore`、`setup-precommit` 之一 |
| 输出路径解析 | `--out`、`--format` | 具体文件路径或云 URI | 如果 `--out` 没有后缀,则根据格式推断后缀 |
| 文件遍历 | 根目录 + 忽略规则 | `FileEntry` 流 | 相对路径规范化为 `/` |
| 文本分析 | 文件路径 | `FileMetadata` + 内容行 | 跳过二进制文件 |
| 状态更新 | 先前状态 + 文件哈希 | 当前状态 | 每个处理过的文本文件都会获得确定性的状态条目 |
| 序列化 | 元数据 + 行 | 格式制品 | 仓库总计在末尾更新 |
### restore 命令数据契约
| 阶段 | 输入 | 输出 | 不变量 |
|---|---|---|---|
| 制品读取 | `.pakem` 或分割部分 | bytes | Header 必须以 `PAKM` 开头 |
| Header 解析 | 制品字节 | 元数据 JSON + payload 字节 | 版本字节必须受协商元数据支持 |
| 块重建 | payload 流 + 每个文件的长度 | 文件字节 | 转换逆转是转换顺序的逆操作 |
| 写入阶段 | `target_dir` + 相对路径 | 恢复的文件 | 拒绝目标之外的路径遍历 |
## 安装与运行环境
### 最小化安装
```
pip install pakem
```
### 开发安装
```
git clone https://github.com/YaronKoresh/pakem.git
cd pakem
pip install -e ".[dev]"
```
### 可选附加项
根据需要安装可选附加项:
```
pip install -e ".[extra]"
```
当前包含的附加项:
| 包 | 启用功能 |
|---|---|
| `pathspec` | 高级 gitignore 风格模式匹配 |
| `tiktoken` | 感知模型的 token 计数 |
| `protobuf` | Proto 序列化器支持 |
| `dulwich` | Git 原生跟踪文件和元数据丰富 |
| `zstandard` | zstd 压缩配置 |
| `lz4` | lz4 压缩配置 |
| `fsspec` + 云 FS 插件(`s3fs`、`gcsfs`、`adlfs`) | 制品和报告的云 URI 读写 |
| `langchain` | LangChain 加载器适配器 |
| `llama-index` | LlamaIndex 读取器适配器 |
### 运行时要求
| 要求 | 值 |
|---|---|
| Python | `>=3.10` |
| 项目版本 | `2.0.0` |
| 入口点 | `pakem = pakem.cli:main` |
## CLI 参考
## 全局调用形式
```
pakem [options]
python -m pakem [options]
```
如果未提供子命令,则隐式使用 `pack`。
## `pack` 命令
```
pakem pack [--path PATH] [--out OUT] [--format {xml,json,proto,pakem,llm-prompt}]
```
### `pack` 选项表
| 选项 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| `--path` | string | `.` | 要处理的根目录 |
| `--out` | string | `repo` | 输出路径或基础名称 |
| `--ignore` | list[string] | 无 | 额外的忽略模式 |
| `--include` | list[string] | 无 | 允许列表模式;仅考虑匹配的路径 |
| `--tracked-files` | flag | `false` | 仅包含 git 索引中跟踪的文件 |
| `--git-metadata` | flag | `false` | 使用提交哈希/作者/日期丰富文件元数据 |
| `--semantic-chunking` | flag | `false` | 在渲染文件内容时保留类/函数边界 |
| `--summary-mode` | enum | `off` | 可选的低优先级摘要模式 |
| `--plugin` | list[string] | 无 | 执行前加载的可选插件模块路径 |
| `--cache-mode` | enum | `off` | 分析缓存模式 |
| `--dedup-chunks` | flag | `false` | 为 pakem payload 启用块级去重 |
| `--distributed-shards` | int | 无 | 分布式打包的分片总数 |
| `--distributed-index` | int | 无 | 本次运行的从零开始的分片索引 |
| `--ignore-file` | string | 无 | 额外忽略文件的路径 |
| `--state` | string | 无 | JSON 状态文件路径 |
| `--delta` | flag | `false` | 仅包含更改的文件 |
| `--max-file-size` | size | 无 | 跳过大于此阈值的文件(`512KB`、`10MB`、`1GB`) |
| `--max-total-tokens` | int | 无 | 限制所选文件的打包 token 总数 |
| `--dry-run` | flag | `false` | 分析并报告,而不写入包/状态/报告文件 |
| `--focus-ranking` | enum | `basic` | token 预算受限时使用的排名策略 |
| `--list-ignored` | flag | `false` | 打印被忽略的条目并退出 |
| `--model` | string | 无 | 分词模型提示 |
| `--workers` | int | auto | 分析工作线程数(正整数) |
| `--format` | enum | `xml` | 输出格式 |
| `--emit-schema` | string | 无 | Schema 输出路径 |
| `--schema-format` | enum | `xml` | Schema 格式 |
| `--compress` | enum | `none` | pakem payload 压缩 |
| `--encrypt-key` | string | 无 | pakem 可逆密钥 |
| `--cipher` | enum | `aes-gcm` | 用于 pakem payload 加密的加密配置 |
| `--sign-key` | string | 无 | 可选的来源签名密钥(`hmac-sha256`) |
| `--split-size` | size | 无 | pakem 分割阈值(`1MB`、`512KB`、`2GB`) |
| `--sensitive-data-policy` | enum | `off` | 敏感数据处理模式 |
| `--secret-scanner` | enum | `builtin` | 密钥扫描器集成模式(`builtin`/`gitleaks`/`trufflehog`/`auto`/`off`) |
| `--sensitive-report-out` | string | 无 | 针对敏感数据发现的可选 JSON 报告输出 |
| `--selection-report-out` | string | 无 | 包含已选和已跳过路径的可选 JSON 报告 |
### `pack` 示例
```
# 在当前目录中默认打包(隐式 .xml 后缀)
pakem pack
# 显式格式及自动扩展名
pakem pack --path ./repo --format json --out snapshot
# 使用 state file 的 Delta pack
pakem pack --path ./repo --state .pakem-state.json --delta --out delta-report
# 带有 include allowlist 和 token budget 的定向打包
pakem pack --path ./repo --include "src/**" --max-total-tokens 20000 --focus-ranking basic --out focused
# 仅执行 Analysis-only pass,不写入 artifact
pakem pack --path ./repo --dry-run --max-file-size 1048576
# 带有 payload transforms 和 splitting 的 pakem archive
pakem pack --path ./repo --format pakem --compress zlib --encrypt-key key123 --split-size 1048576 --out archive
# 带有 semantic chunking 的 LLM prompt profile
pakem pack --path ./repo --format llm-prompt --semantic-chunking --summary-mode basic --out prompt
```
## `diff` 命令
```
pakem diff --state STATE [--path PATH] [--out OUT] [--diff-out FILE]
```
### `diff` 选项表
| 选项 | 类型 | 必需 | 描述 |
|---|---|---:|---|
| `--state` | string | 是 | 要进行比较的现有状态文件 |
| `--path` | string | 否 | 根目录(默认 `.`) |
| `--out` | string | 否 | 制品输出基础名称/路径 |
| `--diff-out` | string | 否 | JSON diff 清单输出路径 |
| `--html-diff-out` | string | 否 | HTML diff 报告输出路径 |
| `--ignore` | list[string] | 否 额外的忽略模式 |
| `--include` | list[string] | 否 | 允许列表模式;仅考虑匹配的路径 |
| `--tracked-files` | flag | 否 | 仅包含 git 索引中跟踪的文件 |
| `--git-metadata` | flag | 否 | 使用提交哈希/作者/日期丰富文件元数据 |
| `--semantic-chunking` | flag | 否 | 在渲染文件内容时保留类/函数边界 |
| `--summary-mode` | enum | 否 | 可选的低优先级摘要模式 |
| `--plugin` | list[string] | 否 | 执行前加载的可选插件模块路径 |
| `--cache-mode` | enum | 否 | 分析缓存模式 |
| `--dedup-chunks` | flag | 否 | 为 pakem payload 启用块级去重 |
| `--distributed-shards` | int | 否 | 分布式打包的分片总数 |
| `--distributed-index` | int | 否 | 本次运行的从零开始的分片索引 |
| `--ignore-file` | string | 否 | 额外的忽略文件 |
| `--format` | enum | 否 | 输出格式 |
| `--max-file-size` | size | 否 | 跳过大于此阈值的文件(`512KB`、`10MB`、`1GB`) |
| `--max-total-tokens` | int | 否 | 限制所选文件的打包 token 总数 |
| `--dry-run` | flag | 否 | 仅分析,不写入包或 diff 输出文件 |
| `--focus-ranking` | enum | 否 | token 预算受限时使用的排名策略 |
| `--selection-report-out` | string | 否 | 包含已选和已跳过路径的可选 JSON 报告 |
| `--secret-scanner` | enum | 否 | 密钥扫描器集成模式(`builtin`/`gitleaks`/`trufflehog`/`auto`/`off`) |
约束语义:
- `--max-file-size` 和 `--max-total-tokens` 定义了所选范围。
- 所选范围一致地用于制品内容、持久化状态条目和 `diff` 输出。
- 运行时统计信息包含针对超出 max-file-size 和 token-budget 的跳过计数器。
- `--selection-report-out` 为自动化和审计发出已选路径和跳过原因。
- 大小参数接受不区分大小写的后缀:`B`、`KB`、`MB`、`GB`、`TB`。
状态后端语义:
- 文件后端(默认):向 `--state` 传递普通路径。
- 内存后端:`--state memory://`。
- SQLite 后端:`--state sqlite:///path/to/state.db?key=`。
归档协商与来源:
- pakem 归档包含 `min_reader_version` 和 `max_reader_version` 元数据。
- 可选签名在 pack 期间使用 `--sign-key`,在 restore 期间使用 `--verify-signature-key`。
- 恢复操作将拒绝签名不匹配及不兼容的协商范围。
Pack 选项兼容性:
- `--compress`、`--encrypt-key` 和 `--split-size` 仅在与 `--format pakem` 一起使用时有效。
- `--cipher` 自定义仅在与 `--format pakem` 一起使用时有效。
- `--cipher none` 不能与 `--encrypt-key` 组合使用。
### `diff` 输出 Schema
如果提供了 `--diff-out`,JSON 结构为:
```
{
"added": ["..."],
"modified": ["..."],
"removed": ["..."]
}
```
## `restore` 命令
```
pakem restore --in ARCHIVE --target TARGET [--format pakem] [--compress {none,zlib,zstd,lz4}] [--encrypt-key KEY]
```
### `restore` 注意事项
- 支持 `.pakem` 制品和分割序列(`.pakem.part001`、`.part002`,...)。
- 使用元数据 `payload_length` 值重建文件 payload 边界。
- 拒绝解析到 `--target` 之外的写入。
## `archive-diff` 命令
```
pakem archive-diff --left OLD --right NEW [--left-format FMT] [--right-format FMT] [--out OUT] [--html-out REPORT.html]
```
无需扫描活动仓库即可生成确定性的新增/修改/删除结果。
## `explore` 命令
```
pakem explore --in ARCHIVE [--tui]
```
使用普通终端输出或基于 curses 的 TUI(`--tui`)检查归档条目。
## `setup-precommit` 命令
```
pakem setup-precommit [--path PATH] [--force]
```
生成包含 `ruff`、`ruff-format` 和本地 `poe check` 钩子的 `.pre-commit-config.yaml`。
## 输出格式与文件规范
## 扩展名自动选择
当 `--out` 没有后缀时:
| 格式 | 应用的后缀 |
|---|---|
| `xml` | `.xml` |
| `json` | `.json` |
| `proto` | `.pb` |
| `pakem` | `.pakem` |
| `llm-prompt` | `.prompt.md` |
如果 `--out` 已有后缀,则保留该后缀。
## XML 和 JSON
两者都表示仓库元数据、目录记录和文件记录。XML 使用嵌套元素,JSON 使用结构化对象。
## Protobuf
Protobuf 使用在运行时通过 `pakem.proto` 描述符构建生成的动态消息。
## pakem 二进制容器
### 二进制布局
| 段 | 大小 | 描述 |
|---|---:|---|
| Magic | 4 bytes | ASCII `PAKM` |
| Version | 1 byte | 当前值:`2` |
| Header length | 4 bytes(大端序) | 元数据 JSON 的字节长度 |
| Metadata | 可变 | 包含仓库/文件描述符的 UTF-8 JSON |
| Payload | 可变 | 拼接的文件 payload 块 |
### 元数据核心键
| 键 | 类型 | 描述 |
|---|---|---|
| `repository` | object | 根元数据、总计、时间戳 |
| `directories` | array | 可选的目录条目 |
| `files` | array | 包含 `payload_length` 的文件描述符 |
| `payload_size` | int | 总 payload 字节数 |
### 分割输出行为
如果最终 blob 大小超过 `--split-size`,写入器会发出:
- `name.pakem.part001`
- `name.pakem.part002`
- ...
在分割模式下不会发出根 `.pakem` 文件。
## 状态、差异与恢复语义
## 状态模型
状态文件存储:
| 字段 | 类型 | 描述 |
|---|---|---|
| `version` | int | Schema 版本,当前默认值为 `2` |
| `files` | object map | `rel_path -> {mtime, size, sha256}` |
没有 `version` 的遗留状态将加载为版本 `1`。
## 差异计算
`RepoState.diff_paths(new_state)` 返回以下项的排序列表:
- `added`(新增)
- `modified`(修改)
- `removed`(删除)
在差异模式下:
- 未更改的文件不会被序列化到输出 payload 中
- 序列化器仓库元数据可以包含 `delta` 块
## 恢复语义
恢复需要 `pakem` 格式,并遵循以下逆操作逻辑:
1. 解析 header 和元数据。
2. 根据每个文件的 `payload_length` 切片 payload。
3. 反转加密(如果提供了密钥)。
4. 反转压缩(如果启用了 `zlib`)。
5. 验证目标路径安全性。
6. 写入文件字节。
## 安全与信任模型
## 当前安全控制
| 控制 | 状态 | 描述 |
|---|---|---|
| 路径遍历预防 | 已启用 | 恢复操作通过 realpath/commonpath 逻辑检查目标路径边界 |
| 格式完整性检查 | 已启用 | `validate_pakem` 检查 magic/version/header 的一致性 |
| 二进制检测 | 已启用 | 在源代码 pack 阶段跳过二进制文件 |
## 重要密码学说明
默认加密配置是认证加密(`aes-gcm` 和 `chacha20-poly1305`),带有与元数据绑定的身份验证。
遗留的可逆 xor 模式仅在显式遗留模式下可用,用于提供恢复兼容性路径。
## 性能与可扩展性调优
## Worker 策略
默认情况下,worker 数量派生自 CPU 计数(`cpu_count * 4`,最小为 1)。
指南:
| 仓库概况 | 建议的 `--workers` |
|---|---:|
| 小型(<5k 个文件) | auto |
| 中型(5k-50k 个文件) | 8-16 |
| 大型 monorepo | 16-32(验证宿主机 IO 限制) |
## 吞吐量注意事项
| 因素 | 影响 |
|---|---|
| 二进制文件流行度 | 更多的二进制文件意味着由于跳过行为,总运行时间更快 |
| 分词器后端 | `tiktoken` 可以提高模型一致性;正则回退可避免依赖 |
| 状态可用性 | 现有状态可以减少昂贵的哈希重新计算路径 |
| 分析缓存模式 | `local` 和 `memory` 缓存减少重复的分析工作 |
| mmap 哈希 | 大文件哈希在可用时使用 mmap,以减少内存 churn |
| Pakem 转换 | 压缩和加密会增加 CPU 负载 |
## 流程图:性能路径
```
flowchart TD
A[File discovered] --> B{binary?}
B -->|yes| C[skip]
B -->|no| D[analyze + hash]
D --> E{delta + unchanged?}
E -->|yes| F[exclude from artifact]
E -->|no| G[serialize]
G --> H{format pakem?}
H -->|no| I[write structured output]
H -->|yes| J[compress/encrypt/split]
```
## 验证与质量门禁
## 内置验证器
| 验证器 | 目标 |
|---|---|
| `validate_xml(path)` | XML 制品 |
| `validate_json(path)` | JSON 制品 |
| `validate_proto(path)` | Proto 制品 |
| `validate_pakem(path)` | pakem 二进制制品 |
| `validate(path, format=None)` | 格式推断 + 分发 |
## 项目质量命令
| 目标 | 命令 |
|---|---|
| 运行测试 | `pytest -q` |
| 运行 Autobot 脚本测试 | `node --test tests/autobot_scripts.test.js` |
| 运行 linter | `ruff check .` |
| 编译检查 | `python -m compileall -q .` |
| 所有检查 | `poe check` |
## Python API 用法
## 基础 Pack
```
from pakem import IgnoreRules, RepoPacker
from pakem.fs import FileWalker
root = "/path/to/repo"
out = "repo.xml"
rules = IgnoreRules.from_defaults(root, extra_patterns=["*.tmp"])
walker = FileWalker(root, rules, output_path=out)
packer = RepoPacker(
root_dir=root,
output_file=out,
ignore_rules=rules,
walker=walker,
output_format="xml",
)
exit_code = packer.pack()
print(exit_code)
```
## 高级 Pack(pakem)
```
from pakem import IgnoreRules, RepoPacker
from pakem.fs import FileWalker
root = "/path/to/repo"
out = "archive.pakem"
rules = IgnoreRules.from_defaults(root)
walker = FileWalker(root, rules, output_path=out)
packer = RepoPacker(
root_dir=root,
output_file=out,
ignore_rules=rules,
walker=walker,
state_path=".pakem-state.json",
delta=True,
output_format="pakem",
compression="zlib",
encryption_key="demo-key",
split_size=2_000_000,
)
packer.pack()
```
## 通过 API 恢复
```
from pakem import IgnoreRules, RepoPacker
from pakem.fs import FileWalker
target = "./restored"
rules = IgnoreRules.from_defaults(target)
packer = RepoPacker(
root_dir=target,
output_file="archive.pakem",
ignore_rules=rules,
walker=FileWalker(target, rules),
output_format="pakem",
compression="zlib",
encryption_key="demo-key",
)
packer.restore("archive.pakem", target)
```
## 运维手册
## 手册 A:每日增量快照
```
flowchart LR
A[Load previous state] --> B[Run pack --delta]
B --> C[Publish artifact]
C --> D[Store new state]
D --> E[Run validate]
```
步骤:
1. 为每个仓库保留一个持久化的状态文件。
2. 运行 `pakem pack --state state.json --delta`。
3. 将生成的制品和更新后的状态文件存储在一起。
4. 可选运行 `pakem diff --state state.json --diff-out diff.json` 以生成变更报告。
## 手册 B:作为分割二进制文件传输
1. `pakem pack --format pakem --split-size 1048576 --out archive`
2. 传输所有 `.partNNN` 文件。
3. 使用以下命令恢复:
`pakem restore --in archive.pakem --target ./target`
## 手册 C:忽略规则调试会话
1. 通过 `--ignore` 或 `--ignore-file` 添加新模式。
2. 执行 `pakem pack --list-ignored --path ...`。
3. 验证预期路径是否出现在输出列表中。
## 故障排除
| 症状 | 可能原因 | 纠正措施 |
|---|---|---|
| `restore` 返回 `1` 且没有文件 | 格式错误或 magic/header 无效 | 验证归档是否以 `PAKM` 开头,运行 `validate_pakem` |
| 输出中缺少预期文件 | 忽略规则将它们过滤掉了 | 使用 `--list-ignored` 并调整模式 |
| 输出扩展名与预期不符 | `--out` 具有显式后缀 | 从 `--out` 中删除后缀以使用自动扩展名 |
| Token 计数看起来很通用 | 未安装 `tiktoken` 或模型不受支持 | 安装附加项并传递 `--model` |
| 差异输出过大 | 状态文件丢失或过时 | 保持状态持久化并限定在每个仓库范围内 |
| 分割归档未恢复 | 部分文件丢失/顺序混乱 | 确保存在连续的 `.partNNN` 文件 |
### 诊断命令
```
# 检查 lints 和 imports
ruff check .
# 验证 runtime behavior
pytest -q
# 验证 artifact(Python snippet)
python -c "from pakem.validation import validate; validate('archive.pakem', 'pakem')"
```
## 模块内部原理
| 模块 | 职责 | 关键类型/函数 |
|---|---|---|
| `pakem/cli.py` | 参数解析和子命令路由 | `main`、`resolve_output_path` |
| `pakem/commands.py` | 命令执行适配器 | `PackCommand`、`DiffCommand`、`RestoreCommand`、`ArchiveDiffCommand`、`ExploreCommand`、`SetupPrecommitCommand` |
| `pakem/packer.py` | 核心编排 pipeline | `RepoPacker.pack`、`RepoPacker.diff`、`RepoPacker.restore` |
| `pak/fs.py` | 确定性文件遍历 | `FileWalker`、`FileEntry` |
| `pakem/ignore.py` | 忽略模式加载和匹配 | `IgnoreRules` |
| `pakem/analyze.py` | 元数据提取和 token/行计数 | `FileMetadata`、`analyze_text` |
| `pakem/tokenizer.py` | Token 计数后端 | `RegexTokenCounter`、`TiktokenTokenCounter` |
| `pakem/state.py` | 增量文件状态和差异 | `RepoState`、`FileState`、`diff_paths` |
| `pakem/serialize.py` | XML/JSON/Proto/Pakem 序列化器 | `XmlSerializer`、`JsonSerializer`、`ProtoSerializer`、`PakemSerializer` |
| `pakem/cloud_io.py` | 本地/云读写抽象 | `read_bytes`、`write_text`、`write_bytes` |
| `pakem/cache.py` | 分析缓存后端 | `AnalysisCache`、`create_cache` |
| `pakem/plugins.py` | 运行时插件加载 | `load_plugins`、`register_analyzer` |
| `pakem/reports.py` | HTML 报告 | `render_html_diff_report` |
| `pakem/loaders.py` | 生态系统数据加载器 | `PakemLangChainLoader`、`PakemLlamaIndexReader` |
| `pakem/tui.py` | 归档探索 UI | `explore_archive` |
| `pakem/validation.py` | 制品验证和路径安全 | `validate`、`validate_pakem`、`is_path_safe` |
| `pakem/proto.py` | 动态 protobuf schema 描述符 | `get_repository_message_class` |
## 贡献与发布工作流
## 开发工作流
```
pip install -e ".[dev,extra]"
ruff check .
pytest -q
node --test tests/autobot_scripts.test.js
```
## 建议的 Pull Request 检查清单
| 检查项 | 状态 |
|---|---|
| 测试覆盖了新行为 | 必需 |
| Lint 通过(`ruff check .`) | 必需 |
| 针对 CLI/API 变更更新了 README | 必需 |
| 考虑了向后兼容性 | 推荐 |
| 记录了状态/格式迁移 | 推荐 |
## 打包任务
| 任务 | 命令 |
|---|---|
| 构建 source + wheel | `poe build` |
| 仅构建 wheel | `poe build-wheel` |
| 安装 pre-commit 钩子 | `poe hook` |
## 术语表
| 术语 | 含义 |
|---|---|
| Artifact(制品) | 运行产生的最终输出文件 |
| Delta mode(差异模式) | 仅序列化相对于先前状态已更改的文件 |
| State file(状态文件) | 文件路径到 mtime/size/hash 的 JSON 映射,用于增量处理 |
| Payload length | pakem payload 流中单个文件序列化字节的字节长度 |
| Split archive(分割归档) | 当 blob 超过 `--split-size` 时生成的多部分输出 |
## 许可证
该项目根据 GNU General Public License v3.0 或更高版本进行许可。
完整条款请参见 [LICENSE](LICENSE)。
标签:Linux安全, Python, SOC Prime, 代码分析, 凭证管理, 大语言模型预处理, 开发工具, 归档备份, 无后门, 逆向工具