Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

DataJig

A precision data jig aligns heterogeneous inputs into a verified training-ready revision

Repeatable dataset work for agents.
面向 Coding Agent 与 Auto Research Agent 的本地数据集工作台。

Agent 很会改数据,却很难证明自己改的是哪一版、审查的是不是当前内容、是否混入了任务外修改。DataJig 像精密治具一样固定并对齐数据,让一次数据任务成为可验证事务:声明意图 → 冻结精确 changeset → 语义检查 → seal 不可变 revision。

Agent 需要的保证 DataJig 的回答
“我改的是哪份数据?” 稳定 ds_... 身份、全文件 BLAKE3 inventory 和原子 HEAD
“这些修改属于哪个任务?” chg_... 意图声明与完整 changeset_... 候选
“审查后还有人动过文件吗?” staged/live identity 不一致立即返回 UNSTAGED_CHANGES
“这版为什么被接受?” review、finding、revision 和 provenance 由 content ID 串联
“训练到底用了哪一群样本?” recipe_...、view_... 与 bundle_... 串联选择语义和实际 shard bytes

它不是另一个 Git/DVC/Oxen 替代品。版本存储后端可以变化,DataJig 专注的是 Agent 执行数据任务时缺失的控制协议:有界 JSON、显式 next action、确定性身份、过期检测和可追溯接受。

语义审查只是第一个内置 validator,不是产品边界。imagefolder adapter 可以识别重命名、标签/划分变化、泄漏、损坏媒体和分布漂移;jsonl adapter 以稳定 ID 对齐记录,把 added、removed、modified、moved、坏行和重复 ID 纳入同一个 changeset/check/seal 协议。Universal Inventory v2 继续为其他普通文件提供精确字节身份。

面向 Agent 的 workspace、artifact 和查询协议完全在本地运行,以 Rust 作为权威内核;完整证据保存在文件中,stdout 只返回适合 Agent 上下文窗口的有界 JSON。人工 compare、Python API 和 HTML 展示目前仍由 Python 集成层提供。数据不会上传,源数据也不会被工具静默修改。

0.5.0-dev · Rust 1.85+ 权威内核 · Universal Inventory v2 · 本地优先 · 可选 Python 集成层

flowchart LR
    A["Declare intent<br/>chg_..."] --> B["Agent edits<br/>dataset files"]
    B --> C["Stage exact bytes<br/>changeset_..."]
    C --> D{"Semantic check"}
    D -->|fix / restage| B
    D -->|PASS + explicit accept| E["Seal immutable<br/>rev_..."]
    E --> F["Resolve cohort<br/>view_..."]
    F --> G["Verify training input<br/>bundle_..."]
    E --> H["Next research task"]
    X["Unexpected live mutation"] -.->|UNSTAGED_CHANGES| C

JSONL:从看懂到安全接受

Auto Research Agent 可以先只读理解两份数据:

datajig inspect data/papers.jsonl --id-field paper_id
datajig record-diff baseline/papers.jsonl data/papers.jsonl --id-field paper_id

inspect 返回稳定的 records_... 字节身份、字段类型和 ID 完整性;record-diff 按 ID 对齐两版数据,区分 added、removed、modified、moved 和 unchanged。两者都不会输出字段值或原始 ID;record-diff 只返回稳定 rid_... 与行号,并对明细做硬上限。

需要让 Agent 真正修改并接受一份 JSONL 时,直接初始化单文件 workspace:

datajig init data/papers.jsonl --id-field paper_id --state .datajig
datajig changeset-begin --state .datajig \
  --intent "Normalize paper metadata" --task-id research-42
# Agent 修改 papers.jsonl
datajig changeset-stage --state .datajig --change chg_...
datajig check --state .datajig --change chg_... --changeset changeset_...
datajig findings .datajig/latest.review.json --offset 0 --limit 50
datajig seal --state .datajig --change chg_... --changeset changeset_... \
  --accept-report review_... --message "Accept normalized records"

workspace 不保存原始记录或 ID,而是保存分页的 recordstate_... / recordpage_... 伪名化事实。坏 JSON、非 UTF-8、缺失/空/复合 ID 和重复 ID 可以被精确 stage 和 review,但必定阻止 seal;审查后发生的任何现场修改都会返回 UNSTAGED_CHANGES。

