Toolchain to build result/affixes, result/uniques, and result/economy from:
- poe2db snapshot data (
config/poe2db_snapshot.json), - PoE2 source data (
data/poe2/data/mods.json, auto-fetched on demand), and - PoE2Scout economy catalog data for currency coverage.
The generated affix JSON files are the canonical affix output. Unique items are emitted separately under result/uniques/{class}.json. Validation warnings are expected coverage advisories, not evidence that the generated affix files are wrong.
- The repository's source code and original project-authored content are licensed under
CC0 1.0; see LICENSE and LICENSE-CC0.txt. - This project fetches and may bundle or derive data from PoE2DB (
https://poe2db.tw), including the modifiers index used byrefresh-poe2db. It also fetches economy catalog data from PoE2Scout (https://poe2scout.com) viarefresh-economy. - PoE2DB states:
Wikis Content is available under CC BY-NC-SA 3.0 unless otherwise noted. - As a result, bundled or generated PoE2DB-derived data in this repository should be treated as
CC BY-NC-SA 3.0unless otherwise noted, not asCC0. - That includes the fetched snapshot and the generated affix/unique/mapping/report artifacts, including
config/poe2db_snapshot.json,config/unmapped_uniques.json,config/item_mapping.json,result/affixes/*.json,result/uniques/*.json,result/poe2db_refresh_report.json,result/build_report.json,result/rebuild_mapping_report.json, andresult/mapping_validation.json. Economy artifacts underresult/economy/*.jsonand tier artifacts underresult/tiers/*are PoE2Scout-derived. - If you redistribute PoE2DB-derived artifacts from this repo, preserve attribution to PoE2DB and comply with the applicable non-commercial and share-alike terms.
- Attribution and scope details are documented in THIRD_PARTY_NOTICES.md.
- Python 3.14+
uv
uv syncRun the fast hygiene and regression gates before logic changes are merged:
uv run ruff check src tests
uv run python -m unittest discover -s tests
uv run poe-affix-build validate-unique-overridesRun uv run poe-affix-build build when generated affix, unique, or report parity needs to be verified locally.
Show the installed CLI version:
uv run poe-affix-build --versionRefresh poe2db snapshot (explicit/manual, not part of build):
uv run poe-affix-build refresh-poe2db \
--snapshot config/poe2db_snapshot.json \
--report result/poe2db_refresh_report.json \
--unmapped-uniques config/unmapped_uniques.jsonrefresh-poe2db prints live progress ([n/total]) and retries transient upstream failures (including Cloudflare 52x responses) with exponential backoff. It first fetches the canonical PoE2DB Unique_item index and visits each unique detail page, adds explicit extra unique detail pages for known records missing from the index, then uses itemtype pages only for bases and modifier sections.
Refresh the standalone economy currency catalog:
uv run poe-affix-build refresh-economy \
--out result/economy/currency.json \
--report result/economy_currency_report.jsonrefresh-economy fetches PoE2Scout economy categories for the Fate of the Vaal league and stores static category/item identifiers only. It includes all Scout currency categories, including Uncut Gems, because PoE2DB economy pages are currently incomplete for currency coverage. It does not map to pickit identifiers and does not store market prices, Divine/Exalted conversions, or tiers.
Rebuild mapping from snapshot + mods source:
uv run poe-affix-build rebuild-mapping \
--source-dir data/poe2/data \
--snapshot config/poe2db_snapshot.json \
--out config/item_mapping.json \
--report result/rebuild_mapping_report.jsonFor contributor debugging, rebuild-mapping can also write a categorized unresolved diagnostic report:
uv run poe-affix-build rebuild-mapping \
--diagnostics result/rebuild_mapping_diagnostics.jsonBuild affix output from source data:
uv run poe-affix-build build \
--source-dir data/poe2/data \
--manifest config/item_mapping.json \
--out-dir result/affixes \
--uniques-dir result/uniques \
--report result/build_report.json \
--unresolved-tiers result/unresolved_tiers.json \
--unique-stat-missing result/unique_stat_mapping_missing.json \
--mods-list data/eb2/ModsList.htmlFor contributor debugging, build can also write the same categorized unresolved diagnostics:
uv run poe-affix-build build \
--diagnostics result/build_diagnostics.jsonValidate mapping coverage against source data:
uv run poe-affix-build validate-mapping \
--source-dir data/poe2/data \
--manifest config/item_mapping.json \
--out result/mapping_validation.jsonValidate unique override/dropdown config against EB2 affix ids:
uv run poe-affix-build validate-unique-overrides \
--config config/unique_stat_affix_overrides.json \
--mods-list data/eb2/ModsList.htmlWrite a local ModsList review copy with known undefined text cells filled from local mappings:
uv run poe-affix-build annotate-mods-list \
--mods-list data/eb2/ModsList.html \
--out result/ModsList.annotated.htmlrefresh-poe2dbfails atomically: snapshot/report are written only after full successful fetch/parse.- Unique items are detail-page records from
https://poe2db.tw/us/Unique_itemwhere possible. Known records missing from that index, such asThe Remembered Tales, are fetched through explicit extra detail URLs instead of scanning itemtype unique tabs. - Unique detail records that cannot be assigned to a known affix itemtype are written to
config/unmapped_uniques.jsonand summarized inresult/poe2db_refresh_report.json. The snapshot storesunmapped_uniques_pathinstead of embedding the full review list. Duringbuild, those records are still included inresult/uniques/{class}.jsonwhen PoE2DB class metadata is available. result/affixes/*.jsonis affix-only. Unique output is grouped by PoE2DB class, for exampleresult/uniques/Boots.json,result/uniques/Body_Armours.json, andresult/uniques/Jewels.json.- During
build, unique stat templates are matched back to generated affixes where possible. If a stat is not present in generated affixes, the builder falls back to rawmods.jsonentries and then exact single-id matches fromdata/eb2/ModsList.html. Unique stat rows also includeaffix_ids, derived fromstat_idsby replacing spaces with underscores. When a unique stat can roll one of several affixes, the row includesaffix_optionsso configurator UIs can show dropdown text while storing the selected affix id. Whenaffix_idsis present, noaffix_mappingblock is emitted.Grants Skilland(Hidden)rows are ignored for affix mapping because they are handled separately; unmatched or ambiguous non-skill visible stats are written toresult/unique_stat_mapping_missing.jsonfor review. - Unique-only affix id overrides and dropdown descriptions are maintained in
config/unique_stat_affix_overrides.json. Runvalidate-unique-overridesafter edits; it checks shape rules and confirms override affix ids exist indata/eb2/ModsList.html. result/economy/currency.jsonis the standalone PoE2Scout economy catalog. It contains category names, item names, Scout API identifiers, item ids, and optional icon URLs only.result/unresolved_tiers.jsonis a build-time analysis artifact with all unresolved tiers in a flat list plus actionability categories. It is easier to inspect than the embeddedunresolved_tiersarray inresult/build_report.json. Combined rows can includetext_partsandaffix_components, so configurators can see each component's display text, numeric values, and resolved affix ids. Component ids are resolved from generated/mods.json references first, then from exact and curatedModsList.htmlreferences for EB2-only rows. Socketable-only unresolved rows are ignored because they are outside the item-drop filter pool.- For
build,validate-mapping, andrebuild-mapping, ifmods.jsonis missing under--source-dirand the source dir follows the default.../poe2/datalayout, the CLI performs a shallow sparse checkout ofhttps://github.com/repoe-fork/poe2.git(master) intodata/poe2, materializing onlydata/mods.json. validate-mappingreports coverage advisories. These are useful for mapping maintenance, but the current affix output files can still be correct even when advisories exist.
The rebuild and build reports can still contain unresolved modifier matches, mostly from non-normal rune/socket/soul-core style sections. The detailed interpretation lives in docs/unresolved-groups.md.
src/poe_affix_builder/domain: typed core models split by source, manifest, snapshot, output, unique, and report concerns;domain.modelsremains the compatibility facadesrc/poe_affix_builder/contracts: serializers and round-trip-safe JSON contractssrc/poe_affix_builder/adapters: filesystem, sparse checkout, poe2db, EB2 ModsList, and Scout HTTP integration boundariessrc/poe_affix_builder/services: build, validation, rebuild, unique-output, snapshot-assignment/reporting, economy catalog/reporting, and shared matching logicsrc/poe_affix_builder/policies: domain/spawn-tag rules
More detail is in docs/architecture.md.
- Preserve parity for
result/affixes,result/uniques,result/economy,config/item_mapping.json, and the committed reports unless a change explicitly intends to alter logic. - When changing matching behavior, update or justify any artifact diffs in tests and review notes.
- Run
uv run ruff check src tests,uv run python -m unittest discover -s tests, anduv run poe-affix-build validate-unique-overridesbefore merging logic changes.