feat: add ocas export / import — CAS closure bundling #91
Reference in New Issue
Block a user
Delete Branch "fix/83-export-import"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
Adds self-contained CAS closure bundling for
ocas:ocas export <root> [<root> ...] -o <bundle.tar>— package a closure (nodes + vars + tags) into a tar bundleocas import <bundle.tar> [--scope @newscope]— restore a bundle into any store, with optional scope remap--store <bundle.tar>flag — read-only inspection of a bundle as if it were a regular store@ocas/coreexports:computeClosure,exportBundle,importBundle,loadBundleStore@ocas/output/export,@ocas/output/importWhy
Closes #83. Enables shipping reproducible CAS slices (workflows, schemas, configs) between machines / users / environments without requiring a shared store. Uses content-addressed dedup on import so re-importing is a safe no-op.
Changes
@ocas/coreclosure.ts—computeClosure(store, roots)walks refs + schema chains, gathers vars/tagsbundle.ts—exportBundle()/importBundle()/loadBundleStore()with a custom POSIX/ustar tar implementation (no external deps)bootstrap.ts— registers@ocas/output/export/@ocas/output/import@ocas/cliexportandimportcommands;--storeand--scopeflags--storeis setclosure.test.ts,bundle.test.ts,export-import.test.tscovering all spec scenarios — 683/683 tests passREADME.md,packages/cli/README.md,packages/core/README.md,packages/cli/prompts/usage.md,.cards/cli.mdupdated.changeset/export-import-bundle.md(minor for@ocas/coreand@ocas/cli)Ref
Fixes #83
LGTM ✅ 仔细过了一遍,2100 行 diff 质量很高。
核心逻辑
closure.ts — 5 阶段遍历设计清晰:refs walk → schema chain → template vars → variable collection → tag collection。用现有
walk()BFS(自带 visited set 防环),meta-schema 自引用终止条件正确。bundle.ts — POSIX tar 实现干净,512 字节对齐 + checksum + end-of-archive markers。导出确定性排序(hash/name/target),导入用收敛循环解决类型依赖顺序。
remapVarName()正确保护@ocas/*builtins。BOOTSTRAP_STOREsymbol 用对了。CLI
WRITE_COMMANDSset 覆盖完整,ensureWritable()在 dispatch 前 fail-fast,--store只允许读命令。export 正确不在写命令里(读 store 写文件)。测试
40 个测试覆盖很扎实:
@ocas/*builtins ✅--store下写命令被拒 ✅Non-blocking observations
put()用Date.now(),bundle 里的node.timestamp被丢弃。不影响 hash 正确性,但 import 后的created时间会变。如果在意审计场景可以考虑putWithTimestamp路径,不过作为 v1 完全可以接受as CasNode/as Variable直接 cast。自产自消场景没问题,后续可以加 schema validation 做 hardeningasync函数内部全是同步 I/O — 猜测是 future-proofing,可以加个注释说明这个 PR 从 #83 issue 到 merge 经历了不少波折(frontmatter 失败 → #139 修复 → session resume → reviewer reject 补文档),最终产出非常扎实。可以合 🍊