用策略约束 Agent 的数据修改

在初始化时用一个不可变策略固定质量门槛:

{
  "namespace": "datajig",
  "schema_version": 1,
  "adapter": "jsonl",
  "mode": "changed_only",
  "fields": {
    "status": {
      "required": true,
      "nullable": false,
      "types": ["string"],
      "enum": ["draft", "published"]
    },
    "score": {"types": ["number"], "minimum": 0, "maximum": 1},
    "doi": {"types": ["string"], "pattern": "^10\\.", "unique": true}
  }
}
datajig init data/papers.jsonl --id-field paper_id \
  --policy data/papers.policy.json --state .datajig

changed_only 只阻止新增或内容已修改记录带来的违规,适合逐步治理已有历史问题;full 要求整个候选都满足策略。唯一性始终在完整候选上计算。策略支持 required、nullability、JSON 类型、typed enum、精确数值范围、Rust regex 和标量唯一性。报告以 JSONL_POLICY_RANGE 等聚合 finding 返回字段名、计数和至多 20 个 rid_...,不会写入原始 ID 或字段值。策略被保存为不可变 policy_... 并进入 workspace 身份,任务中途替换策略、候选或报告都会 fail closed。

先封印 cohort,再花训练算力

Agent 不应把一次临时 filter 当成可复现的实验输入。DataJig 用一个有界 JSON recipe 描述 sealed HEAD 上的子集:顶层谓词全部做 AND,比较不做隐式类型转换,missing 与 null 明确区分;可选抽样按 typed record ID 和 seed 稳定执行。

{
  "namespace": "datajig",
  "kind": "subset_view",
  "schema_version": 1,
  "where": [
    {"field": "status", "op": "eq", "value": "published"},
    {"field": "score", "op": "gte", "value": 0.8}
  ],
  "sample": {"rate_bps": 2500, "seed": "research-42"}
}
# 只读预检:先知道会选中多少条,再决定是否启动训练
datajig view-check --state .datajig --recipe recipes/published.json

# 同一 recipe 进入训练 bundle 的身份和离线验证链
datajig export --state .datajig --view recipes/published.json \
  --output artifacts/published-v1 --split train=9000 --split validation=1000
datajig export-info artifacts/published-v1/datajig.bundle.json --verify

view-check 对空结果返回成功,但标记 exportable: false;真正导出空 view 会以 VIEW_EMPTY 失败且不创建目录。stdout 只给出计数与 content ID,不回显 record ID、记录值或 recipe 字面量。当前 v1 刻意只支持顶层 exists / missing / is_null / eq / in / 数值范围和确定性抽样;不接受 SQL、Python UDF、嵌套路径、join 或任意代码执行。

从可信 revision 到可验证训练输入

通过审查并 seal 后,可以把当前 clean HEAD 一次性导出为确定性的训练 bundle:

datajig export --state .datajig --output artifacts/papers-v1 \
  --seed research-42 \
  --split train=9000 --split validation=1000
datajig export-info artifacts/papers-v1/datajig.bundle.json --verify

DataJig 按 typed record ID 和 seed 确定 split 与伪随机顺序,统一输出 LF JSONL shards。datajig.bundle.json 将 dataset_id、sealed revision、record state、质量策略、每个 shard 的记录数/字节数/BLAKE3 和最终 bundle_... 串成一条证据链。相同 HEAD 与配置导出到不同目录会得到完全相同的 bundle identity 和 shard bytes;dirty workspace、源文件竞态、已有或重叠输出目录都会 fail closed。

bundle 是标准 JSONL,可直接交给现有生态,不要求训练进程依赖 DataJig:

from datasets import load_dataset

dataset = load_dataset(
    "json",
    data_files={
        "train": "artifacts/papers-v1/train/*.jsonl",
        "validation": "artifacts/papers-v1/validation/*.jsonl",
    },
)

首版只导出 keyed JSONL 的当前 sealed HEAD 或它的 sealed subset view。它不假装能够重放未保存原始 bytes 的历史 revision,也不执行任意 SQL 或 Python UDF。完整 HEAD 实验记录 bundle_id;子集实验同时记录 view_id 与 bundle_id,并在训练前运行 export-info --verify。

