Skip to content

Commit 6629dd2

Browse files
authored
docs: remove em-dashes from docs, docstrings and tests (#99)
## Summary Removes every em-dash from the repo: the docs, the doc comments that ship in the published package (and show in editors), code comments and test names. A spaced em-dash became a colon in comments and test names, and a comma or colon in the docs; the two paired dashes around the test-mode outcome list became parentheses. Found in a docs audit across every repo. No runtime string changes, so no release is cut for this; the next release carries it. ## Type of change - [ ] Bug fix (no breaking change) - [ ] New feature (no breaking change) - [ ] Breaking change (existing callers must update) - [x] Docs, tests, or internal maintenance only ## Public API None. Comments and doc text only. ## Test plan Lint, format/type checks and the full test suite run locally, all exit 0. A repo-wide count of em-dashes after the change is 0. ## Checklist - [x] Tests cover the new behavior, and the suite passes locally (no behavior changed; suite passes) - [x] Lint, format, and type checks pass - [x] Docs and README examples updated if the public surface changed - [x] No secrets, credentials, or personal data in the diff or the tests
1 parent dc086e0 commit 6629dd2

8 files changed

Lines changed: 68 additions & 68 deletions

File tree

‎.claude/CLAUDE.md‎

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,22 @@ Python client for the AgentScore APIs.
44

55
## Identity Model
66

7-
Two identity paths: `X-Wallet-Address` (wallet-based) and `X-Operator-Token` (credential-based). Wallet addresses accept both EVM (`0x...` 40-hex) and Solana (base58, 32–44 chars) formats — network is auto-detected from the address shape. `assess` responses include `resolved_operator` and `linked_wallets[]` (same-operator sibling wallets, normalized per network — EVM lowercased, Solana base58 verbatim; may mix chains for cross-chain operators). `create_session` and `create_credential` responses include an `agent_memory` cross-merchant pattern hint. `create_session` also returns `next_steps.action="deliver_verify_url_and_poll"` + polling instructions. `poll_session` returns `next_steps.action` values: `continue_polling`, `retry_merchant_request_with_operator_token`, `use_stored_operator_token`, `create_new_session`, `verification_failed`, `contact_support`.
7+
Two identity paths: `X-Wallet-Address` (wallet-based) and `X-Operator-Token` (credential-based). Wallet addresses accept both EVM (`0x...` 40-hex) and Solana (base58, 32–44 chars) formats; network is auto-detected from the address shape. `assess` responses include `resolved_operator` and `linked_wallets[]` (same-operator sibling wallets, normalized per network, EVM lowercased, Solana base58 verbatim; may mix chains for cross-chain operators). `create_session` and `create_credential` responses include an `agent_memory` cross-merchant pattern hint. `create_session` also returns `next_steps.action="deliver_verify_url_and_poll"` + polling instructions. `poll_session` returns `next_steps.action` values: `continue_polling`, `retry_merchant_request_with_operator_token`, `use_stored_operator_token`, `create_new_session`, `verification_failed`, `contact_support`.
88

99
## Methods (sync + async)
1010

11-
- `assess` / `aassess` — identity gate with policy (paid). Accepts `operator_token` for non-wallet agents. Response includes `linked_wallets[]` and `resolved_operator`. Optional `signer: { address, network }` opts into server-side wallet-signer-match AND OFAC SDN wallet-address screening — the response then carries both a `signer_match` block (wallet-binding verdict: `pass` / `wallet_signer_mismatch` / `wallet_auth_requires_wallet_signing`) and a `signer_sanctions` block (discriminated union: `{status: "clear"}` | `{sanctioned: True, ofac_label, sdn_uid, listed_at}` | `{status: "unavailable"}`). Wallet-OFAC SDN enforcement on the `signer` block is unconditional whenever a signer is supplied — no `policy.require_sanctions_clear` opt-in required. A `sanctioned: True` OR `status: "unavailable"` verdict flips the response `decision` to `deny` with `decision_reasons` including `sanctions_flagged` or `sanctions_check_unavailable` respectively (fail-closed; OFAC strict-liability). `policy.require_sanctions_clear` is the separate NAME-based screen on the resolved operator's KYC identity.
12-
- `create_session` / `acreate_session` — create verification session. Returns `agent_memory` + `next_steps`.
13-
- `poll_session` / `apoll_session` — poll session status, returns credential when verified, plus `next_steps.action`.
14-
- `create_credential` / `acreate_credential` — create operator credential (24h TTL default). Response includes `agent_memory`.
15-
- `list_credentials` / `alist_credentials` — list active credentials
16-
- `revoke_credential` / `arevoke_credential` — revoke a credential
17-
- `associate_wallet` / `aassociate_wallet` — report a signer wallet seen paying under a credential. Accepts optional `idempotency_key` (payment intent id / tx hash) so retries don't inflate transaction_count.
18-
- `telemetry_signer_match` / `atelemetry_signer_match` — fire-and-forget POST to `/v1/telemetry/signer-match`; commerce gate uses this to report `pass` / `wallet_signer_mismatch` / `wallet_auth_requires_wallet_signing` verdicts.
11+
- `assess` / `aassess`: identity gate with policy (paid). Accepts `operator_token` for non-wallet agents. Response includes `linked_wallets[]` and `resolved_operator`. Optional `signer: { address, network }` opts into server-side wallet-signer-match AND OFAC SDN wallet-address screening; the response then carries both a `signer_match` block (wallet-binding verdict: `pass` / `wallet_signer_mismatch` / `wallet_auth_requires_wallet_signing`) and a `signer_sanctions` block (discriminated union: `{status: "clear"}` | `{sanctioned: True, ofac_label, sdn_uid, listed_at}` | `{status: "unavailable"}`). Wallet-OFAC SDN enforcement on the `signer` block is unconditional whenever a signer is supplied, no `policy.require_sanctions_clear` opt-in required. A `sanctioned: True` OR `status: "unavailable"` verdict flips the response `decision` to `deny` with `decision_reasons` including `sanctions_flagged` or `sanctions_check_unavailable` respectively (fail-closed; OFAC strict-liability). `policy.require_sanctions_clear` is the separate NAME-based screen on the resolved operator's KYC identity.
12+
- `create_session` / `acreate_session`: create verification session. Returns `agent_memory` + `next_steps`.
13+
- `poll_session` / `apoll_session`: poll session status, returns credential when verified, plus `next_steps.action`.
14+
- `create_credential` / `acreate_credential`: create operator credential (24h TTL default). Response includes `agent_memory`.
15+
- `list_credentials` / `alist_credentials`: list active credentials
16+
- `revoke_credential` / `arevoke_credential`: revoke a credential
17+
- `associate_wallet` / `aassociate_wallet`: report a signer wallet seen paying under a credential. Accepts optional `idempotency_key` (payment intent id / tx hash) so retries don't inflate transaction_count.
18+
- `telemetry_signer_match` / `atelemetry_signer_match`: fire-and-forget POST to `/v1/telemetry/signer-match`; commerce gate uses this to report `pass` / `wallet_signer_mismatch` / `wallet_auth_requires_wallet_signing` verdicts.
1919

2020
## Errors + observability
2121

22-
Typed error subclasses of `AgentScoreError` so callers can `except` on the specific class without parsing `err.code`: `PaymentRequiredError` (402), `TokenExpiredError` (401 token_expired — exposes parsed `verify_url` / `session_id` / `poll_secret` / `poll_url` / `next_steps` / `agent_memory` instance attributes), `InvalidCredentialError` (401 invalid_credential), `QuotaExceededError` (429 quota_exceeded — don't retry), `RateLimitedError` (429 rate_limited — retry after Retry-After), `TimeoutError` (httpx.TimeoutException — note: subclasses `AgentScoreError`, not the builtin; import explicitly from `agentscore.errors` to disambiguate). All non-timeout `httpx.HTTPError` (ConnectError, ProtocolError, NetworkError, etc.) wrap to `AgentScoreError(code="network_error", status_code=0)` for parity with node-sdk.
22+
Typed error subclasses of `AgentScoreError` so callers can `except` on the specific class without parsing `err.code`: `PaymentRequiredError` (402), `TokenExpiredError` (401 token_expired, exposes parsed `verify_url` / `session_id` / `poll_secret` / `poll_url` / `next_steps` / `agent_memory` instance attributes), `InvalidCredentialError` (401 invalid_credential), `QuotaExceededError` (429 quota_exceeded, don't retry), `RateLimitedError` (429 rate_limited, retry after Retry-After), `TimeoutError` (httpx.TimeoutException, note: subclasses `AgentScoreError`, not the builtin; import explicitly from `agentscore.errors` to disambiguate). All non-timeout `httpx.HTTPError` (ConnectError, ProtocolError, NetworkError, etc.) wrap to `AgentScoreError(code="network_error", status_code=0)` for parity with node-sdk.
2323

2424
`assess()` / `aassess()` responses include an optional `quota` field captured from `X-Quota-Limit` / `X-Quota-Used` / `X-Quota-Reset` response headers, so callers can monitor approach-to-cap proactively before hitting 429.
2525

@@ -34,18 +34,18 @@ Single-package Python library published to PyPI.
3434

3535
## Tooling
3636

37-
- **uv** — package manager. Use `uv sync`, `uv run`.
38-
- **ruff** — linting + formatting. `uv run ruff check .` and `uv run ruff format --check .`.
39-
- **ty** — type checker (Astral). `uv run ty check agentscore/`.
40-
- **vulture** — dead code detection.
41-
- **pytest** — tests. `uv run pytest tests/`.
42-
- **Lefthook** — git hooks. Pre-commit: ruff. Pre-push: ty + vulture (parallel).
37+
- **uv**: package manager. Use `uv sync`, `uv run`.
38+
- **ruff**: linting + formatting. `uv run ruff check .` and `uv run ruff format --check .`.
39+
- **ty**: type checker (Astral). `uv run ty check agentscore/`.
40+
- **vulture**: dead code detection.
41+
- **pytest**: tests. `uv run pytest tests/`.
42+
- **Lefthook**: git hooks. Pre-commit: ruff. Pre-push: ty + vulture (parallel).
4343

4444
## Key Commands
4545

4646
```bash
4747
uv sync --all-extras
48-
uv run lefthook install # one-time per clone — wires pre-commit + pre-push
48+
uv run lefthook install # one-time per clone, wires pre-commit + pre-push
4949
uv run ruff check .
5050
uv run ruff format .
5151
uv run ty check agentscore/
@@ -57,14 +57,14 @@ uv run pytest tests/
5757
1. Create a branch
5858
2. Make changes
5959
3. Lefthook runs ruff on commit, ty + vulture on push
60-
4. Open a PR — CI runs automatically
60+
4. Open a PR, CI runs automatically
6161
5. Merge (squash)
6262

6363
## Rules
6464

6565
- **No silent refactors**
6666
- **Never commit .env files or secrets**
67-
- **Use PRs** — never push directly to main
67+
- **Use PRs**: never push directly to main
6868

6969
## Releasing
7070

‎agentscore/client.py‎

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ def _build_error_from_response(response: httpx.Response) -> AgentScoreError:
111111
# verify_url, linked_wallets, reasons, etc. for granular denial recovery.
112112
details = {k: v for k, v in body.items() if k != "error"}
113113
except ValueError:
114-
# Body wasn't JSON or didn't have the expected shape — keep defaults.
114+
# Body wasn't JSON or didn't have the expected shape: keep defaults.
115115
pass
116116

117117
if response.status_code == 402:
@@ -304,7 +304,7 @@ def create_session(
304304
"""Create a verification or sign-in session.
305305
306306
``address`` pre-associates the session with a known wallet (EVM ``0x...`` or
307-
Solana base58). ``operator_token`` pre-associates with an existing ``opc_...`` —
307+
Solana base58). ``operator_token`` pre-associates with an existing ``opc_...``:
308308
e.g. refresh KYC for a credential. ``kind`` selects the session kind: ``"kyc"``
309309
(the API default) runs identity verification; ``"sign_in"`` is registration-only
310310
(the buyer signs in with an AgentScore account, no identity documents) and mints a
@@ -368,20 +368,20 @@ def associate_wallet(
368368
) -> AssociateWalletResponse:
369369
"""Report that a wallet paid under an operator credential.
370370
371-
``network`` is the key-derivation family (``"evm"`` or ``"solana"``) — EVM EOAs share
371+
``network`` is the key-derivation family (``"evm"`` or ``"solana"``): EVM EOAs share
372372
identity across every EVM chain (Base, Tempo, Ethereum, …) so one value covers them all.
373373
374-
``idempotency_key`` is optional — pass a stable per-payment key (e.g., payment intent id,
374+
``idempotency_key`` is optional: pass a stable per-payment key (e.g., payment intent id,
375375
x402 tx hash) so agent retries of the same logical payment don't inflate transaction_count.
376376
377-
Fire-and-forget friendly — the returned ``first_seen`` boolean is informational only.
377+
Fire-and-forget friendly: the returned ``first_seen`` boolean is informational only.
378378
"""
379379
body: dict[str, Any] = {
380380
"operator_token": operator_token,
381381
"wallet_address": wallet_address,
382382
"network": network,
383383
}
384-
# Truthy check (not `is not None`) so empty strings don't ship a useless key —
384+
# Truthy check (not `is not None`) so empty strings don't ship a useless key:
385385
# only forward when the key actually has content.
386386
if idempotency_key:
387387
if len(idempotency_key) > _IDEMPOTENCY_KEY_MAX:
@@ -446,7 +446,7 @@ async def acreate_session(
446446
"""Create a verification or sign-in session.
447447
448448
``address`` pre-associates the session with a known wallet (EVM ``0x...`` or
449-
Solana base58). ``operator_token`` pre-associates with an existing ``opc_...`` —
449+
Solana base58). ``operator_token`` pre-associates with an existing ``opc_...``:
450450
e.g. refresh KYC for a credential. ``kind`` selects the session kind: ``"kyc"``
451451
(the API default) runs identity verification; ``"sign_in"`` is registration-only
452452
(the buyer signs in with an AgentScore account, no identity documents) and mints a
@@ -514,7 +514,7 @@ async def aassociate_wallet(
514514
"wallet_address": wallet_address,
515515
"network": network,
516516
}
517-
# Truthy check (not `is not None`) so empty strings don't ship a useless key —
517+
# Truthy check (not `is not None`) so empty strings don't ship a useless key:
518518
# only forward when the key actually has content.
519519
if idempotency_key:
520520
if len(idempotency_key) > _IDEMPOTENCY_KEY_MAX:
@@ -527,7 +527,7 @@ async def aassociate_wallet(
527527
return await self._send_async(lambda: client.post("/v1/credentials/wallets", json=body))
528528

529529
def telemetry_signer_match(self, payload: dict[str, Any]) -> None:
530-
"""Fire-and-forget telemetry — report a wallet-signer-match verdict.
530+
"""Fire-and-forget telemetry: report a wallet-signer-match verdict.
531531
532532
Tracks aggregate signer-binding behavior across merchants. Does not raise;
533533
failures are logged at warning level so persistent telemetry outages are visible

‎agentscore/errors.py‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ def __init__(
1212
super().__init__(message)
1313
self.code = code
1414
self.status_code = status_code
15-
# Response-body fields beyond `error.{code,message}` — e.g. verify_url,
15+
# Response-body fields beyond `error.{code,message}`: e.g. verify_url,
1616
# linked_wallets, claimed_operator, actual_signer, reasons. Consumers
1717
# branch on these for granular recovery. Defaults to {} so callers
1818
# constructing this error by hand without a body can omit it.
@@ -25,17 +25,17 @@ def status(self) -> int:
2525

2626

2727
class PaymentRequiredError(AgentScoreError):
28-
"""HTTP 402 — the endpoint is not enabled for this account."""
28+
"""HTTP 402: the endpoint is not enabled for this account."""
2929

3030
def __init__(self, message: str, details: dict[str, Any] | None = None) -> None:
3131
super().__init__("payment_required", message, 402, details)
3232

3333

3434
class TokenExpiredError(AgentScoreError):
35-
"""HTTP 401 with ``error.code = 'token_expired'`` — credential is no longer valid.
35+
"""HTTP 401 with ``error.code = 'token_expired'``: credential is no longer valid.
3636
3737
Covers both revoked and TTL-expired credentials; the API does not distinguish
38-
which. Body carries an auto-minted verification session — exposed here so callers recover
38+
which. Body carries an auto-minted verification session: exposed here so callers recover
3939
without re-parsing ``details``.
4040
"""
4141

@@ -51,7 +51,7 @@ def __init__(self, message: str, details: dict[str, Any] | None = None) -> None:
5151

5252

5353
class InvalidCredentialError(AgentScoreError):
54-
"""HTTP 401 with ``error.code = 'invalid_credential'`` — operator_token doesn't exist.
54+
"""HTTP 401 with ``error.code = 'invalid_credential'``: operator_token doesn't exist.
5555
5656
Permanent: no auto-session is issued. Caller should switch tokens or restart.
5757
"""
@@ -61,7 +61,7 @@ def __init__(self, message: str, details: dict[str, Any] | None = None) -> None:
6161

6262

6363
class QuotaExceededError(AgentScoreError):
64-
"""HTTP 429 with ``error.code = 'quota_exceeded'`` — account-level cap reached.
64+
"""HTTP 429 with ``error.code = 'quota_exceeded'``: account-level cap reached.
6565
6666
Don't retry; the cap won't lift through retry alone. Distinct from per-second
6767
:class:`RateLimitedError`.
@@ -72,7 +72,7 @@ def __init__(self, message: str, details: dict[str, Any] | None = None) -> None:
7272

7373

7474
class RateLimitedError(AgentScoreError):
75-
"""HTTP 429 with ``error.code = 'rate_limited'`` — per-second sliding-window cap hit.
75+
"""HTTP 429 with ``error.code = 'rate_limited'``: per-second sliding-window cap hit.
7676
7777
Retry after the interval indicated by the ``Retry-After`` header (typically <= 1s).
7878
"""

‎agentscore/test_mode.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
AgentScore's ``/v1/assess`` endpoint recognizes seven EVM addresses
44
(``0x0000…0001`` through ``0x0000…0007``) as test fixtures with deterministic
5-
policy outcomes — KYC verified, sanctions clear, age gates passing — so dev/test
5+
policy outcomes (KYC verified, sanctions clear, age gates passing) so dev/test
66
interactions don't burn real KYC credits and produce predictable results.
77
88
Use this in test suites and dev/staging tooling to label test-mode interactions

0 commit comments

Comments
 (0)