e↗entertrainment
← All project stories
Developer tools / PROJECT STORY

EVE development tools

Developer tools and analysis around EVE Online data, fitting and APIs. The project scope focuses on external software and legitimate analysis.

External analysis research14 MIN READDEVELOPMENT ARCHIVE · OCT 2026
PROJECT REVIEW · 18 October 2026

Inside the project

Prepared with the project’s development agent from source and retained evidence. This is a project-owner assessment, not an independent customer review. Dated checks were not rerun for this website.

Two libraries written on 12 October 2026 for people building EVE Online tools on Apple platforms. swift-eve-esi is a dependency-free Swift 6 client for CCP's ESI API and single sign-on; its strength is that it gets CCP's house rules right in one place: the compatibility-date header, the ETag/Expires cache contract, both rate limits with back-off, pagination, and PKCE sign-in with full token verification. The parity harness, inside the user's SemanticCompute library, takes three EVE fitting formulas (turret hit chance, expected applied damage, stacking penalty) and holds GPU and CPU implementations to fixtures generated from pyfa's own functions, within tolerances that are stated and measured rather than assumed. Both are developer foundations: there is no app, no screen, and nothing to click. The practical limits are the ones to expect at version 0.1: sixteen ESI routes, an in-memory token store, Apple-only signature verification, and a harness branch that has not been merged into SemanticCompute's main line. EVE Online itself is CCP Games' product; this work is independent and not endorsed.

What stands out

  • ESI client honours CCP's cache contract: a fresh cached body costs no network call, stale bodies revalidate with If-None-Match (offline tests cover both paths)
  • Tracks the error-limit budget and per-group rate limits, pauses before exhaustion, retries once on 420/429 within a configurable wait
  • Full SSO token verification: ES256 via CryptoKit and RS256 via Security, issuer/audience/expiry checks, forced JWKS refresh on unknown key id, single-flight refresh
  • Parity harness states and measures every tolerance: pyfa fixtures match the Double reference to 0–2 double-ULPs; the pyfa-vs-documented operation-order gap (up to 1,044 ULPs) is pinned rather than hidden
  • Fixtures record provenance (pyfa v2.69.2, commit, file digests) and regenerate deterministically; no GPL code enters the repository

Current limits

  • No consumer app exists; the planned character companion and PI alert worker are unwritten
  • swift-eve-esi: 16 routes, models pinned to compatibility date 2026-08-18, in-memory cache and token store only, EVESSO Apple-only, test pass state unrecorded, no remote or release
  • Harness: three of five formulas built (missile and capacitor have fixtures only), branch unmerged into SemanticCompute main, needs a local pyfa checkout to regenerate pyfa fixtures, Float32 on device by design
  • No screenshots, video, audio or interactive demo exist for either artefact

Features & evidence

ESIClient (swift-eve-esi)

source

Typed async requests with required headers, ETag/Expires cache partitioned by signed-in character, rate-limit guard, typed errors, eager and streaming pagination

Recorded evidence

Commit 09902ed 2026-10-12; 25 @Test functions in Tests/ESITests/ESIClientTests.swift (one live suite gated on ESI_LIVE=1); debug build products and test bundle present under .build/, pass result not recorded

ESI routes and scopes

source

Status, character, skill queue/skills, wallet balance/journal, planetary colonies and layouts with earliestExtractorExpiry, industry jobs, market orders/prices, universe names/types, assets; 17 predefined OAuth scopes

Recorded evidence