60 秒 Agent 工作流

初始化一次。每项 Agent 任务先声明意图,修改完成后把整个候选数据集冻结成 changeset;后续审查与接受始终绑定这两个不可变 ID:

datajig init data/
datajig changeset-begin --intent "Relabel ambiguous cats" --task-id task-42
# 返回 change_id: chg_...;Agent 现在修改 data/
datajig changeset-stage --change chg_...
# 返回 changeset_id: changeset_...
datajig status --change chg_... --changeset changeset_...
datajig check --change chg_... --changeset changeset_...

# WARN / FAIL 时
datajig plan --change chg_... --changeset changeset_...
# 先把 finding 的伪名化证据解析为当前 staged candidate 的行坐标
datajig findings .datajig/latest.review.json --offset 0 --limit 50
datajig locate .datajig/latest.review.json fnd_... \
  --change chg_... --changeset changeset_...
# Agent 按 line 做最小修复;locate 不返回原始 ID、字段值或整条记录
# 重新 stage,随后重新 check;旧 changeset 不会被悄悄改写

# PASS 且 findings > 0 时,先检查证据
datajig findings .datajig/latest.review.json --offset 0 --limit 50

# 使用 check 返回的精确 report_content_id 接受这份报告
datajig seal --change chg_... --changeset changeset_... \
  --accept-report review_... --message "Accept relabeling task"

# 查看不可变历史
datajig log --limit 20

findings 是分页接口。Agent 必须检查返回的 page.has_more;如果为 true,持续将 --offset 增加 50,直到读取完 page.total 条 finding,再决定是否接受并 seal。

核心命令形成从数据修改到训练输入的闭环:

命令 回答的问题 安全边界
init 这是哪个数据集,初始 HEAD 是什么? 为目录写入 inventory,或为 keyed JSONL 写入分页 record state;不改源数据
changeset-begin 这次任务为何修改数据? 只允许从 clean HEAD 开始;生成确定性的 chg_... 意图声明
changeset-stage 这次任务确切改了什么? 冻结全数据集候选和变更摘要为不可变 changeset_...
status 当前内容相对 HEAD 是否变化? 纯读取;返回 HEAD/current state ID 和有界文件或记录变更计数
check 相比 last-good 发生了什么? 输出策略决策和 finding 数量;PASS 仍可能包含 info finding
plan Agent 下一步具体做什么? 只生成 agent_decision 计划,不自动删除或覆盖文件
locate 这个 finding 对应候选文件的哪几行? 严格绑定 report/changeset/live state;只返回伪名化 RID、record hash 和行号
seal 接受的变更可以成为新 revision 吗? 重新验证身份;有 finding 时必须绑定精确报告 ID;以 compare-and-swap 推进 HEAD
log 这份数据是怎么到当前版本的? 分页读取不可变 revision、父链、消息、时间和接受的报告 ID
view-check sealed HEAD 上这个 cohort 到底有多大? 只读解析有界 recipe;绑定 revision、选择语义和命中记录内容,不输出值
export / export-info 训练实际读取的 bytes 是什么? 原子生成并离线复验标准 JSONL shards;可把 view_... 固化进 bundle

重要: PASS 表示当前策略没有 warning/error,不等于所有语义变化都自动正确。seal 是对变化的显式接受,并保证接受的报告没有过期,而不是替 Agent 判断业务意图。新建 inventory 使用 all_files_v2,每个普通文件的路径、大小和字节哈希都会进入 identity;schema 1 artifact 仍按 supported_media_v1 语义严格读取,并在输出中明确标记覆盖范围。

它解决的不是普通文件 diff

普通的文件 diff 很难回答数据集变更中真正重要的问题:

  • 一张图片只是改名了,还是内容真的变了?
  • 样本是否被移动到错误的标签或 train / val / test 划分?
  • 不同划分之间是否出现完全重复或视觉近似的图片?
  • 新版本是否加入了损坏图片、异常通道或明显的类别分布漂移?
  • 这次变更是否应该阻止 CI 继续运行?

