Uh oh!
There was an error while loading. Please reload this page.
feat(data ingest): wire the 5 text tasks (#182) - #209
Conversation
76e6250 to
bcea12fCompareThere was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit bcea12f. Configure here.
Uh oh!
There was an error while loading. Please reload this page.
Wire token_classification, sentence_pair_classification, causal_language_modeling, seq2seq, and embeddings so the family-scoped picker offers them under "Available now" — the ingestor, schema, and backend already support them; CLI-side discovery/staging was the only gap. The CLI now MIRRORS data-ingestors' machine-readable layout contract (di#347/#353) rather than forking its layout rules (RFC-0002 Principle 6): - Vendor layout.v1.json into internal/schema/ + embed it; extend scripts/sync-schema.sh to sync + drift-check both contract files. Bump scripts/.data-ingestors-ref to the #353 merge commit (3c63d9a), which keeps ingest.v1.json byte-identical (no unrelated drift). - internal/push/layout_contract.go parses the contract and drives the ENFORCED record-format checks (sentence_pair: text_a<TAB>text_b; embeddings: anchor<TAB>positive[<TAB>negative]) at discovery, mirroring the ingestor's TabSeparatedRecordValidator. Unenforced formats (seq2seq, causal LM) accept raw text, so the mirror doesn't reject them. - Fix the self-supervised flags for seq2seq + embeddings (no label question), and emit the label for the supervised text tasks. - Flip the 5 CLISupported=true; a drift test pins the Go registry's family/label/subdir facts against the vendored contract. semantic_segmentation stays CLI-pending: it awaits the ingestor's mask_id link column + training sign-off (backend#816). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…exactly Verified review findings on the text-task wiring, fixed minimally so the CLI never forks a fact the layout contract / ingestor owns (RFC-0002 Principle 6): - text.go: the enforced record-format check (sentence_pair, embeddings) now runs only over the .txt files labels.csv references, mirroring the ingestor's TabSeparatedRecordValidator manifest walk — a stray unreferenced .txt no longer fails discovery on a layout the cluster accepts. - preflight.go: the text-family label preflight was hardcoded to text_classification; gate the label-column check on !SelfSupervisedText and the diversity check on IsClassification, so sentence_pair_classification and token_classification get the right previews (token_classification is NOT is_classification, so it skips diversity — the ingestor runs BIOLabelValidator instead). Adds IsClassification to the registry, mirroring the ingestor's ModalitySpec.is_classification. - category.go: derive TextSidecarDir from the contract's primary_subdir instead of a hardcoded MLM special-case; refresh the SelfSupervised docs to cover seq2seq/embeddings (target from the record's paired fields, not the text). - data.go: refresh the stale text-branch comment (7 tasks, supervised split). - sync-schema.sh: restore signal-safe temp-file cleanup (EXIT/INT/TERM, not a RETURN trap) and make a failed write in write mode return non-zero instead of a false "wrote" + exit 0 under the `if ! sync_one` errexit suspension. Part of #182. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
bcea12f to
e4b1addCompare
saadqbal
left a comment
There was a problem hiding this comment.
Careful PR — the registry/contract/flag refactor mirrors the ingestor faithfully (verified SelfSupervised↔has_label_column, IsClassification, TextSidecarDir, buildText against data-ingestors). Findings below are mostly in the new record-format machinery, where the enforced check can silently no-op. Two candidates I checked turned out fine: text tasks resolve the filename by a namedfilename column (not positional like the image path), and token_classification correctly requires --label-column (BIOLabelValidator). #1 and #2 are the ones worth acting on.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
…d files, not reconstructed names (#209) Address Asad's review on #209. The enforced text-record check reconstructed "<stem>.txt" from the manifest instead of matching the files actually discovered on disk, so it fail-opened in several ways. Mirror the ingestor's TabSeparatedRecordValidator exactly (RFC-0002 Principle 6): - Match each manifest filename against the discovered sidecar basenames (case-insensitive on basename and stem), so a row "a" resolves to texts/a.text when the ingestor's configured extension is .text — no more hardcoded ".txt". - Require the filename column locally: a manifest without it now errors clearly (mirrors the ingestor's "Missing required column: filename") instead of silently validating nothing. - Read the manifest with LazyQuotes so a row pandas tolerates (an unescaped quote) is read here too, not silently dropped and left unvalidated. - Drive the field-count error message off the contract separator (sepLabel), so a future non-tab task isn't misdescribed as "tab-separated". - TextSidecarDir now fails loud on a text category missing from the vendored contract — that can only be a vendoring/drift bug, not a runtime condition. - sync-schema.sh checks curl's exit explicitly (a 404 was misdiagnosed as "not valid JSON" under the set -e-suspending `if ! sync_one`) and adds --tlsv1.2 to match the rest of the repo. - Dedupe: shared matchColumnIndex (column resolve) and openCSVReader (BOM-stripping CSV reader) helpers; slices.Contains over hand-rolled containsInt. Tests: .text extension validated, missing filename column errors, case- mismatched basename validated, pandas-tolerable/Go-strict row read, contract- driven message. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
LukasWodka
commented
Jul 10, 2026
Thanks for the careful review, @saadqbal — all 11 addressed in Correctness (the record-format cluster):
Robustness / convention: Reuse: New tests: One thing I did NOT change (flagging for transparency): there's no text-family missing-file cross-check — a text row naming a file absent from disk is caught by the ingestor ("text file not found") but not in CLI preflight, whereas the image family has |
Uh oh!
There was an error while loading. Please reload this page.

Summary
Wires the five CLI-pending text tasks into
data ingest— token classification, sentence-pair classification, causal language modeling, seq2seq, and embeddings — so the whole text family is pushable, not just text classification and masked language modeling. Discovery, staging, spec-building, the interactive picker, and preflight all learn these tasks by reading the vendored layout contract (layout.v1.json), never by forking the ingestor's rules (RFC-0002 Principle 6). Data stays on-prem throughout; only metadata syncs.This PR also folds in the verified review findings on the branch.
What changed
internal/schema/layout.v1.json+layout_contract.gomirror data-ingestors' per-task on-disk layout.sync-schema.shnow vendors bothingest.v1.jsonandlayout.v1.jsonfrom the pinned ref, drift-checked in CI.text_a<TAB>text_b) and embeddings (anchor<TAB>positive[<TAB>negative]) get a local structural check before staging, so a malformed file fails with a clear message instead of after the upload. The check is scoped to the fileslabels.csvactually references — mirroring the ingestor'sTabSeparatedRecordValidatormanifest walk — so a stray unreferenced.txtnever blocks a layout the cluster would accept.!SelfSupervisedTextfor the label-column existence check,IsClassificationfor diversity) rather than a hardcodedtext_classification. Token classification correctly skips the diversity check — the ingestor runsBIOLabelValidatoron it, notLabelDiversityValidator.buildTextemitslabelfor exactly the supervised text tasks, keyed on the registry'sSelfSupervisedflag.TextSidecarDiris now read from the contract'sprimary_subdirinstead of a hardcoded MLM special-case.EXIT/INT/TERM), and a failed write now returns non-zero instead of a false "wrote" + exit 0.Test plan
go build ./...— cleango test ./...— all green (addedTestDiscoverText_EnforcedRecordFormat_IgnoresUnreferenced,TestPreflightDataset_TextLabelParity, plus the existing phase-4 discovery/record-format/spec tests)gofmt -l .— emptygo vet ./...— cleanscripts/sync-schema.sh --check— no drift against the pinned ref; write-failure path verified to exit non-zeroLayout-contract fields consumed
The CLI reads these from
layout.v1.jsonso discovery/staging stays a verified mirror:primary_subdir— the text-file subdir to stage into (texts/, orsequences/for MLM), viaTextSidecarDirrecord_format(fields,min_fields,separator,enforced) — the per-.txtstructure and whether the ingestor rejects a malformed file, viaRecordFormatFor/ValidateTextRecordmanifest.has_label_column— pinned against the registry's supervised/self-supervised split inlayout_contract_test.goStacking
Was stacked on the #180b data-first-inversion work (#198). That has since squash-merged into
develop, so this targetsdevelopdirectly and is standalone — no ordering constraint left.Deferred: semantic segmentation
Semantic segmentation stays CLI-pending on purpose.
di#136shipped the mask sidecar, but the ingestor doesn't yet populate themask_idlink column the contract requires, and the training-side sign-off is tracked in backend#816. The registry keeps it schema-recognized-but-unsupported with that note, so the push gate explains why. Wire it once #816 lands.Part of #182.
Note
Medium Risk
Broad changes to ingest discovery, spec emission, and preflight across the text family; correctness depends on staying in sync with the vendored layout contract, though tests and CI drift checks mitigate that.
Overview
Enables
data ingestfor the five previously CLI-pending text tasks — token classification, sentence-pair classification, causal LM, seq2seq, and embeddings — so the full text family is pushable except semantic segmentation (still blocked on ingestormask_id+ backend#816).Discovery, spec building (
buildTextlabels viaSelfSupervised), preflight, and the interactive picker all follow the vendoredlayout.v1.jsoncontract (synced withingest.v1.jsoninscripts/sync-schema.sh) instead of hardcoded per-task rules.TextSidecarDirnow comes from the contract’sprimary_subdir; a newIsClassificationregistry flag drives label-diversity preflight so token classification skips diversity (BIO tags) while supervised class tasks do not.Local validation before upload: enforced tab-separated shapes for sentence-pair and embeddings mirror the ingestor’s
TabSeparatedRecordValidator, only on files referenced inlabels.csv(stray.txtfiles do not fail discovery). Shared CSV helpers (openCSVReader,matchColumnIndex) dedupe BOM-aware reads and column matching.Tests and registry expectations were updated (14 supported categories; image picker still shows semantic segmentation as “not yet in the CLI”).
Reviewed by Cursor Bugbot for commit a98e598. Bugbot is set up for automated code reviews on this repo. Configure here.