Changelog¶
All notable changes to swarph-mesh are documented in this file.
The format follows Keep a Changelog, and this project adheres to Semantic Versioning per the policy in DEPRECATIONS.md.
swarph-mesh is the graph-protocol substrate for the swarph-mesh ecosystem — every CLI is a node, the LLMAdapter Protocol is the third-party node-implementer contract. Changes to that contract follow strict policy; ordinary feature additions follow ordinary semver.
[Unreleased]¶
Foundations sprint queue (per drop DM #745 + #751 ordering)¶
Renumber note (2026-05-21): the queued node-implementer guide slot shifted v0.7.5 → v0.7.6 (and transport-agnostic mesh → v0.7.7) because v0.7.5 shipped the GeminiCLIAdapter — built, tested, and ready ahead of the guide. Shipped-and-tested takes the lower number; the planned ordering below is otherwise unchanged.
v0.7.6 — Node-implementer guide (
docs/becoming-a-node.md) + protocol-stability test ratchet (mypy strict expanded one module)[Mesh-as-OS PLAN.md §X draft slot] — service-mode LLM workers + ephemeral CLI clients per commander chimes 2026-05-09; auth-surface-minimization framing per drop DM #761; targets slot between v0.7.6 + v0.7.7
v0.7.7+ — Transport-agnostic mesh (Tailscale optional; mTLS + WireGuard + cloud VPN paths) — pairs with commander’s parallel
/btwsession on mesh-of-meshes federation; load-bearing prereq for mesh-as-OS service-worker cross-host dispatch
[0.7.7] — 2026-05-23¶
Added¶
AntigravityAdapter—provider="antigravity"— firejail-sandboxedagy -psubscription path (gemini-3.5-flash), the successor toGeminiCLIAdapterfor Google’s June-2026 gemini-CLI discontinuation. agy reuses~/.gemini/antigravity-cli/antigravity-oauth-token(subscription,cost_usd=0.0) and unlocks 3.5-flash (preview-gated on the old gemini CLI).Security — agy is agentic. Spike found
agy -pauto-fires fs/bash tools, has no--no-toolsflag, and--sandboxdoesn’t contain the filesystem. So every call runs inside a firejail OS sandbox whitelisting only agy’s binary + its~/.gemini/antigravity-cliruntime dir,--caps.drop=all --nonewprivs --noroot --seccomp --private-tmp. Verified: a read outside the whitelist is BLOCKED; the LLM call still works. fs blast-radius sealed. Residual (accepted v1): network egress stays open (the LLM call needs 443) — documented.Billing-leak guard extended:
scrub_env_for_subprocessstrips*_API_KEYby suffix but missedGOOGLE_APPLICATION_CREDENTIALS+ project vars (GOOGLE_CLOUD_PROJECT,VERTEX_*); the adapter strips them explicitly so no metered Vertex/GCP fallback can fire.Per-call audit log (rollout-observation):
{ts, prompt_sha8, exit, duration, resp_len, timed_out, stderr_tail}toswarph_audit.jsonl. firejail--traceis seccomp-incompatible, so observation happens at the adapter layer (semantic signal > syscall noise). 14 unit tests.Dual-runs with
gemini-cliuntil the June EOL; AI²-reviewed end-to-end with droplet (DMs #1383–#1391).
Version drift fix:
__init__.__version__was stale at 0.7.4 (the 0.7.5/0.7.6 publishes bumped onlypyproject); now synced to 0.7.7.
[0.7.6] — 2026-05-21¶
Changed¶
GeminiCLIAdapterdefault model pinned togemini-2.5-flash(was: empty string → let the CLI pick). The CLI’s own default routes togemini-3-flash-preview, and the whole gemini-3.x Flash line (incl. the just-released 3.5 Flash, 2026-05-19) is Preview status — throttle-prone + timeout-prone on the subscription tier (observed: intermittent 30s+ timeouts even back-to-back). Pinning the GA model gives workers a stable, reliable default. Override anytime with no redeploy viaGEMINI_SUBSCRIPTION_MODEL(e.g. set it to a 3.5 Flash preview id once it graduates to GA / is enabled on your subscription).
[0.7.5] — 2026-05-21¶
Added¶
GeminiCLIAdapter—provider="gemini-cli"— subscription-billed Gemini via thegeminiCLI binary (gemini -p -o json), the Google mirror ofClaudeAdapter’sclaude -ppath. Reads~/.gemini/oauth_creds.json(the CLI’s OAuth login) and bills flat-rate through the user’s Google subscription —cost_usd=0.0,raw_response["billing_path"]="subscription". Metered-equivalent cost preserved inraw_response["api_metered_cost_usd"]for subscription-savings auditing.Billing-leak prevention —
GEMINI_API_KEY/GOOGLE_API_KEYare scrubbed from the subprocess env viaswarph_shared.scrub_env_for_subprocess(explicit denylist +*_API_KEYsuffix), so a key sitting in the env can’t silently flip the CLI to metered billing. Proven: invoking withGEMINI_API_KEY=LEAK_CANARYin the env still bills subscription.Token accounting —
_aggregate_tokenssumsprompt(input) +candidates(output) +cachedacross every model instats.models(the CLI may route a utility model plus the main model per call).Why a new provider name, not a replacement for
gemini— the metered SDK path (provider="gemini"→GenAIBridge, Flex rebate + Pro context caching) stays the default. Subscription billing is opt-in via--provider gemini-cliso no caller is silently re-routed onto a personal Google subscription.21 unit tests (
tests/test_gemini_cli_adapter.py), offline-mocked, mirroring the Claude adapter test layout.
[0.7.4] — 2026-05-09¶
Added¶
Coverage publication via Codecov — pytest-cov branch + line coverage measured in CI on the 3.13 matrix arm, uploaded via
codecov/codecov-action@v4. Public repo (flipped 2026-05-09 by commander auth) means no token required.codecov.yml— coverage policy mirrorsDEPRECATIONS.mdtier discipline:Project regression tolerance: 1% drop while we ratchet upward (auto-target)
Patch coverage gate at 70% — new code in a PR must be covered; old uncovered code is grandfathered, fresh uncovered code blocks merge
Components grouped by Tier (Tier 1 Protocol / Tier 1 discovery / Tier 2 SwarphCall+hooks+attribution / Tier 3 adapters) so the dashboard mirrors the contract taxonomy
Ignored: tests/,
__init__.py(re-exports),_build/,docs/
Coverage badges in README.md — PyPI version + Python pyversions + docs site link + Codecov + MIT license
pytest-cov>=4.0added to[project.optional-dependencies] dev
Notes¶
Baseline coverage at v0.7.4: 90.0% line / 87.6% branch across 1316 statements, 330 branches. Per-module: 100% types/exceptions/hooks/mesh_types, 96% mesh_client, 93% gemini/swarph_call, 92% deepseek, 91% json_harness, 88% grok, 87% discovery, 86% openai, 83% claude, 98% attribution.
The 5th hardening dimension after v0.7.3 (doc-surface) is now coverage-surface lockstep — Codecov patch gate forces fresh code to be tested at PR time, same enforcement-at-merge-time pattern as Sphinx strict-mode autodoc.
fail_ci_if_error: falseon the codecov upload step — Codecov outage shouldn’t block merges; the local coverage XML is still authoritative if upload fails.
[0.7.3] — 2026-05-09¶
Added¶
Sphinx auto-docs build — first browsable contract surface for third-party node implementers:
docs/conf.py— autodoc + autosummary + napoleon + intersphinx + viewcode + myst-parser; furo theme; pulls version from package__init__so docs / pyproject never drift.Per-module
docs/api/*.rstfiles for the 8 public modules (types,adapters,swarph_call,mesh_client,discovery,attribution,hooks,exceptions); each rst marks the Tier 1/2/3 stability of the module’s surface up front.docs/index.mdlands the package, links the four-package ecosystem (swarph-shared / swarph-mesh / swarph-cli / swarph-meshlm), and points at the contract anchors (SECURITY.md/DEPRECATIONS.md/CHANGELOG.md).CHANGELOG.md,DEPRECATIONS.md,SECURITY.mdincluded via myst-parser{include}so the canonical files stay GitHub-rendered + the doc site stays single-source-of-truth.
GitHub Pages deploy —
.github/workflows/docs.yml:On
mainpush: build withSPHINXOPTS=-W --keep-going(warnings = errors) + deploy viaactions/deploy-pages@v4.On PR: build only (no deploy) so reviewers see green-or-red before merge.
Concurrency group prevents overlapping deploys.
docsextras inpyproject.toml—pip install swarph-mesh[docs]bootstrapssphinx>=7.0+furo+myst-parser.
Fixed¶
Python 3.10 support honored —
discovery.pyhad three_dt.UTCcallsites (Python 3.11+ only) at lines 424, 702, 933, despitepyproject.tomldeclaringrequires-python = ">=3.10". Replaced with_dt.timezone.utc(works on all 3.10+). The same failure was silently present on PRs #17/#18/#19 (v0.7.0/v0.7.1/v0.7.2) where the pytest 3.10 matrix arm was treated as non-blocking; v0.7.3 review (drop DM #763) caught the discipline drift and fixed it in-PR. Discovered tests on Python 3.11/3.13 always passed; only 3.10 leg failed withAttributeError: module 'datetime' has no attribute 'UTC'. Honors the declared contract surface in keeping with the doc-surface-as-hardening framing of this release.docs/_static/.gitkeepadded — empty directory wasn’t tracked by git, causing strict-modesphinx-build -Wto fail in CI onhtml_static_path entry '_static' does not exist(worked locally because Sphinx tolerates missing_staticin non-strict mode). Caught by drop on first CI invocation — confirms the doc-surface-as-contract-enforcement hypothesis on its first real run.
Notes¶
Strict-mode build catches autodoc misses (missing docstring on a public symbol, broken intersphinx link) so the contract documentation stays in lockstep with the contract.
One docstring formatting fix in
src/swarph_mesh/swarph_call.py(definition-list-followed-by-Usage-block triggered docutils warning under strict mode); rewrote as Google-style napoleon prose +Example::block.Fixes a 404 intersphinx inventory reference (
https://www.python-httpx.org/objects.invdoesn’t exist); httpx removed fromintersphinx_mapping.
[0.7.2] — 2026-05-09¶
Added¶
CHANGELOG.md(Keep-a-Changelog 1.1.0) — full release history v0.0.1 → v0.7.1 with Added/Changed/Fixed/Notes sections per release; CRITICAL fixes called out in version entries (gpt-5 5x + o3 5x over-attribution).DEPRECATIONS.md— versioning + deprecation policy:3-tier contract surface (Tier 1 highest =
LLMAdapterProtocol +ChatMessage+LLMResponse+ canonical adapter names +MeshClient.send/fetch+MeshMessage+ discovery primitives; Tier 2 medium =SwarphCall+AttributionWriter+HookSet+normalize_*_id+_RETIREMENT_REGISTRYkeys; Tier 3 lower = adapterPRICINGdicts + adapter-local_normalizecopies +_ANTHROPIC_PRICINGcontents)Per-tier breaking-change rules (e.g. adding
LLMAdaptermethod = BREAKING under runtime-checkable Protocol, addingMeshMessagefield with default = NON-BREAKING, renaming canonical adapter name = MAJOR-only)Deprecation cycle: announcement +
DeprecationWarning+ min 1 MINOR cycle + CHANGELOG entry + migration paragraph for Tier 1Mypy
--strictmodule ratchet schedule v0.7.0 → v0.8.0Hardening commitment tracker (extends
SECURITY.md)Closing discipline: “When in doubt, default is YES it’s breaking”
Notes¶
Resolves all 8 forward-references from
SECURITY.mdv0.7.1,tests/test_protocol_contract.pyfailure messages, and CI workflow ratchet comment.Pure governance artifact; no code change. Tests: 293 passed + 5 skipped — unchanged.
Feature track queue (after foundations stable)¶
LLM-scraper primitive (subscription-default opt-in per commander direction; cross-check optional)
Drift-detection cron (uses
verified_atmetadata across PRICING tables)Cached-input pricing tuple-shape extension (
(input, cached, output)triples)Retirement-warning runtime hook at adapter dispatch (uses
discovery.is_retired)gpt-5.3-codex / gpt-5.2-codex pricing (deferred from v0.6.2; needs commander pasting from authoritative OpenAI source)
[0.7.1] — 2026-05-09¶
Added¶
SECURITY.md— security policy with 9 explicit in-scope vulnerability classes mapped to actual contract surface (NOT generic boilerplate):Credential leakage (logs, attribution, exception messages, DM contents, PyPI artifacts)
Privilege boundary bypass (regular → admin keys, subscription → metered exfiltration)
Cost over-attribution (the gpt-5 5x and o3 5x classes elevated to first-class security concern at enterprise spend)
Cost under-attribution (audit + quota escape)
Mesh-gateway authentication bypass (
/peers,/messages,/tasks/claim)Ratification bypass (
task_claimforratified=false,peer_ratificationsmutability)Protocol contract violation (
LLMAdapter/MeshMessage/MeshClient.send/discoveryAPI changes without deprecation window — anchored in DEPRECATIONS.md)Catalog poisoning (crafted
ModelInforecords via AIMLAPI or/v1/models)DM contagion (
lab-claudevslab-ovhframing-contagion class promoted to security concern; pre-federation cross-mesh status leaks)
Reporting channels:
pierresamson@gmail.comwith[swarph-mesh security]subject prefix, GitHub Security Advisory (preferred for repo-scoped findings).Response timeline commitments: 48h ack / 5 business days triage / 14d high-critical fix / 30d medium / 90d low.
Hardening commitment per minor release (at least one of: secret-guard regex tightening, protocol-stability snapshot expansion, mypy strict module ratchet, privilege-boundary test addition).
Federation forward-compat note for v0.8+ mesh-to-mesh work.
Notes¶
Pure governance artifact addition. No Protocol changes. No API removals. Backward-compat with v0.7.0.
[0.7.0] — 2026-05-09¶
Added¶
GitHub Actions CI workflow (
.github/workflows/ci.yml):Pytest matrix: Python 3.10 (declared floor) + 3.13 (declared ceiling)
mypy --strictgate scoped totypes.py+exceptions.py(ratchets per minor per DEPRECATIONS.md)Ruff lint (F-rule subset, non-blocking initially)
Concurrency cancellation on force-push
SWARPH_SKIP_NETWORK=1in CI runners (live AIMLAPI catalog smoke + cost-recon don’t hit network from PR runners)
PEP 561 type marker (
src/swarph_mesh/py.typed):Empty file packaged via
tool.setuptools.package-dataThird-party type-checkers (mypy, pyright, etc.) now see swarph-mesh’s hints
Was missing pre-v0.7.0 — every external pip-install consumer got
Untypedannotations from us until they explicitly opted in
Protocol-stability snapshot tests (
tests/test_protocol_contract.py, 10 tests):LLMAdapter@runtime_checkablepreservation (third-partyisinstance()workflow guarantee)Required class attribute set (
name,default_model)Frozen method set:
chat/stream/cost_per_token/list_modelschat()signature kwarg-default frozen (system_prompt=None,json_schema=None,temperature=0.7,max_tokens=None)list_models()ttl_seconds=86400default frozenChatMessage+LLMResponsefield-set guaranteesCanonical adapter names
{gemini, deepseek, claude, openai, grok}reserved + dispatchableDiscovery public API frozen at v0.7.0 baseline
Changed¶
LLMResponse.parsedtyped asdict[str, Any](was baredict) formypy --strict.LLMResponse.raw_responsetyped asdict[str, Any].LLMAdapter.chatjson_schematyped asdict[str, Any].LLMAdapter.list_modelsreturn typed aslist[Any].
Fixed¶
Test fixture
test_canonical_adapter_names_in_registry_dispatchwas caching fake-key adapters in the singleton registry, silently poisoning live smoke tests later in the same run. Wrapped inreset_registry()try/finally. Caught when full pytest run started failingtests/test_smoke_deepseekwith 401 errors from leftover fake keys. The class is now documented infeedback_singleton_pollution_across_tests.md(lab + droplet auto-memory mirrors).
Notes¶
Major-style minor signals foundations-layer shift in v0.7.x line. Each subsequent v0.7.x minor adds one foundations item. Backward-compat with v0.6.x: no Protocol changes, no API removals.
[0.6.2] — 2026-05-09¶
Added¶
OpenAI PRICING entries from authoritative
openai.com/api/pricingsource (commander-pasted 2026-05-09):gpt-5.1 family:
gpt-5.1,gpt-5.1-codex,gpt-5.1-codex-minigpt-5.4 family:
gpt-5.4,gpt-5.4-mini,gpt-5.4-nano,gpt-5.4-progpt-5.5 family:
gpt-5.5,gpt-5.5-progpt-5-pro(premium tier $15/$120)o1-pro(premium reasoner $150/$600)o3-pro($20/$80)
Centralized normalizers in
swarph_mesh.discovery(drop DM #745 obs #1):normalize_xai_id,normalize_deepseek_id,normalize_model_id(provider-aware dispatcher)Adapter-local
_normalize_*_idcopies preserved for back-compat
Shared retirement registry (drop DM #745 obs #2):
_RETIREMENT_REGISTRYdict keyed byprovider/model_id→ ISO date OR"deprecated"sentinelPublic API:
is_retired(provider, model_id, today=None)+retirement_date(provider, model_id)Initial entries:
grok/grok-4+grok/grok-code-fast-1(2026-05-15);claude/claude-sonnet-3-7+claude/claude-opus-3(deprecated sentinels)
Provenance metadata:
_OPENAI_PRICING_VERIFIED_AT = "2026-05-09"+_OPENAI_PRICING_SOURCE.
Fixed¶
o3over-attribution (CRITICAL): was(10.00, 40.00)speculative in v0.6.1; real direct OpenAI pricing is(2.00, 8.00). 5x over-attribution for any caller usingo3between v0.5.x and v0.6.1. Same class as thegpt-5fix in v0.6.1. Regression test asserts the corrected numbers.o1-minicorrection:(3.00, 12.00)→(1.10, 4.40)(matcheso3-mini/o4-minitier).
Deferred¶
gpt-5.3-codex/gpt-5.2-codex: not on the standard-tier source page commander pasted; route to_defaultuntil next verification cycle.Cached-input pricing tuple-shape extension (page exposes
(input, cached, output)triples; tracked as feature-queue item).Retirement-warning runtime hook at adapter dispatch.
[0.6.1] — 2026-05-08¶
Fixed¶
gpt-5over-attribution (CRITICAL): was(5.00, 20.00)speculative in v0.5.x; real direct OpenAI pricing per Helicone is(1.25, 10.00). ~4x over-attribution window for callers usinggpt-5pre-v0.6.1.
Added¶
9 carry-forward fixes batched: gpt-4.1 family, gpt-5-mini/nano, claude-opus-4-1 + dated builds, grok-4-fast family, gemini-2.0-flash, alias normalizers, secret-guard regex tightenings, MeshClient response-shape fixes, kind enum, ?to= wire fix.
fetch_xai_cost_buckets()+reconcile_xai_cost()viamanagement-api.x.ai/v1/billing/teams/{id}/usage(live smoke verified).fetch_deepseek_balance()via/user/balance(live smoke verified).
Notes¶
PR #14 was auto-closed when its stacked base (PR #13 feat/v0-6-0-discovery) was deleted on merge; recovered by opening PR #15 with base=main carrying drop’s #745 approval forward. Class documented in feedback_stacked_pr_base_delete.md.
[0.6.0] — 2026-05-09¶
Architectural promotion: model discovery substrate. BREAKING CHANGE on LLMAdapter Protocol.
Added¶
swarph_mesh.discoverymodule with 4 primitives:Catalog backed by AIMLAPI’s public
/modelsendpoint (~600 entries, no auth, 24h TTL) + per-provider/v1/modelsOpenAI-compat fallbackGemini pricing via Google’s Cloud Billing Catalog API (service
241C-273D-49C8= Vertex AI)Anthropic pricing via static manual table from
claude.com/pricingwithverified_atprovenanceOpenAI cost reconciliation via
/v1/organization/costsadmin-key gated; live smoke PASSED end-to-end
LLMAdapter.list_models()Protocol method — BREAKING CHANGE: external implementations ofLLMAdapterfrom v0.5.x must add this method to satisfy the runtime-checkable Protocol. Each shipped adapter delegates via 3-line lazy-import call.Secret-guard regex tightening:
sk-admin-named pattern with elevated-privilege-class error message.
Notes¶
v0.6.0 not published to PyPI (v0.6.1 supersedes); git tag v0.6.0 exists for provenance.
[0.5.1] — 2026-05-08¶
Fixed¶
MeshClient.sendresponse shape mismatch (pydantic ValidationError on success POST despite delivery — DM duplication risk).MeshClient.fetch?to=wire-shape fix (was using?to_node=which the gateway silently ignored).
Added¶
9 carry-forward fixes: secret-guard regex tightenings (sk-proj-, xai-, deepseek explicit, AIza, mesh-gateway tokens), DEEPSEEK_LEGACY_ENV_PATH override, V4-Pro promo verify-after sentinel, claude.py once-per-instance silent-kwargs warnings, CLAUDE_BIN docstring, grok-2 PRICING removal, OpenAI
_default→ gpt-4o-mini under-bill-on-uncertainty.kind=Literal[...]enum onMeshClient.sendfor fail-fast.
[0.5.0] — 2026-05-08¶
Added¶
Phase 4 #4 + #5:
OpenAIAdapter+GrokAdapter(native AsyncOpenAI from day one per drop’s #7 forward-direction). xAI uses OpenAI-protocol-compatible API athttps://api.x.ai/v1. Reasoning preservation[reasoning]shape consistent across all four reasoner-capable adapters.
[0.4.0] — 2026-05-08¶
Added¶
Phase 4 #3:
ClaudeAdaptersubscription path viaclaude -psubprocess. Reads~/.claude/.credentials.json. Billing-leak prevention viaswarph_shared.scrub_env_for_subprocessstrips ANTHROPIC_API_KEY before invoking.cost_usd=0.0for subscription (honest flat-rate); metered-equivalent inraw_response["api_metered_cost_usd"]for auditors.
[0.3.0] — 2026-05-08¶
Added¶
Phase 4 #2:
DeepSeekAdapter(OpenAI-protocol-compatible client for V4-Flash / V4-Pro / V3 aliases). Preserves reasoning content as[reasoning]preamble for portability.
[0.2.0] — 2026-05-08¶
Added¶
Phase 3:
MeshClientasync wrapper around mesh-gateway HTTP API + recipient validation viaswarph_shared.validate_node_name+ best-effort credential leak guard.
[0.1.0] — 2026-05-08¶
Added¶
Phase 1: First substrate release.
LLMAdapterProtocol +ChatMessage+LLMResponse+SwarphCallpublic surface (caller-validated, hook-wired entry-point) +GeminiAdapter(wrapslanggraph-genai-bridge) + JSON-mode harness +FileAttributionWriter.
[0.0.1] — 2026-05-08¶
Added¶
Typed substrate scaffold: Protocol + dataclasses + exceptions.