DataJig 将路径、BLAKE3 内容哈希和感知哈希分阶段组合,尽量给出稳定且可解释的答案。

flowchart TB
    DATA["Dataset directory"] --> FILES["Universal file inventory<br/>path · size · BLAKE3"]
    DATA --> ADAPTER["ImageFolder adapter<br/>label · split · media · pHash"]
    FILES --> ID["Deterministic dataset identity"]
    ADAPTER --> REVIEW["Semantic findings + policy"]
    ID --> CHANGESET["Task-scoped changeset"]
    REVIEW --> CHANGESET
    CHANGESET --> REVISION["Immutable revision + provenance"]
    REVISION --> HEAD["Atomic CAS HEAD"]
    AGENT["Coding / Research Agent"] <--> JSON["Bounded JSON protocol"]
    JSON <--> CHANGESET

对 Agent 来说,关键差异不只是“检测更多问题”,而是工具本身可以被可靠地调用和恢复:

  • 不用把大报告塞进上下文:完整 artifact 落盘,摘要、分页和样本预览都有硬上限
  • 可以稳定引用同一个问题:finding 使用 fnd_...,修复动作使用 act_...,相同输入得到相同身份
  • 不需要自己维护版本状态:dataset ID、HEAD、不可变 revisions、最新 review 和 remediation plan 都由工作区协议管理
  • 多步任务不会失去身份:意图声明、全量 staged candidate、review 和最终 revision 由同一组 content ID 串联
  • 不会拿旧结论盖章:seal 会重新扫描并校验 baseline 与 candidate 的内容身份
  • 并发写入不会静默互相覆盖:HEAD 使用跨进程锁和 compare-and-swap,过期 Agent 必须重新读取
  • 明确的格式边界:ImageFolder 使用 workspace schema 2,普通 JSONL 使用 schema 3,固定质量策略的 JSONL 使用 schema 4;旧工作区不会被静默迁移或重写
  • 可以先发现能力再执行:capabilities 和 describe 暴露版本、限制、平台、读写效果与退出码
  • 失败可被程序理解:原生 Agent 命令成功时输出单个 JSON;错误包含稳定的 code、message 和 retryable 字段

产品成熟度

当前版本已经具备 Agent-native dataset workspace 的第一层内核:Agent 可以发现能力、建立数据集身份、声明任务意图、把完整候选冻结成 changeset、读取 staged/unstaged 状态、遍历不可变历史、得到确定性审查、按 ID 查询证据、把 finding 定位到当前候选行、生成修复计划,并在重新验证内容身份后 seal 被明确接受的 PASS 结果。对象先于引用发布、HEAD 原子替换,损坏 refs、缺失对象和过期输入都会 fail closed。

但它还没有达到“Agent 一用就离不开”的完整产品状态,也还不能被当成无需判断的全自动安全门。接下来最重要的不是堆更多检查器,而是消除信任、采用和闭环上的摩擦:

  1. 安全执行与回滚:在已经可定位的证据上增加 guarded patch preview、CAS apply 和 seal 前精确 undo
  2. 零摩擦分发:发布内置对应平台 Rust binary 的 PyPI wheel;平台 wheel 构建与隔离安装验收已就绪
  3. 进入 Vibe Coding 默认路径:把已有的 Agent Skill 生成能力升级为一键安装,并补齐 Git hook 和 CI 模板
  4. 训练框架适配:在已稳定的 verified bundle 上提供 PyTorch / Hugging Face 轻量接口
  5. 远程适配与产品验证:消费 Oxen、DVC、Hugging Face 或对象存储 revision,并用真实 Agent 任务衡量价值

我们的产品目标不是“另一个数据集版本控制器”,而是成为 Agent 使用数据的默认控制层:知道自己在改什么,改动有身份,风险可验证,接受可追溯,失败能恢复。

