Skip to content

lance: annotations go through the committer; provenance in changes - #734

Draft
RyanPCo wants to merge 2 commits into
ryanco/lance-annotations-importfrom
ryanco/lance-annotations-stage
Draft

RyanPCo wants to merge 2 commits into
ryanco/lance-annotations-importfrom
ryanco/lance-annotations-stage

Conversation

@RyanPCo

@RyanPCo RyanPCo commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

lance_annotations.py stages a reviewed change file under
/annotations// (meta.json last) instead of
committing it, and lance_commit --source annotations commits each staged
change, oldest first, after reviewing it again against the current
tables. One that no longer applies gets REJECTED.json and waits until it
is restaged. lance_commit is now the only writer of the Lance tables.

changes gains a provenance column (JSON): a delivery batch records each
recording's meta.json provenance, an annotation commit its approver and
source file. A changes table written before the column existed gets it
added in place (old rows read null).

https://claude.ai/code/session_01HjCQBqQCr2igFEMR7yUovw

@RyanPCo
RyanPCo force-pushed the ryanco/lance-annotations-stage branch from 8760d97 to e80a7f6 Compare October 22, 2026 14:06
@RyanPCo
RyanPCo force-pushed the ryanco/lance-annotations-import branch from 9aa93d2 to 4acc697 Compare October 22, 2026 14:06
@RyanPCo
RyanPCo force-pushed the ryanco/lance-annotations-stage branch from e80a7f6 to 879a5a7 Compare October 23, 2026 19:28
@RyanPCo
RyanPCo force-pushed the ryanco/lance-annotations-import branch 2 times, most recently from 815408a to 70b6b0b Compare October 23, 2026 19:36
@RyanPCo
RyanPCo force-pushed the ryanco/lance-annotations-stage branch from 879a5a7 to 6c62f33 Compare October 23, 2026 19:36
@RyanPCo
RyanPCo force-pushed the ryanco/lance-annotations-import branch from 70b6b0b to eaab512 Compare October 23, 2026 20:03
@RyanPCo
RyanPCo force-pushed the ryanco/lance-annotations-stage branch from 6c62f33 to 5c415cf Compare October 23, 2026 20:03
@RyanPCo
RyanPCo force-pushed the ryanco/lance-annotations-stage branch from 5c415cf to 8dced58 Compare October 30, 2026 18:27
@RyanPCo
RyanPCo force-pushed the ryanco/lance-annotations-import branch from eaab512 to 7c73b95 Compare October 30, 2026 18:27

@RyanPCo RyanPCo left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated adversarial review (read-only; findings were checked by a second skeptical pass before posting): 3 low, 1 nit.

Comment thread egomimic/scripts/lance_annotations.py Outdated
def stage(file: Path, staging, approver: str) -> str:
"""Upload a reviewed change file to `<staging>/annotations/<id>/`, meta.json last; `<id>`
is the file's content hash, so staging the same file again changes nothing."""
sid = hashlib.sha256(file.read_bytes()).hexdigest()[:16]

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

low (correctness): read_changes (and the annotations docstring) accept a .lance change file, so cmd_stage reviews one successfully, but stage() then calls file.read_bytes() and pq.read_metadata(file) on a directory and crashes with IsADirectoryError. Either convert first (pq.write_table(read_changes(file), tmp) and stage that file) or reject non-parquet input in cmd_stage before the review.

Comment thread egomimic/rldb/lance/commit.py Outdated
if not _exists(uri):
_append(uri, schema.empty_table())
changes = _open(changes_uri(root))
if "provenance" not in changes.schema.names:

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

low (dead-code): This migration runs on every _ensure_tables call, so every append/tag/annotation commit opens changes.lance again (and _record adds another _ensure_tables just for this). CHANGES is new in this unmerged stack. If no real root was written without provenance, fold the column into CHANGES in #731 and drop the migration, the extra call and its test. If such roots exist, make it a one-off like drop_task_annotations instead of a check on every write.

Comment thread egomimic/scripts/lance_commit.py Outdated
) -> dict:
"""Commit every pending staged delivery of `source`, `batch_size` at a time; returns
{"batches": [commit_batch results], "rejected": {vendor id: errors}}."""
if source == ANNOTATIONS:

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

low (api-design): With --source annotations, batch_size, replace and operator are silently ignored: --operator is documented as "recorded in changes", but the meta.json approver is used. Dispatch to commit_staged_annotations from main() and error out if --replace/--operator are combined with --source annotations, or document that they don't apply.

Comment thread egomimic/scripts/lance_commit.py Outdated
]
provenance = {}
for d in deliveries:
meta = local[d.recording["vendor_recording_id"]] / "meta.json"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit (duplication): This re-reads each meta.json that the loaders already parsed, and indexes local by vendor_recording_id, which again assumes dir name == vendor id. Consider adding provenance: dict | None to commit.Delivery, filling it in the loaders, and building the map in commit_batch.

lance_annotations.py stages a reviewed change file under
<staging>/annotations/<sha256 prefix>/ (meta.json last) instead of
committing it, and lance_commit --lab annotations commits each staged
change, oldest first, after reviewing it again against the current
tables. One that no longer applies gets REJECTED.json and waits until it
is restaged. lance_commit is now the only writer of the Lance tables.

changes gains a provenance column (JSON): a delivery batch records each
recording's meta.json provenance, an annotation commit its approver and
source file. A changes table written before the column existed gets it
added in place (old rows read null).

Claude-Session: https://claude.ai/code/session_01Kt1E8T2x8kdV9akAvbJyVd
The committer's --lab flag became --source (the staging prefix) below this
PR; the stage command's help and the old-changes-table test follow.

Claude-Session: https://claude.ai/code/session_01HjCQBqQCr2igFEMR7yUovw
@RyanPCo

RyanPCo commented Oct 30, 2026

Copy link
Copy Markdown
Contributor Author

Review findings: status after the fixup pass. The fixes are squashed into this PR's commits, and the whole stack was force-pushed.

Fixed

  • stage() only handles parquet, though change files may be .lance datasets: stage() converts a Lance change dir to parquet before hashing and uploading; test added
  • Runtime provenance column migration is unnecessary and runs on every _ensure_tables: Removed the add_columns migration, the extra _ensure_tables in _record and the before-provenance test. Fixup targets 8dced58 (same PR) because that commit edits the removed test
  • commit_staged silently ignores batch_size/replace/operator for annotations: main() dispatches annotations to commit_staged_annotations and errors on --replace, --operator or a non-default --batch-size there
  • meta.json is re-read for provenance after the loaders already parsed it: Delivery.provenance is set by the loaders, and commit_batch builds the provenance map; commit_staged no longer re-reads meta.json for it (zarr_to_lance: vendor and robot zarr episodes into Lance, with their annotations #751 still reads meta.json for annotation spans only)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant