Skip to content

feat!: rename find-by-linkedin to upsert-by-linkedin (breaking, v1.0.0) - #5

Merged
jschfflr merged 3 commits into
mainfrom
feat/upsert-by-linkedin
Jul 1, 2026
Merged

feat!: rename find-by-linkedin to upsert-by-linkedin (breaking, v1.0.0)#5
jschfflr merged 3 commits into
mainfrom
feat/upsert-by-linkedin

Conversation

@jschfflr

@jschfflr jschfflr commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Stacked on #4 (the URL-canonicalization fix) — this base will retarget to main once #4 merges.

Why

find-by-linkedin's name never matched its purpose. It conflated a read (find) with a write (--create) under a read verb, returned a bare contact_id (forcing a second call), treated the normal "not in the CRM yet" outcome as an exit-1 error, and overlapped confusingly with search --linkedin-url (its tier-1 was literally the same query). The half that justified the command's existence — create-if-missing — wasn't in the name.

What

Replace it with contacts upsert-by-linkedin — an honest get-or-create:

  • returns the full contact + a created flag (not a bare id),
  • a missing contact is a normal result, not an error; --name is required to create,
  • name-searches before creating to avoid duplicating a contact stored under a drifted URL,
  • read-only lookups now use contacts search --linkedin-url (the one true read path).

Breaking

  • contacts find-by-linkedin and its --create flag are removed (no back-compat, per request).
  • Version bumped 0.1.0 → 1.0.0.
  • Docs updated: SKILL.md, contact-workflows.md, README.md, CHANGELOG.md.

Tests

  • 4 new command tests (existing / create / name-required / dedup) replace the old find test.
  • Full suite: 43 passed; ruff + mypy clean.

🤖 Generated with Claude Code

@jschfflr
jschfflr force-pushed the fix/linkedin-url-exact-match branch from 4d2ddc0 to e2fc09b Compare July 1, 2026 21:54
jschfflr and others added 2 commits July 1, 2026 23:56
find-by-linkedin conflated a read (find) with a write (--create) under a read verb,
returned a bare id, treated the normal "not in CRM" outcome as an exit-1 error, and
overlapped confusingly with `search --linkedin-url`.

Replace it with `contacts upsert-by-linkedin` (honest get-or-create):
- returns the full contact + a `created` flag (not a bare contact_id)
- a missing contact is a normal result, not an error; --name is required to create
- name-searches before creating to avoid duplicating a contact stored under a different URL
- read-only lookups now use `contacts search --linkedin-url`

BREAKING: find-by-linkedin and its --create flag are removed. Bumps to 1.0.0.
Updates SKILL.md / references / README and the CHANGELOG.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… lowercasing

- require a full "First Last" to create; a single-word --name previously created a
  contact with an empty last name (silent, untested). + test.
- canonicalizer lowercases the whole slug (was %hex-only) so a mixed-case slug matches
  Apollo's lowercase storage; also simpler (drops the _PCT_RE pass). + test.
- upsert renders the contact via format_contact_detail — consistent with get/create/update
  (generic_markdown silently dropped nested contact fields).
- upsert command tests now use real Contact pydantic models, exercising the actual
  serialization path (previously plain dicts / MagicMock gave false confidence).
- polish: _format_upsert_result typed dict[str, Any]; comment noting first-match is intentional.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jschfflr
jschfflr force-pushed the feat/upsert-by-linkedin branch from 36c89fe to bc13cac Compare July 1, 2026 22:01
@jschfflr
jschfflr changed the base branch from fix/linkedin-url-exact-match to main July 1, 2026 22:01
…nto main

Rebasing onto main (which gained #2 notes + #3 parse_comma_list) left duplicate
CHANGELOG headings; consolidate into one Added/Changed/Removed/Fixed set for 1.0.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jschfflr
jschfflr force-pushed the feat/upsert-by-linkedin branch from bc13cac to 95762b1 Compare July 1, 2026 22:07
@jschfflr
jschfflr merged commit 7f53e0d into main Jul 1, 2026
3 checks passed
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