Skip to content

docs: rebrand QURL → qURL across user-facing surfaces#40

Merged
justin-layerv merged 2 commits into
mainfrom
chore/qurl-rebrand
Apr 25, 2026
Merged

docs: rebrand QURL → qURL across user-facing surfaces#40
justin-layerv merged 2 commits into
mainfrom
chore/qurl-rebrand

Conversation

@justin-layerv
Copy link
Copy Markdown
Contributor

Summary

Updates the brand spelling to qURL (case-sensitive) across user-visible strings, documentation, docstrings, and LangChain tool descriptions/response messages.

Why

The product brand is qURL. README, the pyproject.toml description shown on PyPI, public docstrings (which AI agents and IDEs surface via help() / hover), and the LangChain tool descriptions/responses were inconsistently spelled QURL / Qurl. This PR brings them in line.

What changed

  • README.md, CLAUDE.md, pyproject.toml description
  • Module/class/function docstrings (sync + async clients, types, errors, langchain)
  • LangChain tool description: strings and human-readable responses (e.g. qURL r_… has been revoked., No qURLs found.)
  • CI workflow Slack notify header
  • Test docstring + one assertion updated in lockstep with the source string change

What was intentionally not changed

Identifier-style references kept as-is (changing them would break the public Python API):

  • Class names: QURL, QURLClient, AsyncQURLClient, QURLError, QURLNetworkError, QURLTimeoutError, QURLValidationError, QURLAuthError, QURLAuthorizationError, QURLRateLimitError, QURLNotFoundError, QURLConflictError, QURLAPIError, QURLToolkit, CreateQURLTool, ResolveQURLTool, ListQURLsTool, DeleteQURLTool
  • Type aliases: QURLStatus, TokenStatus
  • Field/attribute names: qurl_id, qurl_link, qurl_site, qurl_count, active_qurls, qurls_created, max_active_qurls, max_tokens_per_qurl
  • pip package name (layerv-qurl), Python module name (layerv_qurl)
  • Tool names exposed to LangChain agents: create_qurl, resolve_qurl, list_qurls, delete_qurl
  • OpenAPI schema references in docstrings: CreateQurlRequest, UpdateQurlRequest, QurlData.status, QurlSummary.status
  • Repo URLs and slugs

A few test fixtures keep the old casing in mock detail strings ("QURL not found") that mirror upstream API responses — these will be updated alongside the upstream API rebrand to keep mocks accurate.

Test plan

  • ruff check src/ clean
  • mypy src/ clean (no new issues)
  • pytest tests/ — 158/158 pass
  • Grep verification: no QURL / Qurl left in prose contexts (only identifiers and qurl_* attribute names remain)

Updates the brand spelling to qURL (case-sensitive) in user-visible
strings, documentation, code comments, docstrings, and LangChain tool
descriptions/responses.

Scope:
- README.md, CLAUDE.md, pyproject.toml description
- Module/class/function docstrings (sync + async clients, types,
  errors, langchain)
- LangChain tool descriptions, response strings
  (e.g. "qURL r_… has been revoked.", "No qURLs found.")
- CI status header in Slack notify step
- Test docstring + assertion updated in lockstep

Identifiers, paths, and config keys are intentionally untouched:
- Class names: QURL, QURLClient, AsyncQURLClient, QURLError,
  QURLNetworkError, QURLTimeoutError, QURLToolkit, CreateQURLTool, …
- Type aliases: QURLStatus, TokenStatus
- Field names: qurl_id, qurl_link, qurl_site, qurl_count,
  active_qurls, qurls_created, max_active_qurls, …
- pip package name (layerv-qurl), module name (layerv_qurl)
- Tool names (create_qurl, resolve_qurl, list_qurls, delete_qurl)
- OpenAPI schema references (CreateQurlRequest, UpdateQurlRequest,
  QurlData.status, QurlSummary.status)
- Repo URLs and slugs

A few test fixtures keep "QURL" (mock error `detail` strings that
mirror upstream API responses) — these will be updated alongside the
upstream qurl-service rebrand to keep mocks accurate.

Verified: ruff, mypy, and 158 pytest tests all pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@justin-layerv
Copy link
Copy Markdown
Contributor Author

/simplify result: clean

3-agent review (reuse, quality, efficiency) all returned clean.

  • Reuse: sync client.py and async_client.py docstrings stay mirrored; identifiers (QURLClient, QURLError, QURLStatus, QurlData, layerv-qurl, qurl_* attributes) correctly preserved.
  • Quality: ~100 brand-copy literals don't warrant a shared constant. Test assertions kept in lockstep with source strings.
  • Efficiency: zero runtime impact.

Waiting on cr next.

@claude
Copy link
Copy Markdown

claude Bot commented Apr 25, 2026

Review — docs: rebrand QURL → qURL

Nice, tightly scoped PR. The "What was intentionally not changed" section is the standout — explicitly listing the public-API identifiers (QURL, QURLClient, QURLError, etc.) and qurl_* field names that were left alone makes this trivial to verify and rules out an accidental SemVer break.

Code quality

  • Pure user-visible string replacement; no behavior change. ✅
  • Identifier preservation is consistent across __init__.py __all__, class names, type aliases, and dataclass field names — public API stays intact. ✅
  • LangChain name: attributes (create_qurl, resolve_qurl, …) correctly left untouched — these are stable tool identifiers that downstream agent code keys off.
  • The PyPI description change in pyproject.toml will only surface on the next release publish (heads-up, not a blocker — Release Please will pick it up automatically).

Potential bugs / issues

  • Test assertions: only one exact-match assertion needed updating (tests/test_langchain.py test_list_qurls_tool_empty"No qURLs found."), and it's correctly updated in lockstep. The other LangChain tests use loose substring assertions ("revoked" in result, resource_id substrings), so the "Created qURL …" and "qURL … has been revoked." string changes won't break them. ✅
  • Mock fixtures keeping "detail": "QURL not found" in tests/test_client.py (lines 626, 1415, 2872) — agreed this is the right call for now: the mocks should mirror what the API actually returns. Worth tracking these as a follow-up so they don't drift indefinitely after the upstream rebrand lands.
  • LangChain tool description: strings get surfaced verbatim to LLM agents during tool selection — keeping these consistent with the brand actually has functional value beyond cosmetics, since agents reason over the description text. Good catch including those.

Performance

N/A — strings only.

Security

N/A — no auth, validation, or network paths touched.

Test coverage

  • 158/158 existing tests pass per the PR description; spot-checked the assertion-string surface and confirmed nothing else needs to flip.
  • No new tests required for a docstring rebrand.

Nits (optional, non-blocking)

  • errors.py example: except NotFoundError: print("qURL doesn't exist") reads slightly oddly mid-sentence (qURL at the start of a sentence). Trivially defensible either way; leave as-is.
  • Worth a quick grep -i 'qurl' sweep on CHANGELOG.md / Release Please config if they contain any human-prose strings — but I don't see those changed here, so likely a non-issue.

Verdict

LGTM. Low-risk, well-bounded, and the boundary between "user-facing prose" and "stable identifier" is drawn carefully.

@justin-layerv
Copy link
Copy Markdown
Contributor Author

Thanks — /cr is LGTM. Walking through the notes:

  1. errors.py example wording — the print("qURL doesn't exist") line reads slightly oddly mid-sentence; reviewer's verdict was "leave as-is". Keeping.
  2. grep -i 'qurl' sweep on CHANGELOG.md / release-please-config.json — verified, both clean. No prose mentions present.
  3. Mock fixtures ("detail": "QURL not found") — tracked as a follow-up to update alongside the upstream qurl-service rebrand to keep mocks accurate.
  4. PyPI description lag until next release-please cut — expected, no action needed.

PR is merge-ready: builds green, /simplify clean, /cr approved.

…ject