功能

  • 语义化变更识别:新增、删除、改名、标签变化、划分变化、疑似重编码和视觉编辑
  • 数据泄漏检查:发现跨划分的完全重复与近似重复图片
  • 数据质量检查:报告无法解码的图片、异常通道和不支持的文件
  • JSONL 记录画像:流式统计字段类型与 ID 完整性,定位坏行和重复 ID,不泄露原始值
  • JSONL 记录事务:分页 record state、逻辑记录 changeset、语义 review、修复计划与不可变 revision
  • 可定位证据:把 staged JSONL finding 安全解析为有界行坐标,并拒绝过期 report 或现场修改
  • 可验证训练导出:从 clean sealed JSONL HEAD 生成确定性 split/shard、portable manifest 与 bundle_...
  • 分布对比:比较标签、划分、格式、尺寸、宽高比和通道分布
  • 可视化报告:生成带前后对照和缩略图的自包含 HTML 文件
  • CI 友好:输出确定性 JSON,并通过稳定退出码表达审查结果
  • Agent 原生:能力发现、有界输出、稳定 finding/action ID、显式 next actions
  • 全文件身份:Universal Inventory v2 为每个普通文件记录路径、大小和 BLAKE3
  • 任务级 Changeset:确定性意图声明、全数据集 staging、unstaged 检测和 revision provenance
  • Revision 工作区:稳定 dataset ID、不可变 inventory/revision、原子 HEAD、status/log 和防过期 seal
  • 增量分析:SQLite 缓存保存媒体元数据与感知哈希,不保存图片内容
  • 本地优先:不会上传数据,也不会修改源数据集

安装

当前预览版尚未发布到 PyPI。GitHub 构建产物中的平台 wheel 已内置 Rust 内核,安装后不需要本机 Rust 工具链或 DATAJIG_NATIVE:

python -m pip install /path/to/datajig-0.5.0.dev0-py3-none-PLATFORM.whl
datajig capabilities

从源码参与开发:

git clone https://github.com/liukejun7/DataJig.git datajig
cd datajig
cargo build --release --locked --manifest-path rust/Cargo.toml
python -m pip install -e '.[dev]'
export DATAJIG_NATIVE="$PWD/rust/target/release/datajig-core"

发行 wheel 会优先使用包内的 datajig-core;源码开发也可以让它位于 PATH,或通过 DATAJIG_NATIVE 指向可执行文件。找不到 Rust 后端时会明确失败,不会退回 Python 算法。datajig compare、Python API 和 HTML 展示目前仍走 Python 实现,不依赖原生 binary。

维护者可显式指定受支持目标构建本机平台 wheel;Linux 发布流水线还会使用 auditwheel 在 manylinux2014 环境中审计并生成最终兼容标签:

DATAJIG_BUILD_TARGET=x86_64-unknown-linux-gnu \
  python -m build --wheel

当前 wheel 矩阵覆盖 Linux x86_64 / aarch64 和 macOS x86_64 / arm64。自动化只保存待检查的构建产物,尚未向 PyPI 发布。

人工比较与可视化

准备两份 ImageFolder 数据集:

baseline/                  candidate/
├── train/                 ├── train/
│   ├── cat/               │   ├── cat/
│   │   └── 001.jpg        │   │   └── 001.jpg
│   └── dog/               │   └── dog/
└── val/                   └── val/
    └── cat/                   └── cat/

如果需要人工审查两份显式快照,可以直接生成 HTML 和 JSON:

datajig compare baseline candidate \
  --output review.html \
  --json review.json \
  --cache .cache/datajig.sqlite \
  --workers 4

在浏览器中打开 review.html 即可查看按风险排序的审查结果。报告包含内联样式和脚本,无需服务器;如果数据敏感,可添加 --no-thumbnails 禁止嵌入缩略图。

只需要终端 JSON 时,可以省略输出参数:

datajig compare baseline candidate

Python API

from datajig import compare

report = compare(
    "baseline",
    "candidate",
    cache=".cache/datajig.sqlite",
    workers=4,
    phash_threshold=6,
)

print(report.policy.status.value)
for finding in report.findings:
    print(finding.severity.value, finding.code, finding.sample_ids)

report.save_html("review.html")
report.save_json("review.json")

不可变数据集快照

DataJig 可以为目录中的所有文件创建可移植 manifest。snapshot ID 只取决于规范化相对路径、文件大小和 BLAKE3 内容哈希,不包含绝对路径、mtime、worker 数量或运行机器信息。同一份数据复制到不同目录后仍会得到相同 ID。

