feat(advisor): native deterministic build-advisor tab (Epic #85)#88
Conversation
|
🔄 Cycle 1, attempt 1/3
✅ Agent succeeded (cycle 1, attempt 1) |
This comment has been minimized.
This comment has been minimized.
- Pass minionSkillTypes as third arg to doesTypeExpressionMatch for requireSkillTypes checks so minion-build supports aren't false-positive flagged as inapplicable; guard calcLib global with nil check so the check degrades gracefully when the full calc env isn't loaded. - Emit at most one support.duplicate finding per gameId even when three or more copies are socketed (track "dup" state to suppress re-emission). - Add group.enabled ~= false guard to the attr-requirement check loop, consistent with the three other skill checks; gems in disabled groups no longer produce spurious unmet-attribute findings. - Add unit tests: triple-duplicate deduplication, minionSkillTypes applicability (should not flag), disabled-group attr suppression. Claude-Session: https://claude.ai/code/session_01V9djNKo5yXSeEYjV2XP4WT Co-authored-by: Claude <noreply@anthropic.com>
|
🔄 Cycle 1, attempt 1/3 Dead-end check false positive for ClassStart-adjacent nodes (
✅ Agent succeeded (cycle 1, attempt 1) |
|
🔄 Cycle 1, attempt 1/3 Advisor.lua:195-240 — support applicability check diverges from engine Advisor.lua:370 — Advisor.lua:381 / tree check overlap — missing test ✅ Agent succeeded (cycle 1, attempt 1) |
- Fix calcLib nil-guard inversion: change (calcLib and doesTypeMatch(...)) to (not calcLib or doesTypeMatch(...)) so a missing calc env defaults to "applicable" (skip) instead of false-positive "inapplicable". - Add cannotBeSupported and supportGemsOnly guards to the support- applicability check to match calcLib.canGrantedEffectSupportActiveSkill (CalcTools.lua:85); skills with cannotBeSupported no longer have their supports evaluated. - Add Mastery = true to PAYOFF_TYPES so a Normal travel node whose only allocated payoff is a Mastery node is not flagged tree.deadend. - Add tests: Mastery as payoff (no deadend), Normal-leaf adjacent to unallocated Notable documents that both tree.deadend and tree.adjacent fire independently (expected and intentional overlap). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V9djNKo5yXSeEYjV2XP4WT
|
🔄 Cycle 1, attempt 1/3 The loop that builds the effective skill-type set from support gems' Advisor.lua — and not (ge.supportGemsOnly and not activeGem.gemData)
spec/Modules/Advisor_spec.lua — no coverage for There is no test that places a support gem with ✅ Agent succeeded (cycle 1, attempt 1) |
- Guard addSkillTypes accumulation with gem.enabled ~= false so disabled supports cannot silently widen the effective type set and mask valid inapplicable findings on enabled supports. - Remove the dead supportGemsOnly guard: groupActiveEffect guarantees activeGem.gemData is non-nil, so the condition was always false and the guard never fired; remove it to eliminate the dead branch. - Add test: addSkillTypes broadening is respected for enabled supports only — the same follower support is not flagged when the adder is enabled (type set widened) and IS flagged when it is disabled. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V9djNKo5yXSeEYjV2XP4WT
|
🔄 Cycle 1, attempt 1/3
✅ Agent succeeded (cycle 1, attempt 1) |
- Restructure inapplicable-support check to early-return with ConPrintf when calcLib is nil, making degradation explicit instead of silently producing zero findings; inline calcLib guards on applies line removed. - Switch addSkillTypes accumulation from pairs to ipairs: the field is always an ordered array (matches CalcActiveSkill.lua:341 convention). - Add tests: disabled group suppresses support.inapplicable and support.empty findings (parallel to the existing attr.unmet coverage). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V9djNKo5yXSeEYjV2XP4WT
|
🔄 Cycle 1, attempt 1/3
After full review of all logic, nil-safety, tests, and integration with
The ✅ Agent succeeded (cycle 1, attempt 1) |
Epic #85 — native deterministic build-advisor tab
Implements the full Advisor epic (#85, sub-issues #77–#84): a native, fully-offline
build-advisor tab. It reads the live, already-calculated build and surfaces rule-based
improvement findings. No LLM, no network — pure deterministic Lua over PoB's own
engine output, so every number it cites matches what PoB shows.
This branch bundles the 8 sub-issues, each developed on its own branch and merged into the
epic with a clean first-parent history.
What's included
src/Modules/Advisor.lua— pure logic (Advisor.analyze(build) -> findings), unit-testable headlessly. 14 checks across Survivability, Skills, Attributes, Spirit, and Tree.src/Classes/AdvisorTab.lua— UI tab: findings grouped by category, severity filters + "High only", collapsible headers with counts, click-to-jump, live auto-refresh on recalc.src/Modules/Build.lua— 3 small additive hunks: tab instantiation, mode button + high-severity badge, draw dispatch.spec/Modules/Advisor_spec.lua(20 unit tests, every check) +spec/System/TestAdvisorSmoke_spec.lua(2 headless smoke tests that run every check unguarded on a real engine-calculated build).ADVISOR.md(check catalogue + how to add a check) andADVISOR-DEV.md(headless/test commands, upstream rebase workflow, touched-files list).Check catalogue (id → severity)
res.<elem>.uncapped(high/med),res.<elem>.surplus(info),ehp.low(med),recovery.none(med),mitigation.none(med),maxhit.weakest(info)support.inapplicable.<name>(high),support.empty.<skill>(info),support.duplicate.<id>(med)attr.unmet.<Attr>.<gem>(high)spirit.over(high),spirit.unused(info)tree.adjacent.<id>(info),tree.deadend.<id>(med),tree.floating(med)The support-applicability check uses the engine's own
calcLib.doesTypeExpressionMatchagainst the active skill's tags, so it never relies on a re-derived tag table.
Upstream surface
Only
src/Modules/Build.luais modified (3 additive hunks); everything else is new,self-contained files. This keeps upstream rebases cheap.
Test plan
503 successes / 0 failures / 0 errors(--exclude-tags builds,data)22 successes / 0 failuressrc/Data/,ModParser, orModCachechanges → no cache regen neededbuildsanddatamatrices (verified by GitHub Actions on this PR)🤖 Generated with Claude Code