Repository navigation
fix(atlas): records --data reads a path and fails loudly (#193517); feat(leads): title/external_id/product/segment/name_verified + leads import (#193510–#193514) - #584
Merged
Conversation
…exits non-zero (#193517) upsert fed the path to JSON.parse, printed 'Invalid JSON', then 'Done' and exited 0. add read a path only if it ended in .json; update never did. All three now use one loader (shared with import), and auth/API/parse failures set exit 1 and print 'Failed'. import also exits non-zero when any row is rejected. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…is leads import (#193510 #193511 #193512 #193513 #193514) - leads create/update: --title --external-id --product --segment --name-verified/--no-name-verified; the saved lead is read back and a field the server dropped is an error (exit 1). - leads list: --title --product --segment --external-id --unverified-names; title and product in the table. Rows a server returns without applying a filter are dropped and reported. - leads import <csv|json> --board <id> [--dry-run] [--json] [--map col=field] [--set field=value]: chunks of 1000 to POST /api/v1/leads/import, totals with file row numbers for failures, non-zero exit on any failure. Apollo rows: first_name + last_name_hint -> name, masked hint -> name_verified=false, apollo_id -> external_id apollo:<id>, terra -> iris-terra. Server half is in progress; HTTP tests use a TYPED fake of the agreed contract. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…93513) Co-Authored-By: Claude Opus 5.5 <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Atlas tickets: #193517 (records upsert "Done" on failure), #193510 (title), #193511 (external id), #193512 (product/segment), #193513 (bulk import, CLI side), #193514 (partly hidden names) · parent #193509
Base is
mainbecause platform commands (packages/opencode/src/cli/cmd/) reach the CLI release frommainviasync-iris-v1.ts.1 · #193517:
atlas:datasets records --data <path>records upsert --data <path>read the path as if it were JSON, printed "Invalid JSON", then "Done", and exited 0.addread a path only when it ended in.json.updatenever read a path at all.parseDataArg. It takes inline JSON, an existing file,@file, or~/paths. Reading a file usesloadJsonFile, whichimportuses too. The value must be a JSON object.records add/update/upsert/deletesets exit 1 and prints "Failed", never "Done". That covers auth, parse errors, API errors and thrown errors.importnow also exits 1 when its file is missing, when it can't be parsed, when a chunk fails, or when any row is rejected.2 · Lead fields +
iris leads importleads create/leads update: new flags--title --external-id --product (iris-terra|iris-kinetic|iris-orbit|iris) --segment --name-verified/--no-name-verified.*is sent withname_verified=false.leads list: new filters--title --product --segment --external-id --unverified-names(sent asname_verified=0).leads getshows Title, Product, Segment, External ID and the not-verified warning.--product iris-kineticwould list everyone.leads import <file.csv|file.json> --board <id> [--dry-run] [--json] [--map col=field] [--set field=value] [--external-id-prefix p]:{leads|records|data:[…]}, or an Atlas{external_id,data}export.--mapoverrides that, and--setgives constant values. Columns that aren't imported are listed.POST /api/v1/leads/import. Output: created / merged / failed, with file row and line numbers.dry_rundoesn't match the request, or if created+merged+failed doesn't equal the rows sent.dry_run=trueand prints "DRY RUN — nothing was written".first_name + last_name_hint→ name, a hint containing*→name_verified=false,apollo_id→external_id apollo:<id>(the key the product-leads dataset uses),terra→iris-terra. A masked name is never sent as verified, whatever a column says.How it was verified
bun testacross the leads, atlas-dataset and atlas suites plustest/cli/atlas-json-error-reason: 342 pass, 0 fail, on the merge withorigin/mainat80adef0552.tsgo --noEmitis clean.atlas-records-data-arg.test.ts(9):--data <path>and inline JSON work. Bad JSON, a bad file, a missing file and an API 500 each exit 1, send nothing, and never print "Done".addandupdateare covered the same way.leads-import.test.ts(22): parser, mapping, Apollo rules, flags, filters and the response shape. Commands run through the real yargs tree with fetch stubbed:~/marketing/leads-2026-11-14/terra-leads.csvgave 400 rows → 400 leads, 0 refused. 387 were marked name-not-verified (this matches a Python count of*inlast_name_hint). All 400 haveapollo:<id>external ids, all unique; all areiris-terra; all have a title.Contract points I guessed (backend please confirm)
{data:…}. Both are accepted.failed[].indexis assumed to be the 0-based index within that request'sleadsarray.?name_verified=0for false. Laravel'sbooleanrule rejects the string"false".?title=is checked client-side as a case-insensitive substring. If the server does exact match, that's fine; if it matches more loosely, the guard will drop rows.idsisn't specified. The CLI passes them through and doesn't map them to rows.Not merged, not released. A person merges.
🤖 Generated with Claude Code