datajig snapshot dataset/ \
  --output artifacts/snapshot.json \
  --workers 4

读取快照摘要,或在不访问原始数据集的情况下比较两个 manifest:

datajig snapshot-info artifacts/snapshot.json

datajig snapshot-diff \
  artifacts/before.json \
  artifacts/after.json \
  --offset 0 \
  --limit 50

manifest diff 区分 modified、renamed、removed 和 added。不同路径但内容完全相同的文件会按确定性一对一规则识别为 rename;重复内容的数量不会被折叠。分页结果最多包含 200 项,并受约 50,000 字符的总输出预算约束。

manifest schema version 1 的 snapshot ID 使用明确的二进制预映像,后续 Rust 核心必须逐字兼容:

  1. 写入 ASCII 前缀 datajig-snapshot-v1,随后写入一个 NUL 字节。
  2. 条目按路径 UTF-8 字节的字典序排列。
  3. 每个条目依次写入:4 字节大端无符号路径长度、路径 UTF-8 字节、8 字节大端无符号文件大小、32 字节原始 BLAKE3 内容摘要。
  4. 对全部字节计算 BLAKE3,并添加 snap_ 前缀。

固定兼容向量:a.txt(3 字节,摘要为 32 个 aa 字节)与 数据/猫.jpg(大小 2^64-1,摘要为 32 个 01 字节)共同生成:

snap_366459218864742c742209d14aad2f9f281c7aaece1e859d7d3b905346b39a5c

单条路径最多 4,096 个 UTF-8 字节,单文件大小必须能用无符号 64 位整数表示,单个 manifest 最多 250,000 条记录和 128 MiB。manifest 通过同目录临时文件、fsync 和原子替换发布;输出路径不能位于或指向数据集源文件。

Rust 原生 Agent 内核

v0.5 开始以 datajig-core 作为原生 Agent 协议的唯一权威内核。当前 Rust 已实现 init、changeset-begin、changeset-stage、status、check、plan、locate、seal、log 工作区闭环,view-check sealed subset、export / export-info verified training bundle,inventory、review、snapshot 系列 artifact 操作,以及 schema-1 报告的 findings、finding、explain 只读查询;Python 入口对这些命令只做转发,没有算法 fallback。workspace schema 2 保持 ImageFolder 兼容,schema 3 表示普通单文件 JSONL,schema 4 表示固定质量策略的 JSONL;revision/changeset schema 2 使用 recordstate_...,旧 schema 1 对象仍按原 identity 读取。Windows 会明确报告暂不支持需要文件句柄安全保证的 workspace 写入,但离线 bundle/report 查询可用。

cargo build --release --manifest-path rust/Cargo.toml

./rust/target/release/datajig-core capabilities

./rust/target/release/datajig-core inventory dataset/ \
  --output artifacts/inventory.json \
  --threads 8

./rust/target/release/datajig-core review \
  path:baseline/ path:candidate/ \
  --output artifacts/review.json \
  --threads 8

./rust/target/release/datajig-core snapshot dataset/ \
  --output artifacts/snapshot.json \
  --threads 8

本地 Linux 环境、8 workers/threads、每组 3 次运行的中位数:

数据集 Python 时间 / 峰值 RSS Rust 时间 / 峰值 RSS 时间提升
20,000 个 1 KiB 小文件 10.11s / 166 MiB 0.33s / 26 MiB 约 31×
CIFAR-10 60,000 张图片 32.32s / 378 MiB 0.85s / 63 MiB 约 38×

两组迁移基准的 manifest 均逐字一致。这里的数据用于确定迁移边界,并非所有硬件上的性能承诺。manifest 工作流已经只走 Rust;图像审查、匹配和策略模块将按同一原则继续迁移,最终 Python 只保留 API 兼容和 HTML 渲染。

Agent 协议细节

