Skip to content

fix(ingest): rewrite only the host when normalizing a tweet URL for oEmbed - #3880

Closed
Dakshcore wants to merge 1 commit into
Graphify-Labs:v8from
Dakshcore:fix/tweet-oembed-host-only
Closed

Dakshcore wants to merge 1 commit into
Graphify-Labs:v8from
Dakshcore:fix/tweet-oembed-host-only

Conversation

@Dakshcore

Copy link
Copy Markdown
Contributor

What does this PR do?

_fetch_tweet normalized a tweet URL for oEmbed with url.replace("x.com", "twitter.com") over the whole URL. This is the same bug class dd65345 fixed in _detect_url_type ("classify a URL by its host, not by text it contains"):

  • "x.com" in the path or query was rewritten too: a ?next=https://x.com/... link was changed, and a handle like dropbox.com_fan became dropbotwitter.com_fan, so oEmbed was asked about a different URL.
  • An uppercase X.COM host was missed, since the replace is case-sensitive.

It now parses the URL and rewrites the host only, reusing the _host_is helper from _detect_url_type (so x.com and its subdomains, e.g. mobile.x.com -> mobile.twitter.com).

Split out of #3879 per the one-concern-per-PR rule.

Type of change

  • Bug fix
  • New feature
  • Documentation
  • Tests or CI
  • Refactor
  • Security fix

Verification & Invariants

Invariant: the URL sent to oEmbed differs from the input only in its host.

Persisted state: none. The change only affects the outgoing oEmbed request; the saved note still records the original URL.

  • Read the CONTRIBUTING.md guide.
  • Reproduced the issue and identified the invariant.
  • Made the smallest fix necessary.
  • Added a regression test (if bug fix) or isolated boundary test.
  • Kept the PR description synchronized with the final implementation.
  • Documented any limitations / unsupported cases explicitly.

Limitations: when the host is rewritten, any userinfo (user@) in the netloc is dropped; the port is kept. oEmbed does not use either.

How was this tested?

Windows 11, Python 3.13, fresh venv with pip install -e . ruff pytest.

# New test; 3 of its 5 cases fail with url.replace("x.com", "twitter.com") restored:
pytest tests/test_ingest_url_type.py::test_tweet_oembed_rewrites_only_the_host

pytest tests/test_ingest_url_type.py tests/test_ingest.py
    -> 36 passed
ruff check graphify/ingest.py tests/test_ingest_url_type.py
    -> All checks passed

Graphify-specific checklist

  • I updated generated skill artifacts (uv run python -m tools.skillgen --bless) when changing their source fragments. (N/A: no skill fragments changed; skillgen --check passed in pre-commit.)
  • I confirmed that AST/structural extraction remains deterministic (no ambient state dependencies like ENV variables).
  • I reviewed changes for security implications (no unsafe interpolation into shell/Python).
  • I confirmed no API keys or local-only graph data are included.
  • (If applicable) I disclosed AI authorship in my commit messages. (Co-Authored-By: Claude Opus 5.5 trailer.)

…Embed

_fetch_tweet did url.replace("x.com", "twitter.com") over the whole URL,
so "x.com" in the path or query was rewritten too (a ?next= link, or a
handle like dropbox.com_fan becoming dropbotwitter.com_fan), and an
uppercase X.COM host was missed. Match and rewrite the host only, the
same way _detect_url_type classifies it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Thanks for the pull request, @Dakshcore. A maintainer will review it soon.

Want to talk it through while it is in review? Come join us on our Discord server. For longer-form discussion there is also GitHub Discussions.

A couple of things that speed up review: make sure the test suite passes on Python 3.10 and 3.13, and that the change keeps extraction deterministic.

@graphify-labs graphify-labs Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Graphify reviewed this change.

Looks safe to merge — no coupling regressions and no blocking issues, checked against the code graph (not a self-assessment).

Formal verification. No changes could be formally verified in this run.


Graphify review — findings

Fixes the tweet oEmbed host rewrite in _fetch_tweet to swap only the URL host from x.com to twitter.com, so x.com occurrences in the path or query (e.g. a ?next= link or a dropbox.com_fan handle) are left intact instead of being clobbered by a whole-string replace. The rewrite now parses the URL, matches the host via _host_is (case-insensitive, subdomains like mobile.x.com), and preserves any port. Adds parametrized tests asserting the oEmbed request URL is rewritten host-only.

No blocking issues surfaced. 4 lower-confidence candidates did not survive cross-model review.

Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 233 functions depend on the 35 functions this change touches.

Health — this change adds coupling hotspots:

  • new: main() — 98 callers, 3 callees
  • new: dispatch_command() — 2 callers, 125 callees
  • new: ingest() — 4 callers, 8 callees
  • new: test_poisoned_manifest_is_healed() — 0 callers, 6 callees
  • new: test_lessons_artifact_cannot_be_globbed_back_into_memory() — 0 callers, 6 callees

Verification — 233 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 59 function(s) in the blast radius were not formally verified this run

Test selection

Test selection

3 of 302 test file(s) selected (1%) via static blast radius.

  • tests/test_ingest.py — impact
  • tests/test_ingest_url_type.py — impact, changed-test
  • tests/test_reflect.py — impact

Selection is safe under the controlled-regression assumption; always-run tests + a periodic full run are the backstops. Advisory — it never changes the check verdict.

Formal verification

Could not verify: Could not verify \_fetch\_tweet.

The verifier did not have enough to check \_fetch\_tweet, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: no capturable inputs from the test suite; property tier: not verifiable: all 200 sampled inputs raised on both versions — the function never executed, so 'no divergence' would be vacuous (mostly non-reproducing divergences under module context — load-time entropy, never a sound refutation — names the real obstacle, not a sampling gap)

· 5 more finding(s) on lines outside this diff (see the check run).

safishamsi added a commit that referenced this pull request Sep 28, 2026
SQL triggers (#3863), Groovy enums (#3861), R namespace-qualified
constructors (#3864) and R6 self$/private$ calls (#3865), markdown
wikilink index ignore-rules (#3826), foreign manifest key syntax (#3879),
tweet oEmbed host-only rewrite (#3880), and the refreshed install banner
(#3892).

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

Copy link
Copy Markdown
Collaborator

Shipped in v0.9.71 (now on PyPI) via an authorship-preserving cherry-pick, so your commit keeps contributor-graph credit. Thanks @Dakshcore! Tweet oEmbed normalization now rewrites only the host.

Release: https://github.com/Graphify-Labs/graphify/releases/tag/v0.9.71

@safishamsi safishamsi closed this Sep 28, 2026
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.

2 participants