Sources/ESI/Endpoints/*.swift (16 constructors), Sources/ESI/Core/ESIScope.swift; Spec/openapi-2026-08-18.json checked in; Scripts/fetch-spec.sh

EVESSO sign-in

source

PKCE authorisation URL and callback parsing, code exchange, refresh-before-expiry, revoke, JWT parse and signature/claim verification, SSOSession as the client's authorisation provider, TokenStore protocol

Recorded evidence

Sources/EVESSO/*.swift; 15 @Test functions in Tests/EVESSOTests/EVESSOTests.swift including RFC 7636 vector and tampered-payload rejection; same build evidence as above

TurretHitChance family (SemanticCompute)

component-tested

Seven-input chance-to-hit as Double reference (refuses out-of-domain rows), Float32 reference and IR kernel on Metal, C, WGSL, CUDA; documented and pyfa evaluation forms

Recorded evidence

Branch claude/festive-brown-agrt1q commits 77a244e–98b8529 2026-10-12; NEEDS.md REPLY 2/3: tests pass on macOS 27.0/Xcode 27.0/Swift 6.4, pyfa fixture 608 rows at 0 ULP, Float32 worst 2.3e-5 relative

TurretDamageExpectation family

component-tested

Expected applied damage under the hit-quality roll, composing with hit chance; backends bit-exact to the Float32 reference

Recorded evidence

Same runs; 824-row fixtures, pyfa fixture bit-exact, Float32 2 ULP

StackingPenalty family

component-tested

Whole-fit stacking rule; host orders modifiers, device folds fixed-width rows; multiply operator only

Recorded evidence

NEEDS.md REPLY 3: 83 tests in 13 suites passed 2026-10-12; 364-row fixtures, 0 ULP documented, 2 ULP pyfa, Float32 5 ULP

Missile application and capacitor recharge

planned

pyfa-generated fixtures (175 and 1,320 rows) and generators; no families or tests yet

Recorded evidence

Tests/Fixtures/EVE/missile-application.json, capacitor-recharge.json; Tools/eve-*-fixtures.py and oracle adapters, 2026-10-12

Companion app / PI alert worker

planned

The consumer the library README names as its purpose

Recorded evidence

README.md Status section; no app source found under [local evidence archive]

Review updates & corrections
  • No new commits in either repository since 2026-10-12 (swift-eve-esi .git/logs/HEAD still one commit; worktree log ends at 98b8529)
  • Harness branch still unmerged: SemanticCompute main CHANGELOG has no EVE entries as of this read
  • Yesterday's biography was saved by the coordinator as responses/eve-tooling-collected.md, and a draft page dist/projects/eve-tooling.html now exists in the site build; I did not read or edit it
  • Correction to yesterday's wording: 'tests passed' for swift-eve-esi remains unverified; only a built test bundle exists

Workflow walkthrough

A guide to the native workflow. These steps describe the app; only the recordings and images embedded on this page are available as website demonstrations.

  1. Developer registers an application at CCP's developer portal and chooses scopes (external step, not ours)
  2. Constructs SSOConfiguration and an AuthorizationRequest, opens its URL in ASWebAuthenticationSession, hands the callback URL to SSOSession.signIn; the token is verified against CCP's JWKS
  3. Calls client.authorized(by: session).send(.planetaryColonies(characterID:)) then .planetaryColonyLayout per colony and reads earliestExtractorExpiry; a second call within Expires is served from cache with no network request
  4. Separately, in a SemanticCompute checkout of the branch, runs swift test --filter TurretHitChanceTests and reads the printed parity layers (oracle gap in ULPs, Float32 error, backend agreement)
  5. Optionally points Tools/eve-turret-hit-chance-fixtures.py --oracle Tools/eve-turret-hit-chance-oracle-pyfa.py at a pyfa checkout via PYFA_ROOT and sees a no-op diff against the committed pyfa fixture
  6. Nature: none of this is playable or interactive on the website; no native capture exists; a proposed capture would be a terminal recording of step 4's test output, which does not exist today
Planned captures · not yet available
  • Proposed terminal capture of swift test --filter TurretHitChanceTests printing the parity layers
  • No screenshots exist; neither artefact has a UI

Development biography · earlier archive

Development profile compiled from project source and retained records in October 2026. Dates and test results describe those records; they do not imply a new build, live acceptance test or public release.

Two independent development projects support external EVE Online analysis: swift-eve-esi, a Swift client for ESI and single sign-on, and a fitting-formula parity harness in SemanticCompute. Both are libraries or numerical fixtures; neither is a game client or a finished companion application. The work is independent of CCP Games.


A. swift-eve-esi

Biography

EVE Online exposes its game data through ESI, a public REST API with unusual house rules. CCP requires every consumer to identify itself in the User-Agent with a contact address; it versions the whole API by a date header rather than a path; it publishes ETag and Expires on responses and expects clients to honour them; and it enforces two separate limits, an error budget whose exhaustion returns status 420 and blocks every route, and newer per-route-group limits returning 429 with Retry-After. Most hobby clients get at least one of these wrong and are throttled or banned. swift-eve-esi exists to get all of them right in one place so that an app above it only ever expresses what it wants to read.

The repository's own statement of purpose is modest and specific: the route set "is the slice needed for a character companion and a PI alert worker" . Planetary interaction colonies have extractors with an expiry time; a player who misses one loses production. The package therefore models colony layouts and computes earliestExtractorExpiry across a colony's pins, and its sign-in flow carries the esi-planets.manage_planets.v1 scope. That companion app does not yet exist in any checkout I can see; the library is the foundation written first.

The package has two products. ESI is the client: ESIClient builds the required headers (compatibility date pinned to 2026-08-18, tenant, language, User-Agent, bearer token), looks up an ETag/Expires cache keyed by method, URL, language, compatibility date, tenant and the signed-in principal, serves a fresh body without touching the network, revalidates a stale one with If-None-Match and handles 304, records the error-limit and rate-limit headers in an actor, sleeps before sending when the error budget is nearly spent, retries exactly once on 420 or 429 when the wait is within a configurable maximum, and maps HTTP failures to typed errors. Pagination follows the X-Pages header either eagerly (allPages) or as an async stream (pages). Routes are hand-written from the OpenAPI document kept in Spec/, one file per area: status, character, skill queue and skills, wallet balance and journal, planetary colonies and layouts, industry jobs, character and region market orders and prices, universe names and types, assets. Seventeen OAuth scopes are predefined. Enum values CCP extends without a date change stay as strings on purpose, a decision recorded in AGENTS.md.

EVESSO is the sign-in module. It builds the PKCE authorisation URL, parses the callback and checks the state, exchanges the code, refreshes before expiry with single-flight refresh so concurrent callers share one request, and revokes on sign-out. Every token is parsed as a JWT and verified: signature against the SSO's JWKS (ES256 via CryptoKit, RS256 via the Security framework from the key's modulus and exponent, with forced JWKS refresh on an unknown key id), then issuer, audience and expiry with a clock leeway. SSOSession is itself the client's authorisation provider, so one object signs in and authorises requests. Token persistence is a three-method protocol; only an in-memory store ships, and the README names a Keychain store as "the obvious next one to write".

A representative user journey, as the README shows it: an app registers with CCP's developer portal, constructs SSOConfiguration with its client id, callback scheme and scopes, opens the authorisation URL in ASWebAuthenticationSession, hands the callback URL to session.signIn, then calls client.authorized(by: session).send(.planetaryColonies(characterID:)) and, per colony, the layout, printing each colony's earliest extractor expiry. A worker built on this would poll within the cache contract and alert before the expiry.

The design is deliberately conservative. There are no dependencies, no force-unwraps in library code, strict Swift 6 concurrency, and the rule that "never send requests to ESI before a cached body's Expires" is "the contract, not an optimisation" . The same file carries a guardrail worth quoting on a website: "No automation of the game client, ever. This package speaks ESI and SSO only." The work is independent and, as the README states, not endorsed by CCP Games; use of ESI is governed by the EVE Developer License.

Modules and features (all authored; the only dependencies are Apple frameworks)

  • ESI: client, configuration, compatibility date, user agent, cache contract and in-memory cache, rate-limit guard, typed errors, JSON coding with two date formats, HTTP transport abstraction (URLSession default), request model with cache policy, 16 route constructors across 9 endpoint files, 17 scopes.
  • EVESSO: PKCE (RFC 7636 vector tested), authorisation request and callback parsing, token exchange/refresh/revoke, JWT parsing, JWKS fetch with cache, RS256 and ES256 verification, claim checks, SSOSession, TokenStore protocol with in-memory store.
  • Tooling: Scripts/fetch-spec.sh downloads the OpenAPI document for a compatibility date; Spec/openapi-2026-08-18.json is checked in.
  • Tests: Swift Testing suites with mock transports and locally generated signing keys; 25 @Test functions in ESITests (one live suite gated on ESI_LIVE=1 that hits Tranquility) and 15 in EVESSOTests.

Technical foundations

Swift 6 strict concurrency; actors for the rate-limit guard, caches, token store and session; Sendable value models with explicit CodingKeys; CryptoKit and Security for signature verification, which makes EVESSO Apple-only while ESI is portable in principle. No local package dependencies.

Maturity (dated evidence)

  • Source implemented: yes. One commit, 09902ed, "Swift 6 ESI client and EVE SSO, first cut", 2026-10-12 (git log; epoch 1791841413).
  • Built: yes on this Mac. Debug build products and the swift-eve-esi_ESITests.bundle test bundle exist under .build/ (gitignored), so the package and its test target compiled; date of that build not recorded.
  • Tests passed: not verifiable in this review. No test log or CI exists; the review was read-only and could not run swift test. Treat as "tests written, pass state unrecorded".
  • Installed/runtime verified: no consumer app exists. The gated live test documents one real request against Tranquility but no record of it running.
  • Released: no. CHANGELOG.md reads "0.1.0 (unreleased, started 2026-10-12)". No git remote is configured; no tag.

Roadmap and limits

  • Keychain TokenStore; more routes "added by hand from Spec/ … until a generator earns its place"; the companion app and PI alert worker.
  • Limits: 16 routes only; models pinned to compatibility date 2026-08-18 and must be re-checked when that moves; EVESSO Apple-only; in-memory cache and token store only; no retries beyond one; nothing published.

FAQs

  • Does it play the game for you? No. It reads data through CCP's public API and signs in with CCP's SSO; the project rule forbids any game-client automation.
  • Why pin an API date? ESI versions by date; pinning keeps response shapes stable until the models are revalidated against a newer spec.
  • Will it get my app rate-limited? It is built not to: it tracks both ESI limits, pauses before exhausting the error budget and honours Retry-After.
  • Can I use it on Linux? The ESI module has no Apple-only dependency; EVESSO currently needs CryptoKit and Security.
  • Is it endorsed by CCP? No. Independent work under the EVE Developer License.

B. EVE fitting-formula parity harness (inside SemanticCompute)

Biography

EVE Online players evaluate ship fittings with pyfa, an open-source Python application whose numbers the community treats as ground truth. A Swift fitting engine for Apple platforms would be judged on one thing: whether its heat maps and attribute totals match pyfa's. The harness on this branch is the user's answer to how such a claim can be made honestly. Rather than porting pyfa, it builds each formula as a SemanticCompute family, the library's unit of verified compute, and surrounds it with three measured layers: an oracle fixture against a Double reference, the Double truth against a Float32 reference, and the Float32 reference against the generated kernel on every backend. Each layer states its bar and the tests print the measured gap.

The first formula is the turret chance to hit, a closed form in seven inputs (transversal, distance, tracking, signature resolution, target signature, optimal, falloff). The documented form from EVE University and the fan wiki was implemented first; then pyfa adapters were written that load pyfa's own _calcTurretChanceToHit and related functions at generation time from a checkout named by PYFA_ROOT, so no GPL code enters the repository, and regenerate the fixture with pyfa as the oracle, recording pyfa's version (v2.69.2), commit, commit date and SHA-256 of the source files in the fixture's provenance. That exposed something a port would have hidden: pyfa evaluates the formula in a different operation order, two powers of 0.5 multiplied rather than one power of a sum, and the two forms differ by up to 1,044 double-ULPs. The reference therefore carries both forms, each fixture is held to its own form at 2 ULPs (measured 0), and the gap between forms is pinned so a change in either shows.

The second formula is the expected applied damage under EVE's hit-quality roll, which composes with the first. It has no transcendental, so the backends are held to the Float32 reference bit for bit, and the pyfa fixture agrees with the Double reference bit for bit. The third is the stacking penalty, the whole-fit attribute rule. Here the fixture settled a constant before code was written: a formula quoted from memory mixing exp with the base-0.5 constant would give the second module 81.7 % instead of 86.9 %. The design decision, "the host orders, the device folds", keeps sorting and ranking in testable Double on the host and gives the kernel a fixed-width row to multiply in the reference's order.

A user journey today is a developer's: check out the branch, run swift test --filter TurretHitChanceTests and read the printed layers; or point Tools/eve-turret-hit-chance-fixtures.py --oracle Tools/eve-turret-hit-chance-oracle-pyfa.py at a pyfa checkout and regenerate a fixture that is a no-op diff when nothing changed. Two further fixture sets, missile application (175 rows) and capacitor recharge from pyfa's own simulator (1,320 rows, 0 ULPs against the closed form), are generated and committed but have no families yet.

The work was produced by two sessions handing a notes file back and forth on 2026-10-12 , and that record is itself evidence of rigour: the Mac session found and fixed two defects in the library's reference executor that no earlier family had reached, and the cloud session corrected its own 2-ULP claim to match the data. Everything is labelled: formula fixtures use illustrative archetypes, "not Static Data Export attributes"; only the multiply operator is modelled for stacking; ISK stays in Double on the host. The harness is a developer's foundation, not a player-facing product.

Modules and features (authored on the branch)

  • Families: TurretHitChanceFamily.swift, TurretDamageExpectationFamily.swift, StackingPenaltyFamily.swift (Double reference refusing out-of-domain rows by index, Float32 reference, IR kernel, parity contract, accuracy bounds, fixture loader with schema and count checks); catalogue, symbol index and usage-guide entries.
  • Fixtures Tests/Fixtures/EVE/: turret-hit-chance (608 rows) and -pyfa, turret-applied-damage (824) and -pyfa, stacking-penalty (364) and -pyfa, missile-application (175) and -pyfa, capacitor-recharge (1,320) and -pyfa.
  • Tools: five fixture generators and five pyfa oracle adapters plus eve_pyfa_oracle_common.py.
  • Doc: docs/EVE_TURRET_HIT_CHANCE.md. Tests: 39 @Test functions across the three EVE suites.
  • Dependencies: SemanticCompute's executor, backends and parity doctor (the user's own library); pyfa is external and never vendored.

Maturity

  • Source implemented: yes, commits 77a244e, 4a0c10b, 98b8529 on the branch.
  • Tests passed on the Mac: yes, recorded verbatim in NEEDS.md REPLY 3: 83 tests in 13 suites passed on macOS 27.0 / Xcode 27.0 / Swift 6.4; measured layers printed (hit chance worst Float32 error 2.3e-5 relative over 567 rows; applied damage 2 ULP; stacking 5 ULP, pyfa gap 2 ULP).
  • Built: yes (same runs). Installed/runtime verified: not applicable; library code.
  • Released/merged: no. The main SemanticCompute checkout's CHANGELOG has no EVE entries and its README lists 283 families against the branch's 277, so the branch has not been merged; the EVE entries sit under [Unreleased] on the branch. The branch is pushed to origin (github.com/entertrainmentuk/semanticcompute, ref present locally); whether that repository is public could not be verified from here.
  • Missile and capacitor: fixtures only, no families, no tests.

Roadmap and limits

  • Next, per the doc's own order: missile application family, capacitor closed-form step family, then an SDE-driven fixture and a fitting engine that consumes the families.
  • Limits: not merged; three of five formulas built; formula fixtures use illustrative weapon archetypes; stacking models multiply only (no pre/post increases, resistances or caps); Float32 on the device by design; needs a local pyfa checkout to regenerate pyfa fixtures.

FAQs

  • Is pyfa included? No. Adapters import pyfa from a path at generation time; only the resulting numbers and provenance are committed.
  • What does "agrees with pyfa" mean here? The Double reference matches pyfa's fixture to 0–2 double-ULPs per formula, with the bar and measurement printed by the tests.
  • Why keep two forms of the hit-chance formula? pyfa's operation order differs from the documented one by up to 1,044 ULPs; honesty required pinning both rather than pretending one order serves every oracle.
  • Can this evaluate my fit? Not yet. It evaluates formulas in bulk; the fitting engine above it is roadmap.

Explore the connections.

Browse all project stories ↗