工作区命令建立在确定性、可分页的 JSON 协议上。init 创建自动被 Git 忽略的 .datajig 状态;changeset-begin 把任务意图锚定到 clean HEAD,changeset-stage 冻结候选 inventory 或 record state 和精确摘要。携带 --change 与 --changeset 后,status 会报告 staged/unstaged,check、plan、locate 和 seal 都拒绝脱离该候选的现场修改。check 返回 seal、inspect、fix 或 retry。WARN/FAIL 的下一步是 plan:它把完整 review 转成 .datajig/latest.plan.json,每个动作都绑定稳定的 fnd_... finding ID,并带有稳定的 act_... ID、风险、修复策略、样本预览和复验命令。locate 再把策略 finding 中的 rid_... 或结构 finding 映射为候选文件行号;它不会回显逻辑 ID、字段值或记录内容,也不会接受已经过期的 report。

首版计划刻意采用 agent_decision 模式:它会建议去重、修复媒体、整理布局或复核分布,但不会静默删除、移动或覆盖数据。Agent 完成最小修复后重新运行 check;seal 只接受仍然新鲜的 PASS 报告,同时验证 HEAD baseline 和当前数据都没有在审查后改变。PASS 仍包含 finding 时,--accept-report 必须精确匹配最新 review_...。成功后旧 revision 保留,log 可按父链追溯。

DataJig 在首次公开发布前完成了命名空间硬切;从 0.5.0-alpha 开始,datajig 命令以及 ds_...、inventory_...、rev_...、review_... 等机器身份构成正式兼容承诺。

完整报告保存在状态目录中,Agent 可以按需读取少量 finding,避免把整份数据集审查结果放进上下文窗口。报告解析、finding 排序和紧凑输出均由 Rust 完成;Python 只负责启动已通过能力握手的原生后端。

发现工具能力和协议限制:

datajig capabilities

创建可供 Agent 或后续原生 compare 消费的媒体盘点文件:

datajig inventory dataset/ \
  --output artifacts/inventory.json \
  --workers 8

inventory schema version 2 为所有普通文件记录规范化路径、大小与 BLAKE3,并为受支持图片附加 ImageFolder 语义、64 位 pHash、尺寸、格式、通道和解码错误。schema 1 仍可严格读取并保留原 content ID;完整结果原子写入文件,stdout 只返回有界摘要,避免大型数据集淹没 Agent 上下文。

直接生成可查询的原生 review artifact:

datajig review \
  path:baseline/ inventory:artifacts/candidate-inventory.json \
  --output artifacts/review.json \
  --phash-threshold 6

review 接受 path:<目录>、inventory:<文件>,裸路径等价于 path:。stdout 返回 content ID、状态、finding 数量和推荐的下一步命令;完整 schema-1 报告只写入指定文件。

获取经过筛选的一页 finding:

datajig findings review.json \
  --severity error \
  --code CROSS_SPLIT_EXACT_LEAKAGE \
  --offset 0 \
  --limit 20

每个 finding 都有基于规范化内容生成的稳定 ID。Agent 可以用 ID 单独获取证据,也可以请求有数量上限的紧凑摘要:

datajig finding review.json fnd_0123456789abcdef0123_0001
datajig explain review.json --limit 10

Agent 命令遵循以下约定:

  • 成功时 stdout 只包含一个紧凑 JSON 文档
  • 错误时 stderr 包含带 code、message 和 retryable 的 JSON
  • findings 默认返回 50 项,单页最多 200 项
  • explain 最多携带 20 条 finding,并将紧凑 JSON 控制在约 50,000 字符以内;截断状态会显式返回
  • 过滤条件使用交集语义
  • 查询只读取报告文件,不会重新访问或修改数据集

Agent 查询的退出码为 0(成功)、2(参数、文件或报告无效)和 4(finding 不存在)。完整报告继续使用 schema version 1;v0.2 以兼容方式为 finding 增加了 id 字段。

数据集约定

每份快照使用 {split}/{label}/... 目录结构:

  • 支持的划分:train、val、test
  • 支持的图片:JPEG、PNG、WebP
  • 标签目录下允许继续嵌套目录
  • 不跟随目录符号链接
  • 文件符号链接必须指向当前数据集根目录以内
  • 根目录中的其他文件会被统计,但不会作为图片解码

审查策略

默认情况下,布局错误、图片解码失败和跨划分完全重复会使审查失败;近似重复、匹配歧义和分布变化会产生警告。可以通过 TOML 文件调整严重级别与阈值:

[policy]
label_delta_threshold = 0.15
media_delta_threshold = 0.20