Adds ™ on first prominent mention (README opener, pyproject.toml
description shown on PyPI) and the portal positioning tagline as a
README blockquote. Body prose, docstrings, error messages stay plain.

158 tests still pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@claude
Copy link
Copy Markdown

claude Bot commented Apr 25, 2026

Review

Tight, surgical rebrand — strings only, identifiers preserved, tests updated in lockstep with the one source-string change. PR body's "what was intentionally not changed" section is exactly the right level of detail. ✅

Strengths

  • Public API (class names, type aliases, qurl_* attribute names) untouched — no breaking change for SDK consumers.
  • LangChain description: fields get a real behavioral upside: the tool-selection layer in agents reads these strings, so consistent branding in tool descriptions is genuinely user-facing.
  • tests/test_langchain.py:125 assertion correctly updated alongside langchain.py:105.
  • parse_qurl docstring updated; the Python identifier QURL (class) correctly left alone.

Things worth a second look

1. pyproject.toml description is doing more than a rebrand

-description = "Python SDK for the QURL API - secure, time-limited access links"
+description = "Python SDK for the qURL™ API — secure, time-limited access links. Quantum URL is how you enter the hidden layer of the internet."

This is the package summary surfaced on PyPI search results, pip show, and IDE hover. Three things changed beyond casing: was added, ASCII hyphen → em-dash, and a marketing tagline was appended. None are bugs, but:

  • The tagline ("how you enter the hidden layer of the internet") is a tonal shift from the prior purely technical summary. Worth a deliberate "yes, that's the PyPI blurb we want."
  • This is the only place in the SDK that introduces . Everywhere else (docstrings, LangChain descriptions, error prose, README body) uses plain qURL. The README has qURL™ API once in the lede, then drops the ™. That's a defensible "trademark symbol on first/canonical mention only" convention — but since this is the start of the formal brand rollout, it might be worth writing that convention down somewhere (e.g., a one-liner in CLAUDE.md) so future contributors don't sprinkle ™ inconsistently.

2. Stale-cased mock fixtures

tests/test_client.py lines 626, 1415, 2872 keep "detail": "QURL not found" to mirror upstream. PR description acknowledges this — fair. Two minor suggestions:

  • Add a brief comment at one of the fixture sites (or a shared fixture helper) noting that the casing intentionally tracks the upstream API and shouldn't be "fixed" by a future grep-and-replace pass.
  • These mocks no longer reflect what the upstream API will actually return after its own rebrand. They'll keep passing regardless of the real response casing, so the SDK won't catch a wire-format drift via tests. Low risk for a string-only field, but worth knowing.

3. Minor inconsistency

In LangChain tool responses:

  • langchain.py:64f"Created qURL {result.resource_id}" (no r_… formatting)
  • langchain.py:125f"qURL {resource_id} has been revoked."

PR description references qURL r_… has been revoked. but the actual code is qURL {resource_id} has been revoked. — the format string just interpolates whatever the caller passed. Not a bug, just a description-vs-code drift in the PR write-up.

Bugs / perf / security

Nothing. Pure string change, no behavioral surface touched, no injection vectors, no hot paths affected.

Test coverage

Adequate for the scope. The one user-facing string with an assertion ("No qURLs found.") is covered. Other changed strings (LangChain descriptions, error docstrings) don't have assertions and don't need them.

Bottom line

LGTM modulo a sanity check on the new PyPI description tagline (point 1) — that one's a product/marketing call more than an engineering one.

@justin-layerv
Copy link
Copy Markdown
Contributor Author

Extended scope: added qURL™ at the README opener (first prominent mention) and the portal tagline **Quantum URL (qURL)** · The internet has a hidden layer. This is how you enter. as a blockquote. Body prose, code, doc comments, error strings stay plain qURL — ™ on every occurrence is legally unnecessary and visually noisy. Build + tests still pass.

@justin-layerv justin-layerv merged commit 9c88024 into main Apr 25, 2026
11 checks passed
@justin-layerv justin-layerv deleted the chore/qurl-rebrand branch April 25, 2026 17:04
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