[policy.severity]
CROSS_SPLIT_NEAR_LEAKAGE = "error"
LABEL_DISTRIBUTION_CHANGED = "warning"
datajig compare baseline candidate --policy policy.toml

CLI 退出码:

退出码 含义
0 审查完整,结果为通过或警告
1 命中策略中的失败条件
2 输入、布局或配置无效
3 分析未完整完成

工作原理

匹配按三层进行:相对路径、BLAKE3 内容哈希、pHash 汉明距离。完全相同的内容优先匹配;视觉近似候选使用一对一的最小代价分配;存在多个等价方案时会明确标记为歧义,避免把不确定关系伪装成确定变更。

缓存只保存解码后的尺寸、格式、通道和感知哈希。每次运行仍会流式计算文件的 BLAKE3,因此即使大小和修改时间未变,内容变化也不会错误复用旧分析。

当前范围

0.5.0-dev 已将全文件 BLAKE3 identity、本地 ImageFolder 安全扫描、媒体元数据和 pHash、keyed JSONL record state 与语义事务、内容寻址 manifest、任务级 changeset、last-good workspace、确定性 remediation plan、字段质量策略、sealed subset、verified training bundle,以及 Agent 报告查询和 finding 定位收归 Rust 内核。当前 JSONL 还没有字段级 diff、自动安全 patch/rollback 或历史原始 bytes 重放。远程数据源、MCP、训练框架薄适配、Oxen / DVC / Hugging Face 适配、目标检测、分割、音视频和学习型 embedding 也尚未包含在当前版本中。

Metadata

Release files for datajig 0.5.0.dev0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for datajig 0.5.0.dev0
File
datajig-0.5.0.dev0-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl Python 3 none Linux glibc 2.17+ x86-64 Details
datajig-0.5.0.dev0-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl Python 3 none Linux glibc 2.17+ ARM64 Details
datajig-0.5.0.dev0-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details
datajig-0.5.0.dev0-py3-none-macosx_10_12_x86_64.whl Python 3 none macOS 10.12+ x86-64 Details

Total release size: 12.3 MB

Release files / datajig-0.5.0.dev0-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl

Download URL datajig-0.5.0.dev0-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Size 3.3 MB
Tags Linux glibc 2.17+ x86-64 Python 3
SHA-256 checksum
How to use checksums
0b74d27bb010e172d30cf38ba9086517ea4d4867f1aed9c1a6468ea0c92a8705
BLAKE2b-256 checksum
How to use checksums
74fc94d0882876d3fd232fe31826eec3e64ef508a1853fde9134870727da1161
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.

Transparency log

Release files / datajig-0.5.0.dev0-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl

Download URL datajig-0.5.0.dev0-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Size 3.1 MB
Tags Linux glibc 2.17+ ARM64 Python 3
SHA-256 checksum
How to use checksums
213ec7c1d61bc53ac93d873e657608fa0bd7dc26db14039d202967b91174bfc1
BLAKE2b-256 checksum
How to use checksums
a44f3262e3bda01ce5dc951544f938a5b1ab311c730a3968d742149da604dd6b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.

Transparency log

Release files / datajig-0.5.0.dev0-py3-none-macosx_11_0_arm64.whl

Download URL datajig-0.5.0.dev0-py3-none-macosx_11_0_arm64.whl
Size 2.8 MB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
28e3eb7469262d034b8dccdcea774345480bc6a2d2581918c60421ddeba1c07c
BLAKE2b-256 checksum
How to use checksums
98ba9bb3aaa608de9db9dcda52e672fe3c12d8724349dc4d123641bd3e08d8b2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.

Transparency log

Release files / datajig-0.5.0.dev0-py3-none-macosx_10_12_x86_64.whl

Download URL datajig-0.5.0.dev0-py3-none-macosx_10_12_x86_64.whl
Size 3.1 MB
Tags Python 3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
01a628072146a98b28bd5bf2ecf16cd50ce1db8e01bbb28c7fa9434f1bca47c4
BLAKE2b-256 checksum
How to use checksums
40d57ae7991fe05872aabcbf76765dc4ae3f98971c6907b61979459b04596ec6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.

Transparency log
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page