Skip to content

fix;docs;refactor;build;i18n;chore - #52

Open
YDW99 wants to merge 25 commits into
mainfrom
upload
Open

fix;docs;refactor;build;i18n;chore#52
YDW99 wants to merge 25 commits into
mainfrom
upload

Conversation

@YDW99

@YDW99 YDW99 commented Jul 19, 2026

Copy link
Copy Markdown
Owner

Summary by Gitar

  • Engine Stability:
    • Fixed MainActivity retry loop by correctly incrementing initRetryCount in the null-engine fallback path.
    • Closed final StockfishNative shutdown race by adding Thread.isInterrupted() checks and a final _lifecycleGeneration re-check.
  • Documentation:
    • Added missing HapticManager.java, ui-gameflow.js, and ui-interactions.js to the GPL v3 file list in README.md and NOTICE.
    • Corrected historical license labels for StatsActivity.java and updated CMake prerequisites to 3.31.6 in README.md.
    • Standardized worklog.md by replacing machine-specific file paths with <project-root> placeholders.
  • SonarCloud Cleanup:
    • Applied 47 optional-chaining (e?.message) and 2 .startsWith() conversions to chess.src/*.js and stats.html.
    • Removed dead code in ui.js including unused local variables in _renderReviewMode and _findCriticalMoves.
  • Bug Fixes:
    • Fixed PGN header parsing in worker-pool.js and _syncParsePGNText by correctly consuming trailing brackets.
    • Resolved EngineConfigHelper CPU frequency detection bug where BogoMIPS incorrectly overwrote CPU max MHz values.

This will update automatically on new commits.

YDW99 and others added 14 commits July 16, 2026 19:24
Signed-off-by: D.W. Yang <1151712579@qq.com>
Signed-off-by: D.W. Yang <1151712579@qq.com>
Signed-off-by: D.W. Yang <1151712579@qq.com>
Signed-off-by: D.W. Yang <1151712579@qq.com>
Signed-off-by: D.W. Yang <1151712579@qq.com>
Signed-off-by: D.W. Yang <1151712579@qq.com>
Signed-off-by: D.W. Yang <1151712579@qq.com>
@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR updates v1.2.3 chess gameplay, PGN and Chess960 handling, split UI modules, Android runtime behavior, build configuration, and release documentation.

Changes

Gameplay and PGN flow

Layer / File(s) Summary
Chess rules, PGN, and state contracts
src/main/assets/chess.src/*
Updates designated Chess960 rook tracking, timeout-draw adjudication, PGN/FEN parsing, ECO lookups, state snapshots, and exported module symbols.
Game flow and UI interactions
src/main/assets/chess.src/ui-gameflow.js, src/main/assets/chess.src/ui-interactions.js, src/main/assets/chess.src/ui.js
Adds split game-flow modules, clocks, clock-aware undo/redo, setup restoration, review rendering helpers, guarded dialogs, and interaction flows.
Android runtime hardening
src/main/java/com/Regalia/*
Adds HapticManager and updates WebView recovery, engine lifecycle, URI/cache I/O, UCI validation, timing, and sensor registration.
Build and release records
BUILDING.md, build.gradle, build-chess.py, README.md, NOTICE, PRIVACY.md, Manual/*, worklog.md
Updates CMake and APK instructions, bundle ordering, manifest configuration, privacy records, license classifications, manuals, and v1.2.3 round history.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related issues

Possibly related PRs

  • YDW99/Regalia#51 — Shares Chess960, PGN/FEN, Android hardening, and v1.2.3 changes.

Poem

A rabbit checks the clockwork bright,
Chess960 rooks now land just right.
PGN tags hop into line,
Haptics hum and engines shine.
Build notes bloom in version three—
A tidy burrow, happily!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 64.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive 标题只是标签列表,未概括此次变更的主要内容,因此过于笼统。 请改成一句简短且具体的标题,直接说明本次核心改动。
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed 描述与本次代码、文档和构建修复均相关,且覆盖了主要改动点。
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Comment @coderabbitai help to get the list of available commands.

Comment thread src/main/assets/chess.src/ui-interactions.js

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 14

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@assets/README.license`:
- Around line 4-9: Update the history in assets/README.license beyond the
existing round-22 entry through round-28, adding explicit no-change entries
consistent with the current release documentation; if the directory history is
intentionally capped, document that rationale instead.

In `@build.gradle`:
- Around line 184-192: The CMake configuration currently claims a minimum
version while externalNativeBuild.cmake.version requires an exact selector. In
build.gradle lines 184-192, change the version to the exact 3.31.6 pin and
ensure the corresponding exact CMake package is installed; in README.md lines
409-413, update the release note to describe the exact-version guarantee rather
than a 3.31.6-or-newer requirement.

In `@Manual/Regalia-v1.2.3-manual-zh.html`:
- Line 1856: Update the toolbar-order paragraph to include the 💾 button between
the 📝 PGN button and the 📚 PGN cache management button, matching the
documented mockup order while preserving the surrounding description.

In `@NOTICE`:
- Around line 91-129: Correct the license labels for DroidFish-derived files: in
NOTICE lines 91-129, change tablebase.js, stats.html, and worker-pool.js to GPL
v3; in NOTICE lines 207-236, change JsBridgeGateway.java to GPL v3; and in
src/main/assets/README.license lines 42-49, 68-72, and 107-116, change each
stats.html entry to GPL v3. Make no other classification changes.

In `@README.md`:
- Around line 393-395: Synchronize both permission inventories with the manifest
change by removing ACCESS_NETWORK_STATE from the current permission summaries in
README.md (around lines 319-326; referenced at lines 393-395) and
src/main/README.license (around lines 318-326; referenced at lines 70-77). No
other permission or manifest entries require changes.
- Around line 349-351: Remove the release signing key credentials, keystore
backup path, and certificate-reset details from the README section around the
release APK notes. Keep only non-sensitive build and release verification
information, and ensure signing credentials and local key paths are not
documented publicly.

In `@src/main/assets/chess.src/ai-bridge.js`:
- Around line 3524-3525: Replace the block-scoped temporary variables `info` and
`s` in the engine-info and engine-settings `try` blocks with `const`, preserving
their current scope and JSON parsing behavior.

In `@src/main/assets/chess.src/ui-gameflow.js`:
- Around line 311-322: Update the timeout handling around isDeadPosition() to
use a winner-side mating-possibility check, evaluating whether the winner can
checkmate rather than applying the symmetric dead-position test to the full game
state. Preserve the existing draw flag, error handling, and winner determination
while ensuring the timeout is declared a draw whenever the winner lacks
sufficient mating potential.

In `@src/main/assets/chess.src/ui-interactions.js`:
- Around line 102-107: Update the timer restart logic around initGameClocks so
restored clock state is preserved: when restarting after an existing
gameClockTimerId, start or schedule the timer without invoking initGameClocks(),
which rebuilds clocks from dlgTimeControl.baseSec. Ensure _restoreClocks()
retains the restored remainingSec and displayRemainingSec values while
continuing to restart active timers for non-game-over states.

In `@src/main/assets/stats.html`:
- Line 698: Replace the backtracking-prone PGN tag-removal regex used by mtCheck
and moveText with the escaped-quote-aware canonical tag regex from chess.html,
avoiding overlapping whitespace-consuming patterns while preserving tag removal.
Apply the same correction at src/main/assets/stats.html lines 698-698, 713-713,
1518-1518, and 1558-1558.

In `@src/main/java/com/Regalia/StockfishNative.java`:
- Around line 166-167: Declare the _hapticManager field in StockfishNative as
final, preserving its single constructor assignment and existing use by the
isHapticEnabled and performHaptic delegates.

In `@src/main/res/README.license`:
- Around line 66-70: Update the existing res/xml summary near the backup
resource entries to match the manifest and new note: remove the claim that
fullBackupContent and dataExtractionRules reference these files, or clearly mark
that description as historical. Keep the backup_rules.xml and
data_extraction_rules.xml entries consistent with their retained-for-reference
status.

In `@worklog.md`:
- Around line 417-419: Update the round-23 entry in worklog.md so the stated PDF
count matches the number of filenames listed, preserving the existing filenames
and audit-record wording.
- Around line 1-3: Normalize worklog.md Markdown structure by adding blank lines
around all headings and tables implicated by MD022 and MD058, including the
referenced sections. Rename or otherwise disambiguate repeated ## 任务来源 headings,
including the occurrences near the listed sections, while preserving their
content and hierarchy so MD024 passes.
🪄 Autofix (Beta)

❌ Autofix failed (check again to retry)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: c7880f99-37c7-4c98-8d31-5f73d5552ec0

📥 Commits

Reviewing files that changed from the base of the PR and between aa1b4bf and bfc11e6.

⛔ Files ignored due to path filters (1)
  • LICENSE&NOTICE.zip is excluded by !**/*.zip
📒 Files selected for processing (46)
  • BUILDING.md
  • Manual/README.license
  • Manual/Regalia-v1.2.3-manual-en.html
  • Manual/Regalia-v1.2.3-manual-zh.html
  • NOTICE
  • PRIVACY.md
  • README.md
  • assets/README.license
  • build-chess.py
  • build.gradle
  • gradle.properties
  • src/main/AndroidManifest.xml
  • src/main/README.license
  • src/main/assets/README.license
  • src/main/assets/chess.html
  • src/main/assets/chess.src/README.license
  • src/main/assets/chess.src/ai-bridge.js
  • src/main/assets/chess.src/chess960.js
  • src/main/assets/chess.src/eco-data.js
  • src/main/assets/chess.src/game-logic.js
  • src/main/assets/chess.src/index.html.tpl
  • src/main/assets/chess.src/pgn-standard.js
  • src/main/assets/chess.src/tablebase.js
  • src/main/assets/chess.src/ui-gameflow.js
  • src/main/assets/chess.src/ui-interactions.js
  • src/main/assets/chess.src/ui.js
  • src/main/assets/chess.src/worker-pool.js
  • src/main/assets/stats.html
  • src/main/cpp/README.license
  • src/main/java/com/Regalia/ChessWebViewClient.java
  • src/main/java/com/Regalia/EngineConfigHelper.java
  • src/main/java/com/Regalia/EngineService.java
  • src/main/java/com/Regalia/FileIoHelper.java
  • src/main/java/com/Regalia/HapticManager.java
  • src/main/java/com/Regalia/JsBridgeGateway.java
  • src/main/java/com/Regalia/MainActivity.java
  • src/main/java/com/Regalia/PgnCacheManager.java
  • src/main/java/com/Regalia/README.license
  • src/main/java/com/Regalia/SafPickerHelper.java
  • src/main/java/com/Regalia/StabilizationHelper.java
  • src/main/java/com/Regalia/StatsActivity.java
  • src/main/java/com/Regalia/StockfishNative.java
  • src/main/java/com/Regalia/TlsSecurityHelper.java
  • src/main/res/README.license
  • src/main/res/xml/network_security_config.xml
  • worklog.md
📜 Review details
⏰ Context from checks skipped due to timeout. (2)
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: Gitar
🧰 Additional context used
🪛 ast-grep (0.44.1)
src/main/java/com/Regalia/PgnCacheManager.java

[warning] 197-197: Prevent path traversal
Context: new File(getCacheDir(), safe + ".pgn")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal'). Security best practice.

(path-traversal-java)

src/main/assets/chess.html

[error] 8695-8697: React's useState should not be directly called
Context: setTimeout(function(){
try{reviewAnalyzeAll();}catch(e){console.error('openStatsPage: deferred analyze-all trigger failed:',e);}
},1000)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[error] 12860-12860: React's useState should not be directly called
Context: setChess960Mode(true)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[error] 16303-16308: React's useState should not be directly called
Context: setTimeout(function() {
if (typeof _engineReady !== 'undefined' && (_engineReady || document.getElementById('board-grid'))) {
try{localStorage.removeItem('Regalia_recovery');}catch(e){console.warn('[UI]',e?.message?e.message:e);}
try{if(typeof AndroidBridge!=='undefined'&&AndroidBridge.persistentRemove)AndroidBridge.persistentRemove('Regalia_recovery');}catch(e){console.warn('[UI]',e&&e.message?e.message:e);}
}
}, 5000)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[error] 19573-19575: React's useState should not be directly called
Context: setTimeout(function(){
try{showToast(T('board_debounce_hint'),4500);}catch(e){console.warn('[UI]',e?.message?e.message:e);}
},400)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[error] 19619-19619: React's useState should not be directly called
Context: setTimeout(()=>{const list=document.querySelector('.op-list');if(list){const active=list.querySelector('.op-btn.act');if(active)active.scrollIntoView({block:'center',behavior:'smooth'})}},50)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[error] 21589-21592: React's useState should not be directly called
Context: setTimeout(function(){
try{_pgnCacheSaveCurrentImpl_SkipCoverageCheck(_pendingSave.name,_pendingSave.includeAnn);}
catch(e){showToast(T('pgn_cache_save_failed'),2500);}
},150)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[error] 21596-21599: React's useState should not be directly called
Context: setTimeout(function(){
try{if(typeof openStatsPage==='function')openStatsPage();}
catch(e){console.error('Deferred openStatsPage failed:',e);}
},150)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)

src/main/assets/chess.src/ui-gameflow.js

[warning] 245-245: Avoid using the initial state variable in setState
Context: setInterval(_tickGameClock,200)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(setstate-same-var)


[error] 94-94: React's useState should not be directly called
Context: setChess960Mode(true)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[error] 112-112: React's useState should not be directly called
Context: setChess960Mode(false)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[error] 245-245: React's useState should not be directly called
Context: setInterval(_tickGameClock,200)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)

src/main/assets/chess.src/tablebase.js

[error] 69-69: React's useState should not be directly called
Context: setChess960Mode(true)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[error] 91-91: React's useState should not be directly called
Context: setChess960Mode(false)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[error] 1050-1050: React's useState should not be directly called
Context: setChess960Mode(true)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)

src/main/assets/chess.src/ui-interactions.js

[warning] 388-406: Avoid using the initial state variable in setState
Context: setTimeout(()=>{
try{
if(gameState.hash!==_hashAtSched)return; // stale — abort
const gsr=!setupMode&&gameStatus(gameState);
const _gsKey=gameState.hash+'|'+gameState.currentTurn;_cachedStatus=gsr;_cachedStatusKey=_gsKey;
if(gsr&&!gameOver){
gameOverSoundPlayed=false;_applyGameOver(gsr);
requestAnimationFrame(()=>{updateAfterMove();});
// v1.0.2 NEW FEATURE: After a player move, check if any pending engine PV
// has diverged from the actual game. This must be called AFTER the move is
// pushed to moveRecords (which happens before this setTimeout).
// We call it here (in the deferred callback) because the move record needs
// to be fully populated first.
try{if(typeof _checkPVDivergence==='function')_checkPVDivergence();}catch(e){console.warn('PVDivergence check failed:',e);}
try{if(typeof _checkPVDivergenceSANs==='function')_checkPVDivergenceSANs();}catch(e){console.warn('PVDivergenceSANs check failed:',e);}
if(!gameOver&&gameState.currentTurn!==playerColor){setTimeout(doAIMove,0);}
}
}catch(e){console.error('executeMove deferred callback error:',e)}
},_deferMs)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(setstate-same-var)


[warning] 403-403: Avoid using the initial state variable in setState
Context: setTimeout(doAIMove,0)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(setstate-same-var)


[warning] 1218-1218: Avoid using the initial state variable in setState
Context: setTimeout(_waitForDialog,200)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(setstate-same-var)


[warning] 1224-1224: Avoid using the initial state variable in setState
Context: setTimeout(_waitForDialog,200)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(setstate-same-var)


[warning] 663-663: Avoid assigning untrusted data to innerHTML/outerHTML or document.write
Context: btn.innerHTML=soundOn?'<span style="font-size:1.4rem">🔊 '+T('sound'):'<span style="font-size:1.4rem">🔇 '+T('sound')
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting').

(inner-outer-html)


[error] 388-406: React's useState should not be directly called
Context: setTimeout(()=>{
try{
if(gameState.hash!==_hashAtSched)return; // stale — abort
const gsr=!setupMode&&gameStatus(gameState);
const _gsKey=gameState.hash+'|'+gameState.currentTurn;_cachedStatus=gsr;_cachedStatusKey=_gsKey;
if(gsr&&!gameOver){
gameOverSoundPlayed=false;_applyGameOver(gsr);
requestAnimationFrame(()=>{updateAfterMove();});
// v1.0.2 NEW FEATURE: After a player move, check if any pending engine PV
// has diverged from the actual game. This must be called AFTER the move is
// pushed to moveRecords (which happens before this setTimeout).
// We call it here (in the deferred callback) because the move record needs
// to be fully populated first.
try{if(typeof _checkPVDivergence==='function')_checkPVDivergence();}catch(e){console.warn('PVDivergence check failed:',e);}
try{if(typeof _checkPVDivergenceSANs==='function')_checkPVDivergenceSANs();}catch(e){console.warn('PVDivergenceSANs check failed:',e);}
if(!gameOver&&gameState.currentTurn!==playerColor){setTimeout(doAIMove,0);}
}
}catch(e){console.error('executeMove deferred callback error:',e)}
},_deferMs)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[error] 698-705: React's useState should not be directly called
Context: setTimeout(()=>{
if(typeof AndroidBridge!=='undefined'&&typeof AndroidBridge.isEngineReady==='function'&&AndroidBridge.isEngineReady()){
try{AndroidBridge.engineHint((typeof _sanitizeFenForEngine==='function')?_sanitizeFenForEngine(generateFEN(gameState)):generateFEN(gameState));}catch(e){console.error('engineHint error:',e);isHintLoading=false;_hintBarInfo='';hintText=T('hint_request_failed');render();}
return;
}
isHintLoading=false;hintText=T('engine_unavailable_hint');
render();
},10)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[error] 1065-1065: React's useState should not be directly called
Context: setChess960Mode(true)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[error] 1070-1070: React's useState should not be directly called
Context: setChess960Mode(false)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[error] 1218-1218: React's useState should not be directly called
Context: setTimeout(_waitForDialog,200)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[error] 1224-1224: React's useState should not be directly called
Context: setTimeout(_waitForDialog,200)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[error] 1237-1237: React's useState should not be directly called
Context: setTimeout(function(){_skipPGNSavePrompt=false;},100)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)

src/main/assets/chess.src/ai-bridge.js

[error] 686-688: React's useState should not be directly called
Context: setTimeout(function(){
try{if(typeof _maybeShowBoardDebounceHint==='function')_maybeShowBoardDebounceHint();}catch(e){console.warn('[AIBridge]',e&&e.message?e.message:e);}
},600)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[error] 1535-1537: React's useState should not be directly called
Context: setTimeout(function(){
try{reviewAnalyzeAll();}catch(e){console.error('openStatsPage: deferred analyze-all trigger failed:',e);}
},1000)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[error] 2505-2505: React's useState should not be directly called
Context: setTimeout(()=>{if(!gameOver&&!reviewMode&&!setupMode&&gameState.currentTurn!==playerColor)doAIMove();},0)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[error] 2514-2514: React's useState should not be directly called
Context: setTimeout(()=>{if(!gameOver&&!reviewMode&&!setupMode&&gameState.currentTurn!==playerColor)doAIMove();},0)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)

src/main/assets/chess.src/ui.js

[error] 328-333: React's useState should not be directly called
Context: setTimeout(function() {
if (typeof _engineReady !== 'undefined' && (_engineReady || document.getElementById('board-grid'))) {
try{localStorage.removeItem('Regalia_recovery');}catch(e){console.warn('[UI]',e?.message?e.message:e);}
try{if(typeof AndroidBridge!=='undefined'&&AndroidBridge.persistentRemove)AndroidBridge.persistentRemove('Regalia_recovery');}catch(e){console.warn('[UI]',e&&e.message?e.message:e);}
}
}, 5000)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[error] 3598-3600: React's useState should not be directly called
Context: setTimeout(function(){
try{showToast(T('board_debounce_hint'),4500);}catch(e){console.warn('[UI]',e?.message?e.message:e);}
},400)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[error] 3644-3644: React's useState should not be directly called
Context: setTimeout(()=>{const list=document.querySelector('.op-list');if(list){const active=list.querySelector('.op-btn.act');if(active)active.scrollIntoView({block:'center',behavior:'smooth'})}},50)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[error] 5614-5617: React's useState should not be directly called
Context: setTimeout(function(){
try{_pgnCacheSaveCurrentImpl_SkipCoverageCheck(_pendingSave.name,_pendingSave.includeAnn);}
catch(e){showToast(T('pgn_cache_save_failed'),2500);}
},150)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[error] 5621-5624: React's useState should not be directly called
Context: setTimeout(function(){
try{if(typeof openStatsPage==='function')openStatsPage();}
catch(e){console.error('Deferred openStatsPage failed:',e);}
},150)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)

🪛 GitHub Check: SonarCloud Code Analysis
src/main/java/com/Regalia/HapticManager.java

[warning] 413-413: This block of commented-out lines of code should be removed.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ftcJq4IVm24_IAqO&open=AZ94ftcJq4IVm24_IAqO&pullRequest=52


[warning] 467-467: This block of commented-out lines of code should be removed.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ftcJq4IVm24_IAqQ&open=AZ94ftcJq4IVm24_IAqQ&pullRequest=52


[warning] 445-445: Extract this nested ternary operation into an independent statement.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ftcJq4IVm24_IAqP&open=AZ94ftcJq4IVm24_IAqP&pullRequest=52

src/main/assets/chess.html

[warning] 3134-3134: Extract this nested ternary operation into an independent statement.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ft0bq4IVm24_IArA&open=AZ94ft0bq4IVm24_IArA&pullRequest=52


[failure] 3134-3134: Refactor this function to reduce its Cognitive Complexity from 36 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ft0bq4IVm24_IAq-&open=AZ94ft0bq4IVm24_IAq-&pullRequest=52


[warning] 3870-3870: Extract this nested ternary operation into an independent statement.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ft0bq4IVm24_IArC&open=AZ94ft0bq4IVm24_IArC&pullRequest=52


[warning] 3870-3870: This statement will not be executed conditionally; only the first statement will be. The rest will execute unconditionally.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ft0bq4IVm24_IArB&open=AZ94ft0bq4IVm24_IArB&pullRequest=52


[warning] 4406-4406: This statement will not be executed conditionally; only the first statement will be. The rest will execute unconditionally.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ft0bq4IVm24_IArL&open=AZ94ft0bq4IVm24_IArL&pullRequest=52


[warning] 4406-4406: This statement will not be executed conditionally; only the first statement will be. The rest will execute unconditionally.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ft0bq4IVm24_IArG&open=AZ94ft0bq4IVm24_IArG&pullRequest=52


[warning] 8503-8503: Extract this nested ternary operation into an independent statement.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ft0bq4IVm24_IArO&open=AZ94ft0bq4IVm24_IArO&pullRequest=52


[warning] 14335-14335: Compare with undefined directly instead of using typeof.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ft0bq4IVm24_IArR&open=AZ94ft0bq4IVm24_IArR&pullRequest=52


[warning] 14469-14469: Compare with undefined directly instead of using typeof.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ft0bq4IVm24_IArS&open=AZ94ft0bq4IVm24_IArS&pullRequest=52


[warning] 15490-15490: Compare with undefined directly instead of using typeof.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ft0bq4IVm24_IArV&open=AZ94ft0bq4IVm24_IArV&pullRequest=52


[warning] 16254-16254: Use .includes(), rather than .indexOf(), when checking for existence.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ft0bq4IVm24_IArW&open=AZ94ft0bq4IVm24_IArW&pullRequest=52


[warning] 18353-18353: Function '_renderRvBoardCells' has too many parameters (8). Maximum allowed is 7.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ft0bq4IVm24_IArY&open=AZ94ft0bq4IVm24_IArY&pullRequest=52


[failure] 18353-18353: Refactor this function to reduce its Cognitive Complexity from 100 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ft0bq4IVm24_IArZ&open=AZ94ft0bq4IVm24_IArZ&pullRequest=52


[warning] 18564-18564: Remove the declaration of the unused '_isLandscapeReview' variable.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ft0bq4IVm24_IArb&open=AZ94ft0bq4IVm24_IArb&pullRequest=52


[failure] 21588-21588: Refactor this function to reduce its Cognitive Complexity from 17 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ft0bq4IVm24_IArd&open=AZ94ft0bq4IVm24_IArd&pullRequest=52

src/main/assets/chess.src/ui-gameflow.js

[failure] 324-324: Add the "let", "const" or "var" keyword to this declaration of "_timeoutWinnerColor" to make it explicit.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ftryq4IVm24_IAq0&open=AZ94ftryq4IVm24_IAq0&pullRequest=52


[failure] 279-279: Refactor this function to reduce its Cognitive Complexity from 20 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ftryq4IVm24_IAqz&open=AZ94ftryq4IVm24_IAqz&pullRequest=52

src/main/assets/stats.html

[warning] 713-713: Simplify this regular expression to reduce its runtime, as it has super-linear performance due to backtracking.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ftvMq4IVm24_IAq5&open=AZ94ftvMq4IVm24_IAq5&pullRequest=52


[warning] 1518-1518: Simplify this regular expression to reduce its runtime, as it has super-linear performance due to backtracking.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ftvMq4IVm24_IAq6&open=AZ94ftvMq4IVm24_IAq6&pullRequest=52


[warning] 3928-3928: Prefer String#replaceAll() over String#replace().

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ftvMq4IVm24_IAq8&open=AZ94ftvMq4IVm24_IAq8&pullRequest=52

src/main/assets/chess.src/tablebase.js

[warning] 205-205: Simplify this regular expression to reduce its runtime, as it has super-linear performance due to backtracking.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94fts3q4IVm24_IAq1&open=AZ94fts3q4IVm24_IAq1&pullRequest=52


[warning] 1429-1429: Prefer using an optional chain expression instead, as it's more concise and easier to read.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94fts3q4IVm24_IAq2&open=AZ94fts3q4IVm24_IAq2&pullRequest=52

src/main/assets/chess.src/ui-interactions.js

[failure] 99-99: Add the "let", "const" or "var" keyword to this declaration of "gameClockExpired" to make it explicit.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ftq3q4IVm24_IAqv&open=AZ94ftq3q4IVm24_IAqv&pullRequest=52


[failure] 1075-1075: Add the "let", "const" or "var" keyword to this declaration of "gameSPID" to make it explicit.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ftq3q4IVm24_IAqy&open=AZ94ftq3q4IVm24_IAqy&pullRequest=52


[warning] 387-387: Prefer using an optional chain expression instead, as it's more concise and easier to read.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ftq3q4IVm24_IAqx&open=AZ94ftq3q4IVm24_IAqx&pullRequest=52

src/main/assets/chess.src/ai-bridge.js

[warning] 1004-1004: Compare with undefined directly instead of using typeof.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ftkrq4IVm24_IAqR&open=AZ94ftkrq4IVm24_IAqR&pullRequest=52


[warning] 1343-1343: Extract this nested ternary operation into an independent statement.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ftkrq4IVm24_IAqU&open=AZ94ftkrq4IVm24_IAqU&pullRequest=52


[warning] 1901-1901: Prefer using an optional chain expression instead, as it's more concise and easier to read.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ftkrq4IVm24_IAqV&open=AZ94ftkrq4IVm24_IAqV&pullRequest=52


[warning] 2317-2317: Prefer using an optional chain expression instead, as it's more concise and easier to read.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ftkrq4IVm24_IAqX&open=AZ94ftkrq4IVm24_IAqX&pullRequest=52


[failure] 3525-3525: Unexpected var, use let or const instead.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ftkrq4IVm24_IAqZ&open=AZ94ftkrq4IVm24_IAqZ&pullRequest=52

src/main/assets/chess.src/game-logic.js

[failure] 1817-1817: Refactor this function to reduce its Cognitive Complexity from 36 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ftm2q4IVm24_IAqa&open=AZ94ftm2q4IVm24_IAqa&pullRequest=52


[warning] 1817-1817: Extract this nested ternary operation into an independent statement.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ftm2q4IVm24_IAqc&open=AZ94ftm2q4IVm24_IAqc&pullRequest=52


[warning] 1923-1923: Prefer using an optional chain expression instead, as it's more concise and easier to read.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ftm2q4IVm24_IAqd&open=AZ94ftm2q4IVm24_IAqd&pullRequest=52


[warning] 2553-2553: This statement will not be executed conditionally; only the first statement will be. The rest will execute unconditionally.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ftm2q4IVm24_IAqg&open=AZ94ftm2q4IVm24_IAqg&pullRequest=52


[warning] 2553-2553: This statement will not be executed conditionally; only the first statement will be. The rest will execute unconditionally.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ftm2q4IVm24_IAqe&open=AZ94ftm2q4IVm24_IAqe&pullRequest=52


[warning] 3089-3089: This statement will not be executed conditionally; only the first statement will be. The rest will execute unconditionally.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ftm2q4IVm24_IAql&open=AZ94ftm2q4IVm24_IAql&pullRequest=52


[warning] 3089-3089: This statement will not be executed conditionally; only the first statement will be. The rest will execute unconditionally.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ftm2q4IVm24_IAqh&open=AZ94ftm2q4IVm24_IAqh&pullRequest=52


[warning] 3089-3089: This statement will not be executed conditionally; only the first statement will be. The rest will execute unconditionally.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ftm2q4IVm24_IAqo&open=AZ94ftm2q4IVm24_IAqo&pullRequest=52


[warning] 3089-3089: This statement will not be executed conditionally; only the first statement will be. The rest will execute unconditionally.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ftm2q4IVm24_IAqk&open=AZ94ftm2q4IVm24_IAqk&pullRequest=52


[warning] 3089-3089: This statement will not be executed conditionally; only the first statement will be. The rest will execute unconditionally.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ftm2q4IVm24_IAqm&open=AZ94ftm2q4IVm24_IAqm&pullRequest=52


[warning] 3089-3089: This statement will not be executed conditionally; only the first statement will be. The rest will execute unconditionally.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ftm2q4IVm24_IAqi&open=AZ94ftm2q4IVm24_IAqi&pullRequest=52

src/main/assets/chess.src/ui.js

[failure] 2452-2452: Refactor this function to reduce its Cognitive Complexity from 22 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ftpZq4IVm24_IAqr&open=AZ94ftpZq4IVm24_IAqr&pullRequest=52


[warning] 2378-2378: Function '_renderRvBoardCells' has too many parameters (8). Maximum allowed is 7.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ftpZq4IVm24_IAqp&open=AZ94ftpZq4IVm24_IAqp&pullRequest=52


[failure] 3641-3641: Add the "let", "const" or "var" keyword to this declaration of "_ecoSearchFocused" to make it explicit.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ftpZq4IVm24_IAqt&open=AZ94ftpZq4IVm24_IAqt&pullRequest=52


[failure] 5613-5613: Refactor this function to reduce its Cognitive Complexity from 17 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ftpZq4IVm24_IAqu&open=AZ94ftpZq4IVm24_IAqu&pullRequest=52

🪛 LanguageTool
worklog.md

[duplication] ~29-~29: Možný preklep: zopakovali ste slovo
Context: ...原值(正确),但为快照完整性仍应包含。 - _snapshotClocks 新增 baseSec:gameClocks.baseSec||0 - _restoreClocks 新增 `if(snap.baseSec!==undefined)gameClocks...

(WORD_REPEAT_RULE)


[typographical] ~507-~507: Nepárový symbol: zdá sa, že chýba '['
Context: ...非引号感知**(tablebase.js + stats.html 4 处): /\[\w+\s+\S[^\]]*\]/g → `/[\s*\w+\s+(?:"[^"]"|[^\]]?)\s...

(UNPAIRED_BRACKETS)


[typographical] ~508-~508: Nepárový symbol: zdá sa, že chýba ']'
Context: ...html 4 处): /\[\w+\s+\S[^\]]*\]/g/\[\s*\w+\s+(?:"[^"]*"|[^\]]*?)\s*\]/g,引号分...

(UNPAIRED_BRACKETS)


[typographical] ~517-~517: Dve po sebe idúce bodky
Context: ...t[], int) API(API 26+)。float[] 振幅 [0..1] 缩放至 int[] [0..255],long[] 时长原样传递,保留多阶...

(DOUBLE_PUNCTUATION)


[typographical] ~517-~517: Dve po sebe idúce bodky
Context: ... 26+)。float[] 振幅 [0..1] 缩放至 int[] [0..255],long[] 时长原样传递,保留多阶段包络语义。17 个 触觉...

(DOUBLE_PUNCTUATION)


[typographical] ~535-~535: Nepárový symbol: zdá sa, že chýba '"'
Context: ...Q8:worker-pool.js 的 headerRe 已是引号感知("((?:[^"\\]|\\.)*)" 处理转义引号), 无需改动;记录为部...

(UNPAIRED_BRACKETS)


[typographical] ~568-~568: Dve po sebe idúce bodky
Context: ...[]) 与原 tryPwleVibrate 一致,float[] 振幅 [0..1] 缩放至 int[] [0..255](Math.round + clamp...

(DOUBLE_PUNCTUATION)


[typographical] ~568-~568: Dve po sebe idúce bodky
Context: ...rate 一致,float[] 振幅 [0..1] 缩放至 int[] [0..255](Math.round + clamp),long[] 时长 原样传...

(DOUBLE_PUNCTUATION)


[typographical] ~574-~574: Nepárový symbol: zdá sa, že chýba ')'
Context: ...terval)。 - Q7 引号感知正则:使用 alternation (?:"[^"]*"|[^\]]*?) 而非回溯分支。引号分支 优先匹配(消...

(UNPAIRED_BRACKETS)


[typographical] ~575-~575: Nepárový symbol: zdá sa, že chýba '['
Context: ...支。引号分支 优先匹配(消耗完整引号字符串),非引号分支非贪婪匹配到第一个 ]。验证无 ReDoS 风险 (分支互斥,非贪婪单字符类)。 ## 验证 -...

(UNPAIRED_BRACKETS)


[typographical] ~750-~750: Nepárový symbol: zdá sa, že chýba '['
Context: ...s.html:1518/1558 PGN 标签剥离正则 | 非误报 | /\[[A-Za-z]\w*\s+[^\]]+\]/g(\s+ 与 [^\]]+ 空白重叠→多项式回溯)改为 `/[\w+\s...

(UNPAIRED_BRACKETS)


[typographical] ~750-~750: Nepárový symbol: zdá sa, že chýba '['
Context: .../\[[A-Za-z]\w*\s+[^\]]+\]/g(\s+ 与 [^\]]+ 空白重叠→多项式回溯)改为 /\[\w+\s+\S[^\]]*\]/g(...

(UNPAIRED_BRACKETS)


[typographical] ~750-~750: Nepárový symbol: zdá sa, že chýba '['
Context: ...+[^\]]+]/g(\s+ 与 [^\]]+ 空白重叠→多项式回溯)改为 /[\w+\s+\S[^\]]*]/g`(相邻量词类互斥),同款 5 处全改(stats.html×4 + tab...

(UNPAIRED_BRACKETS)


[typographical] ~947-~947: Nepárový symbol: zdá sa, že chýba '{'
Context: ... - pgn-standard.js parseStandardPGN:游离 } 死循环防御修复(函数当前无调用方; RAV 归属方向/无引号标签未剥...

(UNPAIRED_BRACKETS)

🪛 markdownlint-cli2 (0.23.0)
worklog.md

[warning] 3-3: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 9-9: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 25-25: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 34-34: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 42-42: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 49-49: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 54-54: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 60-60: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 66-66: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 75-75: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 86-86: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 93-93: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 99-99: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 105-105: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 110-110: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 117-117: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 122-122: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 128-128: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 137-137: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 148-148: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 154-154: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 171-171: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 182-182: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 187-187: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 190-190: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 197-197: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 206-206: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 213-213: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 224-224: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 231-231: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 243-243: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 256-256: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 273-273: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 279-279: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 287-287: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 296-296: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 303-303: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 317-317: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 326-326: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 347-347: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 361-361: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 370-370: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 377-377: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 388-388: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 398-398: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 405-405: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 416-416: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 436-436: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 439-439: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 440-440: Tables should be surrounded by blank lines

(MD058, blanks-around-tables)


[warning] 463-463: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 484-484: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 491-491: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 534-534: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 539-539: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 561-561: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 578-578: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 593-593: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 603-603: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 610-610: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 625-625: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 632-632: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 646-646: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 656-656: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 667-667: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 677-677: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 686-686: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 690-690: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 696-696: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 702-702: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 715-715: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 721-721: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 726-726: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 738-738: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 746-746: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 747-747: Tables should be surrounded by blank lines

(MD058, blanks-around-tables)


[warning] 755-755: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 762-762: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)


[warning] 775-775: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 782-782: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 793-793: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 797-797: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 808-808: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 817-817: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 833-833: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 856-856: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 873-873: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 880-880: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 892-892: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 900-900: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 909-909: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 910-910: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)


[warning] 911-911: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)


[warning] 926-926: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 977-977: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 985-985: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 998-998: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 1012-1012: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 1012-1012: Multiple headings with the same content

(MD024, no-duplicate-heading)


[warning] 1017-1017: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 1029-1029: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 1040-1040: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 1063-1063: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 1083-1083: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 1087-1087: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 1101-1101: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 1110-1110: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)

BUILDING.md

[warning] 40-40: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 41-41: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 41-41: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 43-43: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 58-58: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)

🪛 OpenGrep (1.25.0)
src/main/assets/chess.src/ui-interactions.js

[WARNING] 664-664: Setting innerHTML with dynamic content can lead to XSS. Use textContent or createElement with proper escaping instead.

(coderabbit.xss.innerhtml-assignment)

src/main/assets/chess.src/game-logic.js

[WARNING] 3089-3089: Setting innerHTML with dynamic content can lead to XSS. Use textContent or createElement with proper escaping instead.

(coderabbit.xss.innerhtml-assignment)

🔇 Additional comments (48)
src/main/res/xml/network_security_config.xml (1)

54-54: LGTM!

Manual/Regalia-v1.2.3-manual-zh.html (1)

543-552: LGTM!

Also applies to: 698-703, 1899-1899, 1916-1916, 1928-1928, 1961-1961

src/main/res/README.license (1)

1-65: LGTM!

Also applies to: 71-79

src/main/assets/chess.src/worker-pool.js (1)

89-92: LGTM!

Also applies to: 121-125, 173-173, 290-290, 443-445, 486-486

src/main/assets/stats.html (1)

41-43: LGTM!

Also applies to: 801-801, 852-852, 897-897, 956-964, 1535-1557, 1602-1604, 1633-1641, 1703-1703, 1758-1758, 2678-2679, 2700-2701, 2767-2767, 3918-3930, 4225-4225

BUILDING.md (1)

40-58: 📐 Maintainability & Code Quality | 💤 Low value

Markdown lint violations in the new "Build APK"/"Requirements" section.

Static analysis flags missing blank lines around the ## Build APK / ## Requirements headings and around the fenced code block, plus a missing language tag on the fence.

📝 Proposed fix
 ## Build APK
+

+```bash
./gradlew assembleRelease

+
The signed APK (v1+v2+v3 signed with `../debug.keystore`) is output at
@@
> simply re-run `./gradlew assembleRelease` and it passes.

## Requirements
+
- JDK 21 (e.g. Temurin JDK 21.0.5+11) — must include `javac` (JRE-only is insufficient)

Source: Linters/SAST tools

Manual/README.license (1)

1-142: LGTM!

Manual/Regalia-v1.2.3-manual-en.html (1)

543-554: LGTM!

Also applies to: 700-705, 1833-1833, 1876-2857

NOTICE (1)

1-90: LGTM!

Also applies to: 130-206, 237-427

src/main/assets/README.license (1)

1-41: LGTM!

Also applies to: 50-67, 73-106, 117-136

src/main/assets/chess.src/README.license (1)

1-119: LGTM!

Also applies to: 124-419

src/main/cpp/README.license (1)

1-87: LGTM!

worklog.md (1)

503-504: 🎯 Functional Correctness

No issue: only the leading black-to-move placeholder is skipped; any other null aborts replay.

			> Likely an incorrect or invalid review comment.
PRIVACY.md (1)

57-126: LGTM!

Also applies to: 248-248, 279-314

build-chess.py (1)

55-61: LGTM!

Also applies to: 102-107

build.gradle (1)

123-128: LGTM!

gradle.properties (1)

77-82: LGTM!

src/main/AndroidManifest.xml (2)

31-34: LGTM!

Also applies to: 61-85


95-105: 🔒 Security & Privacy

Remove the backup-rule wiring comment. This manifest intentionally leaves android:allowBackup="false" in place, and the repository’s own notes treat both android:fullBackupContent and android:dataExtractionRules as dead configuration here.

			> Likely an incorrect or invalid review comment.
src/main/README.license (1)

1-68: LGTM!

Also applies to: 79-94

src/main/assets/chess.html (1)

14459-14524: LGTM!

src/main/assets/chess.src/ai-bridge.js (2)

2494-2517: LGTM!

Also applies to: 2597-2609


907-941: LGTM!

src/main/assets/chess.src/chess960.js (1)

457-491: LGTM!

Also applies to: 669-692

src/main/assets/chess.src/game-logic.js (3)

1577-1615: LGTM!


2058-2092: LGTM!

Also applies to: 2271-2313


3140-3145: LGTM!

src/main/assets/chess.src/index.html.tpl (1)

36-38: LGTM!

Also applies to: 211-214

src/main/assets/chess.src/pgn-standard.js (1)

762-769: LGTM!

Also applies to: 960-967

src/main/assets/chess.src/tablebase.js (2)

1429-1429: LGTM!

Also applies to: 1971-1975


58-95: LGTM!

src/main/java/com/Regalia/FileIoHelper.java (1)

287-294: LGTM!

src/main/assets/chess.src/eco-data.js (1)

133-139: LGTM!

src/main/assets/chess.src/ui-gameflow.js (1)

38-224: LGTM!

Also applies to: 226-276, 338-376

src/main/assets/chess.src/ui-interactions.js (1)

53-71: LGTM!

Also applies to: 233-408, 430-560, 562-614

src/main/assets/chess.src/ui.js (1)

276-336: LGTM!

Also applies to: 1390-1399, 1590-1608, 1669-1670, 2316-2562, 4535-4545, 6000-6004, 6082-6111

src/main/java/com/Regalia/ChessWebViewClient.java (1)

25-25: LGTM!

Also applies to: 86-104, 169-196, 213-244

src/main/java/com/Regalia/EngineConfigHelper.java (1)

544-548: LGTM!

src/main/java/com/Regalia/TlsSecurityHelper.java (1)

173-173: LGTM!

src/main/java/com/Regalia/EngineService.java (1)

295-298: LGTM!

src/main/java/com/Regalia/HapticManager.java (1)

47-471: LGTM!

src/main/java/com/Regalia/JsBridgeGateway.java (1)

127-144: LGTM!

src/main/java/com/Regalia/MainActivity.java (1)

375-378: LGTM!

Also applies to: 793-798

src/main/java/com/Regalia/PgnCacheManager.java (1)

152-158: LGTM!

Also applies to: 192-222

src/main/java/com/Regalia/SafPickerHelper.java (1)

336-378: LGTM!

src/main/java/com/Regalia/StabilizationHelper.java (1)

140-151: LGTM!

src/main/java/com/Regalia/StatsActivity.java (1)

596-604: LGTM!

src/main/java/com/Regalia/StockfishNative.java (1)

669-683: LGTM!

Also applies to: 1569-1569, 1833-1833, 1942-1957, 2635-2642, 3023-3023, 3088-3092, 3863-3871

Comment thread assets/README.license
Comment thread build.gradle
Comment on lines +184 to +192
// v1.2.3 round-13: pinned to 3.31.6+ to avoid the CMake 3.22.1
// re-run loop bug ("manifest 'build.ninja' still dirty after 100
// tries"). The root cause was actually source files extracted
// with future timestamps from the zip, which ninja interpreted
// as "always out of date". CMake 3.31.6's ninja provides a
// clearer error message ("perhaps system time is not set") that
// surfaced the real issue. Either way, pinning to 3.31.6+ is
// safer for fresh environments.
version "3.31.6+"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- build.gradle excerpt ---'
nl -ba build.gradle | sed -n '170,200p'

printf '\n%s\n' '--- README excerpt ---'
nl -ba README.md | sed -n '400,420p'

printf '\n%s\n' '--- search for cmake version selector usage ---'
rg -n 'version\s+"[^"]+\+"' -S build.gradle README.md . | sed -n '1,120p'

Repository: YDW99/Regalia

Length of output: 220


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- build.gradle excerpt ---'
awk 'NR>=170 && NR<=200 { printf "%5d  %s\n", NR, $0 }' build.gradle

printf '\n%s\n' '--- README excerpt ---'
awk 'NR>=400 && NR<=420 { printf "%5d  %s\n", NR, $0 }' README.md

printf '\n%s\n' '--- CMake version references ---'
rg -n 'version\s+"[^"]+"|cmake|externalNativeBuild|android\.cmake' build.gradle README.md . --glob '!**/.git/**' | sed -n '1,200p'

Repository: YDW99/Regalia

Length of output: 17633


🌐 Web query:

Android Gradle externalNativeBuild cmake version "3.31.6+" semantics exact pin plus selector

💡 Result:

In the Android Gradle Plugin (AGP), the externalNativeBuild configuration allows you to specify a CMake version using the version property [1][2]. The semantics of this setting are that of an exact pin [2]. When you provide a version string, such as version "3.31.6", the Android Gradle Plugin attempts to locate that specific version of CMake within the Android SDK's CMake installation directory [2]. It does not act as a selector for a range (e.g., "3.31.6 or higher") or perform semantic version matching; it expects an exact directory name match for the installed CMake component [3][2]. Key points regarding this behavior include: 1. Exact Pinning: If you set version "3.31.6", AGP looks for a folder named 3.31.6 inside the cmake directory of your Android SDK (e.g., ~/Android/Sdk/cmake/3.31.6) [3][2]. If that exact folder does not exist, the build will fail [3][2]. 2. Availability: By default, the Android SDK Manager provides specific versions of CMake [2]. If you require a version not provided by the SDK Manager, such as 3.31.6, you must either: - Manually install that CMake version and place it in the expected directory structure (inside the SDK's cmake folder) so that it matches the version string provided in your build.gradle [3]. - Define the cmake.dir property in your local.properties file to point to a custom installation [2]. When cmake.dir is set, Gradle uses that path instead of searching the default SDK locations [2]. 3. Native Behavior: This is distinct from CMake's internal cmake_minimum_required(VERSION 3.x) command, which is specified inside your CMakeLists.txt file and controls CMake's internal feature requirements, rather than the version of the CMake executable invoked by Gradle [4]. If you are attempting to use CMake 3.31.6, ensure that the version string matches exactly what is installed or provided via your build configuration [2].

Citations:


🌐 Web query:

site:developer.android.com externalNativeBuild cmake version exact match Android Gradle Plugin

💡 Result:

To specify a specific CMake version in the Android Gradle Plugin (AGP), you use the version property within the externalNativeBuild.cmake block in your module-level build.gradle file [1][2]. Example configuration: android {... externalNativeBuild { cmake { version "3.22.1" } } } When you configure this property, the plugin will look for the specified CMake version [1][3]. If the version is not found in the SDK manager, you must ensure the path to that specific CMake binary is included in your PATH environment variable [1][4]. Alternatively, you can specify the path to a custom CMake installation in your project's local.properties file using the cmake.dir property [1][3]. If you do not explicitly set the version property, the Android Gradle Plugin will default to using the version of CMake provided by the Android SDK Manager [1][2]. If that version is not installed, Android Studio will prompt you to download it [1][5].

Citations:


Make the CMake version an exact pin

  • build.gradle#L181-L192: externalNativeBuild.cmake.version is an exact selector, so 3.31.6+ is misleading here. Use 3.31.6 and install that exact CMake package, or change the setting/docs to describe a minimum/custom-install requirement instead of a pin.
  • README.md#L409-L413: update the release note to match the actual guarantee.
📍 Affects 2 files
  • build.gradle#L184-L192 (this comment)
  • README.md#L409-L413
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@build.gradle` around lines 184 - 192, The CMake configuration currently
claims a minimum version while externalNativeBuild.cmake.version requires an
exact selector. In build.gradle lines 184-192, change the version to the exact
3.31.6 pin and ensure the corresponding exact CMake package is installed; in
README.md lines 409-413, update the release note to describe the exact-version
guarantee rather than a 3.31.6-or-newer requirement.

Comment thread Manual/Regalia-v1.2.3-manual-zh.html Outdated
Comment thread NOTICE
Comment thread README.md Outdated
Comment thread src/main/assets/stats.html Outdated
Comment thread src/main/java/com/Regalia/StockfishNative.java Outdated
Comment thread src/main/res/README.license
Comment thread worklog.md
Comment thread worklog.md Outdated
@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown

Note

Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.

Cannot run autofix: This PR has merge conflicts.

Please resolve the conflicts with the base branch and try again.

Alternatively, use @coderabbitai resolve merge conflict to automatically resolve the conflicts.

Co-authored-by: D.W. Yang <292429627+YDW99@users.noreply.github.com>
@YDW99 YDW99 self-assigned this Jul 19, 2026
YDW99 and others added 2 commits July 19, 2026 14:37
Signed-off-by: D.W. Yang <1151712579@qq.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/assets/chess.src/state-store.js (1)

225-238: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Avoid a redundant full deep-clone per dispatch()/reset() call.

_notifyListeners() now deep-clones _state internally for the listener snapshot, but dispatch() (and reset()) immediately deep-clones _state again for its own return value — two full clones of the same state tree per call, even though _state hasn't changed between them. Given stateHistory can hold up to 200 entries plus moveRecords, this doubles a non-trivial cost on every game-state-changing action.

♻️ Proposed fix — compute one clone and reuse it
-    function _notifyListeners() {
-        const snapshot = _deepClone(_state);
+    function _notifyListeners(snapshot) {
+        if (snapshot === undefined) snapshot = _deepClone(_state);
         const listeners = _listeners.slice();
         for (let i = 0; i < listeners.length; i++) {
@@
     function dispatch(action, payload) {
         const reducer = _reducers[action];
         if (!reducer) {
             if (typeof console !== 'undefined' && console.warn) console.warn('[Store] No reducer for action:', action);
             return _deepClone(_state);
         }
         const partial = reducer(_state, payload);
+        let snapshot = null;
         if (partial && typeof partial === 'object') {
             _state = Object.assign({}, _state, partial);
-            _notifyListeners();
+            snapshot = _deepClone(_state);
+            _notifyListeners(snapshot);
         }
-        // v1.2.1: Return deep clone (P0-2)
-        return _deepClone(_state);
+        return snapshot || _deepClone(_state);
     }

Apply the same pattern to reset().

Also applies to: 267-284, 292-298

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/assets/chess.src/state-store.js` around lines 225 - 238, Eliminate
the duplicate state deep-clone in dispatch() and reset(): compute a single clone
after updating _state, pass that same snapshot through _notifyListeners(), and
return it from the operation. Update _notifyListeners() to accept and reuse the
provided snapshot while preserving listener behavior, and apply the same pattern
to the reset() implementation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/main/assets/chess.html`:
- Around line 3787-3841: Reduce the cognitive complexity of
winnerLacksMatingMaterial in chess.src/game-logic.js by extracting
board-scanning and/or material-classification logic into focused helper
functions, then keep winnerLacksMatingMaterial responsible for the
mating-material decisions. Preserve all existing piece-count, bishop-parity,
king-validation, and return behavior, and allow the build process to regenerate
chess.html rather than editing it directly.

In `@src/main/assets/chess.src/ai-bridge.js`:
- Around line 4609-4617: Update _evalOrMate so mate===0 is treated as “no active
mate” and returns fallbackEval, while only positive and negative mate values map
to the ±90000 sentinels. Preserve the existing handling for null/undefined and
the documented White-POV score behavior.
- Line 3591: Replace the bitwise coercion in the _settingsImportGen
generation-counter update with Math.trunc, preserving the existing increment
behavior without using |0.

In `@src/main/assets/chess.src/game-logic.js`:
- Around line 2463-2524: Reduce the cognitive complexity of
winnerLacksMatingMaterial by extracting the board scan and winner-piece
counting, including bishop-parity tracking, into a focused helper. Keep the
existing material-decision rules and outcomes unchanged, with
winnerLacksMatingMaterial consuming the helper’s tally and retaining the
king-count sanity check.

In `@src/main/assets/chess.src/ui-gameflow.js`:
- Around line 320-327: In the draw-detection logic, replace the separate
winnerLacksMatingMaterial and isDeadPosition branches with one conditional using
||, while preserving the typeof guard before calling each optional function and
retaining the single assignment to _isDrawByInsufficientMaterial.

In `@src/main/java/com/Regalia/HapticManager.java`:
- Around line 70-79: Update the cache expiration timing in HapticManager’s
system haptic settings refresh logic to use Android’s monotonic
SystemClock.elapsedRealtime() instead of System.currentTimeMillis(). Keep the
existing 5-second TTL comparison and cache update behavior unchanged.

In `@src/main/java/com/Regalia/MainActivity.java`:
- Around line 344-352: Update the engine-failure fallback flow around
showFallbackUI and the Activity’s BACK handling so fallback mode is explicitly
tracked or the WebView is detached/cleared. Ensure BACK does not dispatch to the
hidden webView while fallback UI is displayed, allowing the event to reach super
and close the Activity; preserve normal WebView navigation behavior outside
fallback mode.
- Around line 85-86: Serialize the stabilization lifecycle between
toggleStabilization() and onDestroy() by dispatching toggle operations to the
main thread or protecting both methods with the same synchronization and
destroyed-state check. Ensure no new StabilizationHelper is created or started
after destruction begins, and that onDestroy() cannot clear the helper while a
toggle is starting one.

In `@worklog.md`:
- Around line 37-69: Fix markdownlint issues in the new round-30 section of
worklog.md: add an explicit text language to every fenced log or verification
output block flagged by MD040, including the blocks around the listed entries.
Preserve the intentional running numbering in the ordered list and configure
markdownlint to allow it by disabling or appropriately configuring MD029 rather
than renumbering the entries.

---

Outside diff comments:
In `@src/main/assets/chess.src/state-store.js`:
- Around line 225-238: Eliminate the duplicate state deep-clone in dispatch()
and reset(): compute a single clone after updating _state, pass that same
snapshot through _notifyListeners(), and return it from the operation. Update
_notifyListeners() to accept and reuse the provided snapshot while preserving
listener behavior, and apply the same pattern to the reset() implementation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 37ac9d99-8f12-4a89-af4b-b637b9163a43

📥 Commits

Reviewing files that changed from the base of the PR and between acda070 and 74aa314.

⛔ Files ignored due to path filters (1)
  • LICENSE&NOTICE.zip is excluded by !**/*.zip
📒 Files selected for processing (32)
  • BUILDING.md
  • Manual/README.license
  • Manual/Regalia-v1.2.3-manual-en.html
  • Manual/Regalia-v1.2.3-manual-zh.html
  • NOTICE
  • PRIVACY.md
  • README.md
  • assets/README.license
  • src/main/README.license
  • src/main/assets/README.license
  • src/main/assets/chess.html
  • src/main/assets/chess.src/README.license
  • src/main/assets/chess.src/ai-bridge.js
  • src/main/assets/chess.src/game-logic.js
  • src/main/assets/chess.src/state-store.js
  • src/main/assets/chess.src/tablebase.js
  • src/main/assets/chess.src/ui-gameflow.js
  • src/main/assets/chess.src/ui-interactions.js
  • src/main/assets/chess.src/ui.js
  • src/main/assets/chess.src/worker-pool.js
  • src/main/assets/stats.html
  • src/main/cpp/README.license
  • src/main/java/com/Regalia/EngineConfigHelper.java
  • src/main/java/com/Regalia/FileIoHelper.java
  • src/main/java/com/Regalia/HapticManager.java
  • src/main/java/com/Regalia/MainActivity.java
  • src/main/java/com/Regalia/PgnCacheManager.java
  • src/main/java/com/Regalia/README.license
  • src/main/java/com/Regalia/StatsActivity.java
  • src/main/java/com/Regalia/StockfishNative.java
  • src/main/res/README.license
  • worklog.md
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: semgrep-cloud-platform/scan
🧰 Additional context used
🪛 ast-grep (0.44.1)
src/main/assets/chess.html

[warning] 7815-7822: Avoid using the initial state variable in setState
Context: setTimeout(()=>{
t.style.opacity='0';
_toastRemoveTimer=setTimeout(()=>{
t.remove();
_toastRemoveTimer=0;
},300);
_toastTimer=0;
},duration)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(setstate-same-var)


[error] 7815-7822: React's useState should not be directly called
Context: setTimeout(()=>{
t.style.opacity='0';
_toastRemoveTimer=setTimeout(()=>{
t.remove();
_toastRemoveTimer=0;
},300);
_toastTimer=0;
},duration)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[error] 10828-10834: React's useState should not be directly called
Context: setTimeout(function(){
if(myGen!==_settingsImportGen)return;
showEngineConfig=false;
var dov2=document.querySelector('.dov[role="dialog"]');
if(dov2){dov2.remove();}
render();
},100)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[warning] 14691-14691: Avoid using the initial state variable in setState
Context: setInterval(_tickGameClock,200)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(setstate-same-var)


[error] 14691-14691: React's useState should not be directly called
Context: setInterval(_tickGameClock,200)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[warning] 15812-15812: Avoid using the initial state variable in setState
Context: setTimeout(_waitForDialog,200)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(setstate-same-var)


[error] 15812-15812: React's useState should not be directly called
Context: setTimeout(_waitForDialog,200)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)

src/main/assets/chess.src/ui-interactions.js

[warning] 1232-1232: Avoid using the initial state variable in setState
Context: setTimeout(_waitForDialog,200)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(setstate-same-var)


[error] 1232-1232: React's useState should not be directly called
Context: setTimeout(_waitForDialog,200)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)

src/main/assets/chess.src/ai-bridge.js

[warning] 579-586: Avoid using the initial state variable in setState
Context: setTimeout(()=>{
t.style.opacity='0';
_toastRemoveTimer=setTimeout(()=>{
t.remove();
_toastRemoveTimer=0;
},300);
_toastTimer=0;
},duration)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(setstate-same-var)


[error] 579-586: React's useState should not be directly called
Context: setTimeout(()=>{
t.style.opacity='0';
_toastRemoveTimer=setTimeout(()=>{
t.remove();
_toastRemoveTimer=0;
},300);
_toastTimer=0;
},duration)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[error] 3592-3598: React's useState should not be directly called
Context: setTimeout(function(){
if(myGen!==_settingsImportGen)return;
showEngineConfig=false;
var dov2=document.querySelector('.dov[role="dialog"]');
if(dov2){dov2.remove();}
render();
},100)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)

🪛 GitHub Check: SonarCloud Code Analysis
src/main/java/com/Regalia/HapticManager.java

[warning] 96-96: Rename this field "_systemHapticCached" to match the regular expression '^[a-z][a-zA-Z0-9]*$'.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ95GWsOq4IVm24_K2cn&open=AZ95GWsOq4IVm24_K2cn&pullRequest=52


[warning] 97-97: Rename this field "_systemHapticCacheTs" to match the regular expression '^[a-z][a-zA-Z0-9]*$'.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ95GWsOq4IVm24_K2co&open=AZ95GWsOq4IVm24_K2co&pullRequest=52

src/main/java/com/Regalia/StatsActivity.java

[warning] 96-96: Rename this field "_statsHapticManager" to match the regular expression '^[a-z][a-zA-Z0-9]*$'.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ95GW1Uq4IVm24_K2ct&open=AZ95GW1Uq4IVm24_K2ct&pullRequest=52

src/main/assets/chess.src/ui-gameflow.js

[warning] 323-327: This branch's code block is the same as the block for the branch on line 321.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ95GXBUq4IVm24_K2c0&open=AZ95GXBUq4IVm24_K2c0&pullRequest=52

src/main/assets/chess.html

[failure] 3787-3787: Refactor this function to reduce its Cognitive Complexity from 29 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ95GXI0q4IVm24_K2c2&open=AZ95GXI0q4IVm24_K2c2&pullRequest=52


[failure] 10827-10827: Use Math.trunc instead of | 0.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ95GXI0q4IVm24_K2c3&open=AZ95GXI0q4IVm24_K2c3&pullRequest=52


[warning] 14492-14496: This branch's code block is the same as the block for the branch on line 14490.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ95GXI0q4IVm24_K2c4&open=AZ95GXI0q4IVm24_K2c4&pullRequest=52

src/main/java/com/Regalia/StockfishNative.java

[warning] 171-171: Rename this field "_hapticManager" to match the regular expression '^[a-z][a-zA-Z0-9]*$'.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ95GW2zq4IVm24_K2cu&open=AZ95GW2zq4IVm24_K2cu&pullRequest=52

src/main/assets/chess.src/ui-interactions.js

[warning] 394-394: Prefer using an optional chain expression instead, as it's more concise and easier to read.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ95GXAaq4IVm24_K2cz&open=AZ95GXAaq4IVm24_K2cz&pullRequest=52

src/main/assets/chess.src/game-logic.js

[failure] 2470-2470: Refactor this function to reduce its Cognitive Complexity from 29 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ95GW78q4IVm24_K2cw&open=AZ95GW78q4IVm24_K2cw&pullRequest=52

src/main/assets/chess.src/ui.js

[failure] 3611-3611: Add the "let", "const" or "var" keyword to this declaration of "_cachedBwrap" to make it explicit.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ95GW-fq4IVm24_K2cy&open=AZ95GW-fq4IVm24_K2cy&pullRequest=52

src/main/assets/chess.src/ai-bridge.js

[failure] 3591-3591: Use Math.trunc instead of | 0.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ95GW50q4IVm24_K2cv&open=AZ95GW50q4IVm24_K2cv&pullRequest=52

🪛 markdownlint-cli2 (0.23.0)
worklog.md

[warning] 37-37: Ordered list item prefix
Expected: 1; Actual: 7; Style: 1/2/3

(MD029, ol-prefix)


[warning] 39-39: Ordered list item prefix
Expected: 2; Actual: 8; Style: 1/2/3

(MD029, ol-prefix)


[warning] 41-41: Ordered list item prefix
Expected: 3; Actual: 9; Style: 1/2/3

(MD029, ol-prefix)


[warning] 43-43: Ordered list item prefix
Expected: 4; Actual: 10; Style: 1/2/3

(MD029, ol-prefix)


[warning] 45-45: Ordered list item prefix
Expected: 5; Actual: 11; Style: 1/2/3

(MD029, ol-prefix)


[warning] 47-47: Ordered list item prefix
Expected: 6; Actual: 12; Style: 1/2/3

(MD029, ol-prefix)


[warning] 49-49: Ordered list item prefix
Expected: 7; Actual: 13; Style: 1/2/3

(MD029, ol-prefix)


[warning] 53-53: Ordered list item prefix
Expected: 1; Actual: 14; Style: 1/2/3

(MD029, ol-prefix)


[warning] 55-55: Ordered list item prefix
Expected: 2; Actual: 15; Style: 1/2/3

(MD029, ol-prefix)


[warning] 57-57: Ordered list item prefix
Expected: 3; Actual: 16; Style: 1/2/3

(MD029, ol-prefix)


[warning] 59-59: Ordered list item prefix
Expected: 4; Actual: 17; Style: 1/2/3

(MD029, ol-prefix)


[warning] 61-61: Ordered list item prefix
Expected: 5; Actual: 18; Style: 1/2/3

(MD029, ol-prefix)


[warning] 65-65: Ordered list item prefix
Expected: 1; Actual: 19; Style: 1/2/3

(MD029, ol-prefix)


[warning] 67-67: Ordered list item prefix
Expected: 2; Actual: 20; Style: 1/2/3

(MD029, ol-prefix)


[warning] 69-69: Ordered list item prefix
Expected: 3; Actual: 21; Style: 1/2/3

(MD029, ol-prefix)


[warning] 81-81: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 104-104: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 111-111: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 118-118: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 128-128: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 137-137: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 288-288: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 308-308: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 315-315: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 322-322: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 332-332: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 347-347: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🔇 Additional comments (38)
src/main/java/com/Regalia/HapticManager.java (1)

47-58: LGTM!

Also applies to: 99-427, 429-493

src/main/java/com/Regalia/EngineConfigHelper.java (1)

216-240: LGTM!

Also applies to: 561-565

src/main/java/com/Regalia/FileIoHelper.java (1)

287-294: LGTM!

Also applies to: 371-387

src/main/java/com/Regalia/PgnCacheManager.java (1)

42-42: LGTM!

Also applies to: 64-70, 94-96, 160-166, 200-230

src/main/java/com/Regalia/MainActivity.java (1)

55-55: LGTM!

Also applies to: 390-393

src/main/java/com/Regalia/StatsActivity.java (1)

93-96: LGTM!

Also applies to: 226-244, 318-325, 599-607

src/main/java/com/Regalia/StockfishNative.java (1)

166-171: LGTM!

Also applies to: 464-472, 673-688, 757-786, 817-817, 1576-1580, 1800-1800, 1836-1844, 1953-1968, 2646-2653, 2801-2809, 2874-2874, 2967-2971, 3025-3034, 3099-3103, 3727-3731, 3874-3891

src/main/assets/chess.src/ui-gameflow.js (1)

304-329: Resolved: the winner-side mating-material check (via winnerLacksMatingMaterial) now correctly supersedes the symmetric isDeadPosition() check for FIDE 6.9 timeout draws, addressing the earlier review feedback on this function.

src/main/assets/chess.src/ai-bridge.js (2)

3573-3574: Resolved: info/s now use const instead of var, addressing the earlier SonarCloud/var review feedback.


260-279: LGTM! The remaining changes (eviction guard, generation token, HapticManager API surface trim, toast-timer tracking, capped polling loops, _buildPGNString NAG/annotation plumbing aside from _evalOrMate, UCI optional-chaining collapses, and the _requestBatchEval spin-timer removal) are sound, defensive, and consistent with their stated intent.

Also applies to: 417-420, 429-515, 535-588, 689-829, 1065-1411, 1934-2003, 2177-2390, 3551-3609, 4454-4532

src/main/assets/chess.src/ui-interactions.js (2)

78-116: Resolved: clock restoration now restarts only the tick interval and no longer calls initGameClocks(), fixing the previously-flagged Undo/Redo clock-reset bug.


240-415: LGTM!

Also applies to: 1208-1247

src/main/assets/stats.html (3)

698-698: Resolved: these four sites now use the canonical escaped-quote-aware PGN tag regex, addressing the previously-flagged backtracking-prone pattern.

Also applies to: 713-713, 1518-1518, 1558-1558


3918-3933: LGTM! String.raw correctly preserves the literal \u003c escape-sequence text (rather than a decoded <), so the exported payload can't prematurely close a <script> tag.


41-43: LGTM!

Also applies to: 801-801, 852-852, 897-897, 956-964, 1535-1558, 1602-1604, 1633-1641, 1703-1703, 1758-1758, 2678-2701, 2767-2767, 4228-4228

src/main/assets/chess.src/tablebase.js (3)

205-205: LGTM!

Also applies to: 363-379, 455-459, 547-554, 832-855, 894-906, 960-960, 982-982, 1191-1191, 1227-1238, 1436-1438, 1546-1554, 1581-1581, 1742-1742, 1827-1827, 1866-1866, 1875-1876, 1983-1987


1051-1090: LGTM! The unconditional reset of gameSPID=null before derivation correctly prevents stale SP-ID leakage from a prior game into a Chess960 import that lacks a [FEN] tag or whose back-rank derivation fails.


1913-1920: LGTM! Collapsing has()+get() into a single get() with an undefined check is a valid micro-optimization since tablebase responses are always non-undefined objects.

src/main/assets/chess.src/game-logic.js (1)

1923-1928: LGTM!

src/main/assets/chess.src/ui.js (3)

2016-2060: LGTM! The review-mode extraction into pure helpers, render-throttle simplification, scroll/state hardening with optional chaining, and analyze-all helper extraction are consistent, behavior-preserving refactors.

Also applies to: 2581-2941, 3477-3650, 3706-4067, 4100-4204, 5272-5311, 5419-5632, 5681-5772, 5918-6528


5819-5902: LGTM!


3611-3611: 🩺 Stability & Availability

No change needed here _cachedBwrap is already declared in src/main/assets/chess.src/game-logic.js, so this line just clears the shared cache; adding let here would introduce a new binding instead of resetting it.

			> Likely an incorrect or invalid review comment.
src/main/assets/chess.src/worker-pool.js (1)

256-340: LGTM!

Also applies to: 421-428, 564-566

BUILDING.md (1)

24-780: LGTM!

Manual/README.license (1)

1-159: LGTM!

Manual/Regalia-v1.2.3-manual-en.html (1)

543-546: LGTM!

Also applies to: 1837-1837, 1880-1909

NOTICE (1)

23-551: LGTM!

Manual/Regalia-v1.2.3-manual-zh.html (1)

543-557: LGTM!

Also applies to: 1860-1958

src/main/java/com/Regalia/README.license (1)

1-263: LGTM!

Also applies to: 397-397, 422-422, 483-483, 607-607, 1175-1175, 1199-1199, 1354-1354, 1511-1544

src/main/assets/chess.html (1)

7057-7824: LGTM!

Also applies to: 8040-8065, 10802-10836, 11758-11853, 12503-12510, 13869-13876, 14483-14498, 14655-14692, 15804-15818, 17882-17885, 18749-18754, 20314-20323

assets/README.license (1)

1-12: 📐 Maintainability & Code Quality

Round-23 through round-28 gap still unfilled.

The new round-30 and round-29 entries were added, but rounds 23-28 are still missing between round-29 and round-22 (line 12), same gap flagged previously.

PRIVACY.md (1)

57-64: LGTM!

Also applies to: 256-256, 287-322

README.md (1)

105-107: LGTM!

Also applies to: 131-131, 158-161, 176-187, 210-210, 263-502

src/main/README.license (1)

1-18: LGTM!

Also applies to: 337-346, 565-565

src/main/assets/README.license (1)

1-168: LGTM!

Also applies to: 185-185, 202-202, 218-218, 293-293, 303-303, 315-315, 327-327, 944-952

src/main/assets/chess.src/README.license (1)

20-23: 📐 Maintainability & Code Quality | ⚡ Quick win

state-store.js license classification contradicts every other entry in this file.

This round-30 summary line groups state-store.js with the GPL v3 files, but every other entry in this file (round-9, round-11, round-7, Phase 73-80, etc.) classifies state-store.js as AGPL v3 (original work, not DroidFish-derived). Round-29 (immediately preceding, lines 49-51) does not mention reclassifying it either. This appears to be a copy-paste error.

📝 Proposed fix
-  - License classification: all files unchanged (game-logic.js, pgn-standard.js,
-    state-store.js, ai-bridge.js, tablebase.js, worker-pool.js, ui-gameflow.js,
-    ui-interactions.js, ui.js, index.html.tpl = GPL v3; chess960.js, eco-data.js
-    = AGPL v3).
+  - License classification: all files unchanged (game-logic.js, pgn-standard.js,
+    ai-bridge.js, tablebase.js, worker-pool.js, ui-gameflow.js,
+    ui-interactions.js, ui.js, index.html.tpl = GPL v3; chess960.js, eco-data.js,
+    state-store.js = AGPL v3).
src/main/cpp/README.license (1)

1-95: LGTM!

src/main/res/README.license (1)

1-13: LGTM!

Also applies to: 248-253

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/assets/chess.src/state-store.js (1)

225-238: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Avoid a redundant full deep-clone per dispatch()/reset() call.

_notifyListeners() now deep-clones _state internally for the listener snapshot, but dispatch() (and reset()) immediately deep-clones _state again for its own return value — two full clones of the same state tree per call, even though _state hasn't changed between them. Given stateHistory can hold up to 200 entries plus moveRecords, this doubles a non-trivial cost on every game-state-changing action.

♻️ Proposed fix — compute one clone and reuse it
-    function _notifyListeners() {
-        const snapshot = _deepClone(_state);
+    function _notifyListeners(snapshot) {
+        if (snapshot === undefined) snapshot = _deepClone(_state);
         const listeners = _listeners.slice();
         for (let i = 0; i < listeners.length; i++) {
@@
     function dispatch(action, payload) {
         const reducer = _reducers[action];
         if (!reducer) {
             if (typeof console !== 'undefined' && console.warn) console.warn('[Store] No reducer for action:', action);
             return _deepClone(_state);
         }
         const partial = reducer(_state, payload);
+        let snapshot = null;
         if (partial && typeof partial === 'object') {
             _state = Object.assign({}, _state, partial);
-            _notifyListeners();
+            snapshot = _deepClone(_state);
+            _notifyListeners(snapshot);
         }
-        // v1.2.1: Return deep clone (P0-2)
-        return _deepClone(_state);
+        return snapshot || _deepClone(_state);
     }

Apply the same pattern to reset().

Also applies to: 267-284, 292-298

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/assets/chess.src/state-store.js` around lines 225 - 238, Eliminate
the duplicate state deep-clone in dispatch() and reset(): compute a single clone
after updating _state, pass that same snapshot through _notifyListeners(), and
return it from the operation. Update _notifyListeners() to accept and reuse the
provided snapshot while preserving listener behavior, and apply the same pattern
to the reset() implementation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/main/assets/chess.html`:
- Around line 3787-3841: Reduce the cognitive complexity of
winnerLacksMatingMaterial in chess.src/game-logic.js by extracting
board-scanning and/or material-classification logic into focused helper
functions, then keep winnerLacksMatingMaterial responsible for the
mating-material decisions. Preserve all existing piece-count, bishop-parity,
king-validation, and return behavior, and allow the build process to regenerate
chess.html rather than editing it directly.

In `@src/main/assets/chess.src/ai-bridge.js`:
- Around line 4609-4617: Update _evalOrMate so mate===0 is treated as “no active
mate” and returns fallbackEval, while only positive and negative mate values map
to the ±90000 sentinels. Preserve the existing handling for null/undefined and
the documented White-POV score behavior.
- Line 3591: Replace the bitwise coercion in the _settingsImportGen
generation-counter update with Math.trunc, preserving the existing increment
behavior without using |0.

In `@src/main/assets/chess.src/game-logic.js`:
- Around line 2463-2524: Reduce the cognitive complexity of
winnerLacksMatingMaterial by extracting the board scan and winner-piece
counting, including bishop-parity tracking, into a focused helper. Keep the
existing material-decision rules and outcomes unchanged, with
winnerLacksMatingMaterial consuming the helper’s tally and retaining the
king-count sanity check.

In `@src/main/assets/chess.src/ui-gameflow.js`:
- Around line 320-327: In the draw-detection logic, replace the separate
winnerLacksMatingMaterial and isDeadPosition branches with one conditional using
||, while preserving the typeof guard before calling each optional function and
retaining the single assignment to _isDrawByInsufficientMaterial.

In `@src/main/java/com/Regalia/HapticManager.java`:
- Around line 70-79: Update the cache expiration timing in HapticManager’s
system haptic settings refresh logic to use Android’s monotonic
SystemClock.elapsedRealtime() instead of System.currentTimeMillis(). Keep the
existing 5-second TTL comparison and cache update behavior unchanged.

In `@src/main/java/com/Regalia/MainActivity.java`:
- Around line 344-352: Update the engine-failure fallback flow around
showFallbackUI and the Activity’s BACK handling so fallback mode is explicitly
tracked or the WebView is detached/cleared. Ensure BACK does not dispatch to the
hidden webView while fallback UI is displayed, allowing the event to reach super
and close the Activity; preserve normal WebView navigation behavior outside
fallback mode.
- Around line 85-86: Serialize the stabilization lifecycle between
toggleStabilization() and onDestroy() by dispatching toggle operations to the
main thread or protecting both methods with the same synchronization and
destroyed-state check. Ensure no new StabilizationHelper is created or started
after destruction begins, and that onDestroy() cannot clear the helper while a
toggle is starting one.

In `@worklog.md`:
- Around line 37-69: Fix markdownlint issues in the new round-30 section of
worklog.md: add an explicit text language to every fenced log or verification
output block flagged by MD040, including the blocks around the listed entries.
Preserve the intentional running numbering in the ordered list and configure
markdownlint to allow it by disabling or appropriately configuring MD029 rather
than renumbering the entries.

---

Outside diff comments:
In `@src/main/assets/chess.src/state-store.js`:
- Around line 225-238: Eliminate the duplicate state deep-clone in dispatch()
and reset(): compute a single clone after updating _state, pass that same
snapshot through _notifyListeners(), and return it from the operation. Update
_notifyListeners() to accept and reuse the provided snapshot while preserving
listener behavior, and apply the same pattern to the reset() implementation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 37ac9d99-8f12-4a89-af4b-b637b9163a43

📥 Commits

Reviewing files that changed from the base of the PR and between acda070 and 74aa314.

⛔ Files ignored due to path filters (1)
  • LICENSE&NOTICE.zip is excluded by !**/*.zip
📒 Files selected for processing (32)
  • BUILDING.md
  • Manual/README.license
  • Manual/Regalia-v1.2.3-manual-en.html
  • Manual/Regalia-v1.2.3-manual-zh.html
  • NOTICE
  • PRIVACY.md
  • README.md
  • assets/README.license
  • src/main/README.license
  • src/main/assets/README.license
  • src/main/assets/chess.html
  • src/main/assets/chess.src/README.license
  • src/main/assets/chess.src/ai-bridge.js
  • src/main/assets/chess.src/game-logic.js
  • src/main/assets/chess.src/state-store.js
  • src/main/assets/chess.src/tablebase.js
  • src/main/assets/chess.src/ui-gameflow.js
  • src/main/assets/chess.src/ui-interactions.js
  • src/main/assets/chess.src/ui.js
  • src/main/assets/chess.src/worker-pool.js
  • src/main/assets/stats.html
  • src/main/cpp/README.license
  • src/main/java/com/Regalia/EngineConfigHelper.java
  • src/main/java/com/Regalia/FileIoHelper.java
  • src/main/java/com/Regalia/HapticManager.java
  • src/main/java/com/Regalia/MainActivity.java
  • src/main/java/com/Regalia/PgnCacheManager.java
  • src/main/java/com/Regalia/README.license
  • src/main/java/com/Regalia/StatsActivity.java
  • src/main/java/com/Regalia/StockfishNative.java
  • src/main/res/README.license
  • worklog.md
📜 Review details
🔇 Additional comments (38)
src/main/java/com/Regalia/HapticManager.java (1)

47-58: LGTM!

Also applies to: 99-427, 429-493

src/main/java/com/Regalia/EngineConfigHelper.java (1)

216-240: LGTM!

Also applies to: 561-565

src/main/java/com/Regalia/FileIoHelper.java (1)

287-294: LGTM!

Also applies to: 371-387

src/main/java/com/Regalia/PgnCacheManager.java (1)

42-42: LGTM!

Also applies to: 64-70, 94-96, 160-166, 200-230

src/main/java/com/Regalia/MainActivity.java (1)

55-55: LGTM!

Also applies to: 390-393

src/main/java/com/Regalia/StatsActivity.java (1)

93-96: LGTM!

Also applies to: 226-244, 318-325, 599-607

src/main/java/com/Regalia/StockfishNative.java (1)

166-171: LGTM!

Also applies to: 464-472, 673-688, 757-786, 817-817, 1576-1580, 1800-1800, 1836-1844, 1953-1968, 2646-2653, 2801-2809, 2874-2874, 2967-2971, 3025-3034, 3099-3103, 3727-3731, 3874-3891

src/main/assets/chess.src/ui-gameflow.js (1)

304-329: Resolved: the winner-side mating-material check (via winnerLacksMatingMaterial) now correctly supersedes the symmetric isDeadPosition() check for FIDE 6.9 timeout draws, addressing the earlier review feedback on this function.

src/main/assets/chess.src/ai-bridge.js (2)

3573-3574: Resolved: info/s now use const instead of var, addressing the earlier SonarCloud/var review feedback.


260-279: LGTM! The remaining changes (eviction guard, generation token, HapticManager API surface trim, toast-timer tracking, capped polling loops, _buildPGNString NAG/annotation plumbing aside from _evalOrMate, UCI optional-chaining collapses, and the _requestBatchEval spin-timer removal) are sound, defensive, and consistent with their stated intent.

Also applies to: 417-420, 429-515, 535-588, 689-829, 1065-1411, 1934-2003, 2177-2390, 3551-3609, 4454-4532

src/main/assets/chess.src/ui-interactions.js (2)

78-116: Resolved: clock restoration now restarts only the tick interval and no longer calls initGameClocks(), fixing the previously-flagged Undo/Redo clock-reset bug.


240-415: LGTM!

Also applies to: 1208-1247

src/main/assets/stats.html (3)

698-698: Resolved: these four sites now use the canonical escaped-quote-aware PGN tag regex, addressing the previously-flagged backtracking-prone pattern.

Also applies to: 713-713, 1518-1518, 1558-1558


3918-3933: LGTM! String.raw correctly preserves the literal \u003c escape-sequence text (rather than a decoded <), so the exported payload can't prematurely close a <script> tag.


41-43: LGTM!

Also applies to: 801-801, 852-852, 897-897, 956-964, 1535-1558, 1602-1604, 1633-1641, 1703-1703, 1758-1758, 2678-2701, 2767-2767, 4228-4228

src/main/assets/chess.src/tablebase.js (3)

205-205: LGTM!

Also applies to: 363-379, 455-459, 547-554, 832-855, 894-906, 960-960, 982-982, 1191-1191, 1227-1238, 1436-1438, 1546-1554, 1581-1581, 1742-1742, 1827-1827, 1866-1866, 1875-1876, 1983-1987


1051-1090: LGTM! The unconditional reset of gameSPID=null before derivation correctly prevents stale SP-ID leakage from a prior game into a Chess960 import that lacks a [FEN] tag or whose back-rank derivation fails.


1913-1920: LGTM! Collapsing has()+get() into a single get() with an undefined check is a valid micro-optimization since tablebase responses are always non-undefined objects.

src/main/assets/chess.src/game-logic.js (1)

1923-1928: LGTM!

src/main/assets/chess.src/ui.js (3)

2016-2060: LGTM! The review-mode extraction into pure helpers, render-throttle simplification, scroll/state hardening with optional chaining, and analyze-all helper extraction are consistent, behavior-preserving refactors.

Also applies to: 2581-2941, 3477-3650, 3706-4067, 4100-4204, 5272-5311, 5419-5632, 5681-5772, 5918-6528


5819-5902: LGTM!


3611-3611: 🩺 Stability & Availability

No change needed here _cachedBwrap is already declared in src/main/assets/chess.src/game-logic.js, so this line just clears the shared cache; adding let here would introduce a new binding instead of resetting it.

			> Likely an incorrect or invalid review comment.
src/main/assets/chess.src/worker-pool.js (1)

256-340: LGTM!

Also applies to: 421-428, 564-566

BUILDING.md (1)

24-780: LGTM!

Manual/README.license (1)

1-159: LGTM!

Manual/Regalia-v1.2.3-manual-en.html (1)

543-546: LGTM!

Also applies to: 1837-1837, 1880-1909

NOTICE (1)

23-551: LGTM!

Manual/Regalia-v1.2.3-manual-zh.html (1)

543-557: LGTM!

Also applies to: 1860-1958

src/main/java/com/Regalia/README.license (1)

1-263: LGTM!

Also applies to: 397-397, 422-422, 483-483, 607-607, 1175-1175, 1199-1199, 1354-1354, 1511-1544

src/main/assets/chess.html (1)

7057-7824: LGTM!

Also applies to: 8040-8065, 10802-10836, 11758-11853, 12503-12510, 13869-13876, 14483-14498, 14655-14692, 15804-15818, 17882-17885, 18749-18754, 20314-20323

assets/README.license (1)

1-12: 📐 Maintainability & Code Quality

Round-23 through round-28 gap still unfilled.

The new round-30 and round-29 entries were added, but rounds 23-28 are still missing between round-29 and round-22 (line 12), same gap flagged previously.

PRIVACY.md (1)

57-64: LGTM!

Also applies to: 256-256, 287-322

README.md (1)

105-107: LGTM!

Also applies to: 131-131, 158-161, 176-187, 210-210, 263-502

src/main/README.license (1)

1-18: LGTM!

Also applies to: 337-346, 565-565

src/main/assets/README.license (1)

1-168: LGTM!

Also applies to: 185-185, 202-202, 218-218, 293-293, 303-303, 315-315, 327-327, 944-952

src/main/assets/chess.src/README.license (1)

20-23: 📐 Maintainability & Code Quality | ⚡ Quick win

state-store.js license classification contradicts every other entry in this file.

This round-30 summary line groups state-store.js with the GPL v3 files, but every other entry in this file (round-9, round-11, round-7, Phase 73-80, etc.) classifies state-store.js as AGPL v3 (original work, not DroidFish-derived). Round-29 (immediately preceding, lines 49-51) does not mention reclassifying it either. This appears to be a copy-paste error.

📝 Proposed fix
-  - License classification: all files unchanged (game-logic.js, pgn-standard.js,
-    state-store.js, ai-bridge.js, tablebase.js, worker-pool.js, ui-gameflow.js,
-    ui-interactions.js, ui.js, index.html.tpl = GPL v3; chess960.js, eco-data.js
-    = AGPL v3).
+  - License classification: all files unchanged (game-logic.js, pgn-standard.js,
+    ai-bridge.js, tablebase.js, worker-pool.js, ui-gameflow.js,
+    ui-interactions.js, ui.js, index.html.tpl = GPL v3; chess960.js, eco-data.js,
+    state-store.js = AGPL v3).
src/main/cpp/README.license (1)

1-95: LGTM!

src/main/res/README.license (1)

1-13: LGTM!

Also applies to: 248-253

🛑 Comments failed to post (9)
src/main/assets/chess.html (1)

3787-3841: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Reduce winnerLacksMatingMaterial's cognitive complexity (SonarCloud failure: 29 > 15).

The nested loop + 7-case switch + sequential decision ifs push this over SonarCloud's cognitive-complexity threshold. Since chess.html is rebuilt from chess.src/game-logic.js via build-chess.py, the fix needs to land in the source module (not edited here directly).

♻️ Suggested extraction
-function winnerLacksMatingMaterial(s,winnerColor){
-  if(!s||!s.board)return false;
-  let wPawn=0,wKnight=0,wBishop=0,wRook=0,wQueen=0,wKing=0;
-  let wBishopParity=-1;
-  for(let r=0;r<8;r++){
-    const row=s.board[r];if(!row)continue;
-    for(let c=0;c<8;c++){
-      const p=row[c];
-      if(!p)continue;
-      if(p.color!==winnerColor)continue;
-      switch(p.type){
-        case'pawn':wPawn++;break;
-        case'knight':wKnight++;break;
-        case'rook':wRook++;break;
-        case'queen':wQueen++;break;
-        case'king':wKing++;break;
-        case'bishop':{
-          wBishop++;
-          const parity=(r+c)%2;
-          if(wBishopParity===-1)wBishopParity=parity;
-          else if(wBishopParity!==parity)wBishopParity=-2;
-          break;
-        }
-      }
-    }
-  }
-  if(wKing!==1)return false;
+function _countWinnerMaterial(s,winnerColor){
+  const counts={pawn:0,knight:0,bishop:0,rook:0,queen:0,king:0,bishopParity:-1};
+  for(let r=0;r<8;r++){
+    const row=s.board[r];if(!row)continue;
+    for(let c=0;c<8;c++){
+      const p=row[c];
+      if(!p||p.color!==winnerColor)continue;
+      if(p.type==='bishop'){
+        counts.bishop++;
+        const parity=(r+c)%2;
+        counts.bishopParity=counts.bishopParity===-1?parity:(counts.bishopParity!==parity?-2:counts.bishopParity);
+      }else{
+        counts[p.type]=(counts[p.type]||0)+1;
+      }
+    }
+  }
+  return counts;
+}
+function winnerLacksMatingMaterial(s,winnerColor){
+  if(!s||!s.board)return false;
+  const {pawn:wPawn,knight:wKnight,bishop:wBishop,rook:wRook,queen:wQueen,king:wKing,bishopParity:wBishopParity}=_countWinnerMaterial(s,winnerColor);
+  if(wKing!==1)return false;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

function _countWinnerMaterial(s,winnerColor){
  const counts={pawn:0,knight:0,bishop:0,rook:0,queen:0,king:0,bishopParity:-1};
  for(let r=0;r<8;r++){
    const row=s.board[r];if(!row)continue;
    for(let c=0;c<8;c++){
      const p=row[c];
      if(!p||p.color!==winnerColor)continue;
      if(p.type==='bishop'){
        counts.bishop++;
        const parity=(r+c)%2;
        counts.bishopParity=counts.bishopParity===-1?parity:(counts.bishopParity!==parity?-2:counts.bishopParity);
      }else{
        counts[p.type]=(counts[p.type]||0)+1;
      }
    }
  }
  return counts;
}
function winnerLacksMatingMaterial(s,winnerColor){
  if(!s||!s.board)return false;
  const {pawn:wPawn,knight:wKnight,bishop:wBishop,rook:wRook,queen:wQueen,king:wKing,bishopParity:wBishopParity}=_countWinnerMaterial(s,winnerColor);
  // Sanity: winner must have exactly one king (otherwise state is corrupt).
  if(wKing!==1)return false;
  // Any pawn / rook / queen → mating is possible.
  if(wPawn>0||wRook>0||wQueen>0)return false;
  // K vs K (winner has only king) → cannot mate.
  if(wKnight===0&&wBishop===0)return true;
  // K + single minor (N or B) → cannot mate.
  if(wKnight+wBishop===1)return true;
  // K + 2N → cannot force mate (FIDE rules; help-mate possible but not forced).
  if(wKnight===2&&wBishop===0)return true;
  // K + B+B same color (no knight) → cannot force mate (enemy king escapes
  // to the opposite-color squares). wBishopParity>=0 ensures ALL bishops
  // are the same color; the no-knight guard excludes K+N+B+B(same color)
  // which CAN mate (knight attacks both square colors).
  // v1.2.3 round-30: added this case (was missing — the FIDE 6.9 timeout
  //   draw was incorrectly judged a win for K+B+B same-color winners).
  if(wBishop>=2&&wKnight===0&&wBishopParity>=0)return true;
  // K + B+B same color + knight → CAN mate.
  // K + B+B opposite color → CAN mate (covers both square colors).
  // K + N+B → CAN mate.
  // K + 2N+anything else → CAN mate (the anything-else enables mate).
  return false;
}
🧰 Tools
🪛 GitHub Check: SonarCloud Code Analysis

[failure] 3787-3787: Refactor this function to reduce its Cognitive Complexity from 29 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ95GXI0q4IVm24_K2c2&open=AZ95GXI0q4IVm24_K2c2&pullRequest=52

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/assets/chess.html` around lines 3787 - 3841, Reduce the cognitive
complexity of winnerLacksMatingMaterial in chess.src/game-logic.js by extracting
board-scanning and/or material-classification logic into focused helper
functions, then keep winnerLacksMatingMaterial responsible for the
mating-material decisions. Preserve all existing piece-count, bishop-parity,
king-validation, and return behavior, and allow the build process to regenerate
chess.html rather than editing it directly.

Source: Linters/SAST tools

src/main/assets/chess.src/ai-bridge.js (2)

3591-3591: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use Math.trunc instead of |0 for the generation counter (SonarCloud gate).

Proposed fix
-      _settingsImportGen=(_settingsImportGen|0)+1;
+      _settingsImportGen=Math.trunc(_settingsImportGen)+1;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

      _settingsImportGen=Math.trunc(_settingsImportGen)+1;
🧰 Tools
🪛 GitHub Check: SonarCloud Code Analysis

[failure] 3591-3591: Use Math.trunc instead of | 0.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ95GW50q4IVm24_K2cv&open=AZ95GW50q4IVm24_K2cv&pullRequest=52

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/assets/chess.src/ai-bridge.js` at line 3591, Replace the bitwise
coercion in the _settingsImportGen generation-counter update with Math.trunc,
preserving the existing increment behavior without using |0.

Source: Linters/SAST tools


4609-4617: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

_evalOrMate mishandles mate===0, breaking eval-delta / NAG classification for almost every move.

Throughout this codebase, mate is normalized to 0 (not null) to mean "no active mate" — see mate:_e.mate||0 and _mate=0 in tablebase.js, and the terminal-position caching in _requestBatchEval (mate:0). But _evalOrMate only treats null/undefined as "no mate":

function _evalOrMate(mate,fallbackEval){
  if(mate==null)return fallbackEval;
  return mate>0?90000:-90000;
}

For mate===0 this falls through to mate>0?90000:-90000-90000, the opposite of the documented intent ("no mate → use cur.eval directly"). Since two adjacent non-mate positions both have mate===0, curEv/prevEv both become -90000, so delta collapses to 0 for virtually every move — silently disabling the NAG move-quality annotations in PGN export (_buildPGNString, line ~1386) and, per the file summary, the rewritten _formatEvalDelta used across the review UI.

🐛 Proposed fix
 function _evalOrMate(mate,fallbackEval){
-  if(mate==null)return fallbackEval;
+  if(!mate)return fallbackEval; // covers null, undefined, AND 0 ("no mate")
   return mate>0?90000:-90000;
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/assets/chess.src/ai-bridge.js` around lines 4609 - 4617, Update
_evalOrMate so mate===0 is treated as “no active mate” and returns fallbackEval,
while only positive and negative mate values map to the ±90000 sentinels.
Preserve the existing handling for null/undefined and the documented White-POV
score behavior.
src/main/assets/chess.src/game-logic.js (1)

2463-2524: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Correctly implements FIDE 6.9 winner-side mating-material check. Verified the K vs K / K+minor / K+2N / K+B+B same-color / mixed-color / K+N+B cases against FIDE rules — logic is sound and resolves the previously-flagged gap where isDeadPosition() (symmetric FIDE 5.2.2) missed asymmetric timeout draws.

SonarCloud flags cognitive complexity 29 (limit 15) for this function. Consider splitting the material-tally scan and the decision logic into two smaller functions to satisfy the gate.

🧰 Tools
🪛 GitHub Check: SonarCloud Code Analysis

[failure] 2470-2470: Refactor this function to reduce its Cognitive Complexity from 29 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ95GW78q4IVm24_K2cw&open=AZ95GW78q4IVm24_K2cw&pullRequest=52

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/assets/chess.src/game-logic.js` around lines 2463 - 2524, Reduce the
cognitive complexity of winnerLacksMatingMaterial by extracting the board scan
and winner-piece counting, including bishop-parity tracking, into a focused
helper. Keep the existing material-decision rules and outcomes unchanged, with
winnerLacksMatingMaterial consuming the helper’s tally and retaining the
king-count sanity check.

Source: Linters/SAST tools

src/main/assets/chess.src/ui-gameflow.js (1)

320-327: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Simplify the duplicate-branch structure flagged by SonarCloud. Both branches perform the identical action (_isDrawByInsufficientMaterial=true); this can be collapsed into a single if with an ||.

♻️ Proposed simplification
-      if(typeof winnerLacksMatingMaterial==='function'
-         && winnerLacksMatingMaterial(gameState,winner)){
-        _isDrawByInsufficientMaterial=true;
-      }else if(typeof isDeadPosition==='function'&&isDeadPosition(gameState)){
-        // FIDE 5.2.2 fallback: whole position is dead (both sides lack
-        //   material). This subsumes K vs K and the rare mutual case.
-        _isDrawByInsufficientMaterial=true;
-      }
+      const _winnerCantMate=typeof winnerLacksMatingMaterial==='function'&&winnerLacksMatingMaterial(gameState,winner);
+      // FIDE 5.2.2 fallback: whole position is dead (both sides lack material).
+      const _isDead=typeof isDeadPosition==='function'&&isDeadPosition(gameState);
+      if(_winnerCantMate||_isDead){
+        _isDrawByInsufficientMaterial=true;
+      }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

      const _winnerCantMate=typeof winnerLacksMatingMaterial==='function'&&winnerLacksMatingMaterial(gameState,winner);
      // FIDE 5.2.2 fallback: whole position is dead (both sides lack material).
      const _isDead=typeof isDeadPosition==='function'&&isDeadPosition(gameState);
      if(_winnerCantMate||_isDead){
        _isDrawByInsufficientMaterial=true;
      }
🧰 Tools
🪛 GitHub Check: SonarCloud Code Analysis

[warning] 323-327: This branch's code block is the same as the block for the branch on line 321.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ95GXBUq4IVm24_K2c0&open=AZ95GXBUq4IVm24_K2c0&pullRequest=52

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/assets/chess.src/ui-gameflow.js` around lines 320 - 327, In the
draw-detection logic, replace the separate winnerLacksMatingMaterial and
isDeadPosition branches with one conditional using ||, while preserving the
typeof guard before calling each optional function and retaining the single
assignment to _isDrawByInsufficientMaterial.

Source: Linters/SAST tools

src/main/java/com/Regalia/HapticManager.java (1)

70-79: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '1,220p' src/main/java/com/Regalia/HapticManager.java
printf '\n--- search ---\n'
rg -n "_systemHapticCacheTs|_systemHapticCached|System\.currentTimeMillis|elapsedRealtime|SystemClock" src/main/java

Repository: YDW99/Regalia

Length of output: 13870


🌐 Web query:

Android SystemClock elapsedRealtime monotonic currentTimeMillis wall clock docs

💡 Result:

In Android development, SystemClock.elapsedRealtime and System.currentTimeMillis serve fundamentally different purposes based on their clock characteristics [1][2]. System.currentTimeMillis This is the standard wall clock, representing the number of milliseconds since the Unix epoch (January 1, 1970) [1][3]. It is intended for use when correspondence with real-world dates and times is required, such as in alarm clocks, calendars, or UI displays [1][4]. Importantly, this clock is not monotonic; it can be adjusted by the user, the phone network, or time zone changes, meaning it may jump backwards or forwards unpredictably [1][5]. It should not be used for measuring intervals [6]. SystemClock.elapsedRealtime This clock provides the number of milliseconds since the system was booted, including time spent in deep sleep [1][2]. It is guaranteed to be monotonic, meaning it will never jump backward or behave unexpectedly due to time synchronization or user settings [1][4]. Consequently, it is the recommended basis for all general-purpose interval timing and duration measurements in Android [1][6]. Related Clocks - SystemClock.uptimeMillis: Similar to elapsedRealtime, it measures time since boot but stops during deep sleep [1][5]. It is suitable for interval timing where the interval is not expected to span device sleep [1]. - System.nanoTime: Provides a high-resolution time source for measuring elapsed time, but it is unrelated to wall-clock time and does not account for time spent in deep sleep [3]. Its origin is arbitrary and only meaningful for comparing durations within the same Java virtual machine instance [3].

Citations:


Use a monotonic clock for the 5s cache TTL. System.currentTimeMillis() can jump backward or forward, which can stretch or stall the refresh window; SystemClock.elapsedRealtime() is the right clock for elapsed-duration checks.

Proposed fix
-            long now = System.currentTimeMillis();
+            long now = android.os.SystemClock.elapsedRealtime();
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

            long now = android.os.SystemClock.elapsedRealtime();
            boolean systemEnabled;
            if (now - _systemHapticCacheTs > 5000) {
                _systemHapticCached = android.provider.Settings.System.getInt(
                    context.getContentResolver(),
                    android.provider.Settings.System.HAPTIC_FEEDBACK_ENABLED, 1
                ) != 0;
                _systemHapticCacheTs = now;
            }
            systemEnabled = _systemHapticCached;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/Regalia/HapticManager.java` around lines 70 - 79, Update
the cache expiration timing in HapticManager’s system haptic settings refresh
logic to use Android’s monotonic SystemClock.elapsedRealtime() instead of
System.currentTimeMillis(). Keep the existing 5-second TTL comparison and cache
update behavior unchanged.
src/main/java/com/Regalia/MainActivity.java (2)

85-86: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map the relevant file structure first
ast-grep outline src/main/java/com/Regalia/MainActivity.java --view expanded || true

# Read the relevant section around the cited lines
sed -n '1,240p' src/main/java/com/Regalia/MainActivity.java | cat -n

# Find stabilization-related methods and lifecycle hooks
rg -n "stabilization|toggleStabilization|onDestroy|onPause|onResume|setContentView|webView|BACK|fallback" src/main/java/com/Regalia/MainActivity.java src/main/java -S

# Locate the helper implementation
fd -a "StabilizationHelper.java" src/main/java || true

Repository: YDW99/Regalia

Length of output: 50369


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Read the stabilization toggle implementation and nearby lifecycle methods
sed -n '540,920p' src/main/java/com/Regalia/MainActivity.java | cat -n

# Inspect the helper class structure
fd -a "StabilizationHelper.java" src/main/java
helper_path="$(fd -a "StabilizationHelper.java" src/main/java | head -n 1)"
if [ -n "${helper_path:-}" ]; then
  echo "=== $helper_path ==="
  sed -n '1,260p' "$helper_path" | cat -n
fi

# Find any synchronization / threading annotations or handlers used by the helper
if [ -n "${helper_path:-}" ]; then
  rg -n "synchronized|Handler|Looper|post|Thread|Atomic|volatile|registerListener|unregisterListener|start\\(|stop\\(" "$helper_path" -S
fi

Repository: YDW99/Regalia

Length of output: 35123


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Read the stabilization toggle implementation and nearby lifecycle methods
sed -n '540,920p' src/main/java/com/Regalia/MainActivity.java | cat -n

# Inspect the helper class structure
helper_path="$(fd -a "StabilizationHelper.java" src/main/java | head -n 1)"
if [ -n "${helper_path:-}" ]; then
  echo "=== $helper_path ==="
  sed -n '1,260p' "$helper_path" | cat -n
  echo "=== threading/synchronization references ==="
  rg -n "synchronized|Handler|Looper|post|Thread|Atomic|volatile|registerListener|unregisterListener|start\\(|stop\\(" "$helper_path" -S
fi

Repository: YDW99/Regalia

Length of output: 35098


Serialize stabilization lifecycle on one thread. volatile only gives visibility here; onDestroy() can clear the helper while toggleStabilization() concurrently creates/starts a new one from the JS callback, leaving a sensor listener tied to a destroyed Activity. Marshal the toggle onto the main thread or guard both paths with the same destroyed/state check.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/Regalia/MainActivity.java` around lines 85 - 86, Serialize
the stabilization lifecycle between toggleStabilization() and onDestroy() by
dispatching toggle operations to the main thread or protecting both methods with
the same synchronization and destroyed-state check. Ensure no new
StabilizationHelper is created or started after destruction begins, and that
onDestroy() cannot clear the helper while a toggle is starting one.

344-352: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Do not trap users on the engine-failure fallback UI.

This fallback leaves webView non-null. Consequently, BACK follows the webView != null branch at Line 802, dispatches to the hidden page, and consumes the event instead of closing the Activity. Track fallback mode (or detach/clear the WebView) and let BACK reach super while it is displayed.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/Regalia/MainActivity.java` around lines 344 - 352, Update
the engine-failure fallback flow around showFallbackUI and the Activity’s BACK
handling so fallback mode is explicitly tracked or the WebView is
detached/cleared. Ensure BACK does not dispatch to the hidden webView while
fallback UI is displayed, allowing the event to reach super and close the
Activity; preserve normal WebView navigation behavior outside fallback mode.
worklog.md (1)

37-69: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Fix markdownlint violations in the new round-30 section.

Static analysis flags MD040 (fenced code blocks missing a language, e.g. lines 81, 104, 111, 118, 128, 137, 288, 308, 315, 322, 332, 347 — mostly log/verification output blocks) and MD029 (ordered-list prefix mismatch, lines 37-69) in the newly added round-30 entry. This mirrors the recurring markdown-lint pattern already flagged in earlier reviews of this file.

🧹 Suggested fix direction
-```
+```text
 所有 11 个 chess.src/*.js 模块通过 node --check ✓

The MD029 numbering (e.g. jumping straight to "7." under "健壮性巩固(7 项)") may be an intentional running count across subsections — if so, consider disabling MD029 in the markdownlint config instead of renumbering, to avoid re-triggering this on every future round entry.

Also applies to: 81-347

🧰 Tools
🪛 markdownlint-cli2 (0.23.0)

[warning] 37-37: Ordered list item prefix
Expected: 1; Actual: 7; Style: 1/2/3

(MD029, ol-prefix)


[warning] 39-39: Ordered list item prefix
Expected: 2; Actual: 8; Style: 1/2/3

(MD029, ol-prefix)


[warning] 41-41: Ordered list item prefix
Expected: 3; Actual: 9; Style: 1/2/3

(MD029, ol-prefix)


[warning] 43-43: Ordered list item prefix
Expected: 4; Actual: 10; Style: 1/2/3

(MD029, ol-prefix)


[warning] 45-45: Ordered list item prefix
Expected: 5; Actual: 11; Style: 1/2/3

(MD029, ol-prefix)


[warning] 47-47: Ordered list item prefix
Expected: 6; Actual: 12; Style: 1/2/3

(MD029, ol-prefix)


[warning] 49-49: Ordered list item prefix
Expected: 7; Actual: 13; Style: 1/2/3

(MD029, ol-prefix)


[warning] 53-53: Ordered list item prefix
Expected: 1; Actual: 14; Style: 1/2/3

(MD029, ol-prefix)


[warning] 55-55: Ordered list item prefix
Expected: 2; Actual: 15; Style: 1/2/3

(MD029, ol-prefix)


[warning] 57-57: Ordered list item prefix
Expected: 3; Actual: 16; Style: 1/2/3

(MD029, ol-prefix)


[warning] 59-59: Ordered list item prefix
Expected: 4; Actual: 17; Style: 1/2/3

(MD029, ol-prefix)


[warning] 61-61: Ordered list item prefix
Expected: 5; Actual: 18; Style: 1/2/3

(MD029, ol-prefix)


[warning] 65-65: Ordered list item prefix
Expected: 1; Actual: 19; Style: 1/2/3

(MD029, ol-prefix)


[warning] 67-67: Ordered list item prefix
Expected: 2; Actual: 20; Style: 1/2/3

(MD029, ol-prefix)


[warning] 69-69: Ordered list item prefix
Expected: 3; Actual: 21; Style: 1/2/3

(MD029, ol-prefix)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@worklog.md` around lines 37 - 69, Fix markdownlint issues in the new round-30
section of worklog.md: add an explicit text language to every fenced log or
verification output block flagged by MD040, including the blocks around the
listed entries. Preserve the intentional running numbering in the ordered list
and configure markdownlint to allow it by disabling or appropriately configuring
MD029 rather than renumbering the entries.

Source: Linters/SAST tools

YDW99 and others added 2 commits July 20, 2026 06:11
Signed-off-by: D.W. Yang <1151712579@qq.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 13

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (12)
src/main/java/com/Regalia/StockfishNative.java (2)

3026-3035: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Do not overwrite a concurrent shutdown request.

After shutdown() sets shutdownRequested = true, this restart task unconditionally recreates the executor and sets it back to false. If another shutdown occurs during the 500 ms delay, that request is lost and startEngine() can launch a new engine after the user has quit. Coordinate restart/shutdown with a lifecycle lock or generation token, and re-check cancellation before resetting the flag and scheduling startup.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/Regalia/StockfishNative.java` around lines 3026 - 3035, The
restart path around shutdownRequested must not clear a newer shutdown request
after the 500 ms delay. Coordinate the delayed restart with shutdown() using the
existing lifecycle synchronization or a generation/cancellation token,
re-checking cancellation immediately before resetting shutdownRequested and
invoking startEngine(); ensure a shutdown occurring during the delay prevents
executor recreation and engine startup.

975-983: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Capture the timestamp before _safeExecute().

_callTimeMs is recorded inside the executor runnable, so any wait in the single-thread queue is excluded from setupElapsedMs. When engineGoTimed() backs up behind another task, the wtime/btime you send are already stale and Stockfish can overrun the GUI clock. Move the timestamp capture outside the runnable and pass it in.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/Regalia/StockfishNative.java` around lines 975 - 983, Move
the _callTimeMs capture in engineGoTimed() to immediately before invoking
_safeExecute(), rather than inside the executor runnable. Pass that captured
timestamp into the runnable so setupElapsedMs includes any queue wait before
execution, preserving the existing clock deduction behavior.
src/main/java/com/Regalia/HapticManager.java (2)

80-88: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Force the first system-setting cache refresh.

_systemHapticCacheTs starts at 0, so the first calls after boot skip the refresh while _systemHapticCached stays true. If system haptics are disabled, that setting is ignored until the TTL expires. Treat 0 as uncached or add an explicit validity flag.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/Regalia/HapticManager.java` around lines 80 - 88, Update
the cache refresh condition in HapticManager’s system haptic lookup to treat
_systemHapticCacheTs == 0 as uncached, ensuring the first lookup reads
HAPTIC_FEEDBACK_ENABLED immediately. Preserve the existing five-second TTL
behavior for subsequent refreshes.

55-58: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Store the application context here.
StatsActivity passes an Activity instance into HapticManager, and the posted runnable can keep that reference alive longer than the screen. context.getApplicationContext() is enough for the resolver/service lookups here, and it matches the existing StockfishNative pattern.

Proposed fix
-        this.context = context;
+        this.context = context.getApplicationContext();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/Regalia/HapticManager.java` around lines 55 - 58, Update
the HapticManager constructor to store context.getApplicationContext() instead
of the Activity context, while leaving the existing prefs and mainHandler
assignments unchanged.
src/main/java/com/Regalia/ChessWebViewClient.java (1)

83-100: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use the application-context fallback when the Activity is no longer usable. activityRef.get() only tells you the MainActivity hasn’t been GC’d; it can still be finishing or destroyed, so this branch can skip the safer application-context path. Check the lifecycle state before calling activity.startActivity(intent), and fall back to view.getContext().getApplicationContext() otherwise.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/Regalia/ChessWebViewClient.java` around lines 83 - 100,
Update the activity launch logic around activityRef.get() to verify the Activity
is usable, not merely non-null, before calling activity.startActivity(intent).
Treat finishing or destroyed activities as unusable and route those cases
through the existing application-context fallback using
view.getContext().getApplicationContext(); preserve the direct Activity launch
for valid lifecycle states.
src/main/java/com/Regalia/MainActivity.java (3)

361-369: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Fallback-on-exhaustion never fires if stockfishEngine stays null.

Both branches require stockfishEngine != null. If the constructor at Line 341 keeps throwing (persistent native init failure), stockfishEngine remains null forever; neither branch executes, scheduleInitRetry() is never invoked again, and the loop dies silently after the very first attempt — with no fallback UI ever shown. This is exactly the "indefinite spinner" scenario the comment says this change fixes, but it only covers the "created-but-not-ready" case, not "never-created".

🐛 Treat null engine the same as not-ready
-                if (stockfishEngine != null && !stockfishEngine.isEngineReady() && initRetryCount < INIT_MAX_RETRIES) {
+                boolean engineNotReady = stockfishEngine == null || !stockfishEngine.isEngineReady();
+                if (engineNotReady && initRetryCount < INIT_MAX_RETRIES) {
                     initRetryCount++;
                     Log.i(TAG, "Delayed engine init retry " + initRetryCount + "/" + INIT_MAX_RETRIES);
-                    initStockfishEngine();
+                    if (stockfishEngine != null) initStockfishEngine();
                     // Also trigger JS-side init via evaluateJavascript as backup
                     try {
                         webView.evaluateJavascript(
                             "try{if(typeof AndroidBridge!=='undefined'&&AndroidBridge.initEngine){AndroidBridge.initEngine();}}catch(e){console.error('Delayed init error:',e);}",
                             null
                         );
                     } catch (Throwable e) {
                         Log.w(TAG, "JS delayed init call failed", e);
                     }
                     scheduleInitRetry();
-                } else if (stockfishEngine != null && !stockfishEngine.isEngineReady()
-                           && initRetryCount >= INIT_MAX_RETRIES) {
+                } else if (engineNotReady && initRetryCount >= INIT_MAX_RETRIES) {
                     Log.e(TAG, "All " + INIT_MAX_RETRIES + " init retries exhausted — showing fallback UI");
                     showFallbackUI(getString(R.string.app_name) + ": engine init failed. Please restart the app.");
                 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/Regalia/MainActivity.java` around lines 361 - 369, Update
the initialization retry logic around stockfishEngine and scheduleInitRetry() so
a null engine is treated the same as an engine that exists but is not ready.
Ensure persistent constructor failures continue through the retry/exhaustion
path, invoke the fallback UI after INIT_MAX_RETRIES, and preserve the existing
behavior for non-null engines.

369-369: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Fallback message is English-only, inconsistent with the app's bilingual pattern.

Other showFallbackUI messages in this file are Chinese-only (unicode-escaped) and the equivalent message in ChessWebViewClient.java is bilingual (zh/en). This new message is English-only despite the app having an explicit language-preference mechanism (showToastLocalized), which will read oddly for the likely majority Chinese-speaking user base.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/Regalia/MainActivity.java` at line 369, Update the fallback
message at the MainActivity showFallbackUI call to follow the app’s bilingual
messaging pattern, including the corresponding Chinese and English text. Reuse
the established localized-message approach or matching bilingual format from
ChessWebViewClient.java, while preserving the existing app-name prefix and
engine-init failure guidance.

76-103: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

_stabilizationLock isn't held by onResume/onPause, so the race it's meant to close still exists.

toggleStabilization() (JS binder thread) and onDestroy() (main thread) both correctly synchronize on _stabilizationLock around every mutation of stabilizationHelper/stabilizationEnabled. But onResume (Line 583-585) and onPause (Line 646-648) still call stabilizationHelper.start()/.stop() on the same shared instance without acquiring the lock. Since toggleStabilization() can fire on the binder thread at any moment, it can race with onResume/onPause on the main thread — two threads calling start()/.stop() on the same non-thread-safe listener concurrently. The comment justifying this ("fields stay volatile for the onResume/onPause single-reads") addresses stale-read visibility, not the actual hazard, which is concurrent mutation of shared listener state; a lost toggle (user's long-press silently not taking effect) is the realistic symptom.

🔒 Extend the lock to onResume/onPause
// onResume (currently unguarded, Line 583-585)
synchronized (_stabilizationLock) {
    if (stabilizationEnabled && stabilizationHelper != null) {
        try { stabilizationHelper.start(); } catch (Throwable e) { Log.w(TAG, "stab restart on resume failed", e); }
    }
}

// onPause (currently unguarded, Line 646-648)
synchronized (_stabilizationLock) {
    if (stabilizationEnabled && stabilizationHelper != null) {
        try { stabilizationHelper.stop(); } catch (Throwable e) { Log.w(TAG, "stab stop on pause failed", e); }
    }
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/Regalia/MainActivity.java` around lines 76 - 103, Guard the
stabilization lifecycle calls in onResume and onPause with _stabilizationLock,
including their enabled/helper checks and start()/stop() operations. Preserve
the existing exception handling and logging, ensuring these calls cannot run
concurrently with toggleStabilization() or onDestroy().
Manual/Regalia-v1.2.3-manual-en.html (1)

706-711: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Keep the UI architecture documentation synchronized. The build examples list ui-gameflow.js and ui-interactions.js, while both architecture diagrams still describe ui.js as the sole UI/interaction module.

  • Manual/Regalia-v1.2.3-manual-en.html#L706-L711: update the diagram above the example to show both extracted modules and their responsibilities.
  • Manual/Regalia-v1.2.3-manual-zh.html#L704-L710: mirror the same diagram update in the Chinese manual.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Manual/Regalia-v1.2.3-manual-en.html` around lines 706 - 711, The
architecture diagrams still present ui.js as the sole UI/interaction module;
update both Manual/Regalia-v1.2.3-manual-en.html lines 706-711 and
Manual/Regalia-v1.2.3-manual-zh.html lines 704-710 to show ui-gameflow.js and
ui-interactions.js with their respective responsibilities, keeping the English
and Chinese diagrams synchronized.
NOTICE (1)

575-583: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Synchronize the canonical GPL file inventory with the refactor.

Round-17 correctly documents HapticManager.java, ui-gameflow.js, and ui-interactions.js as GPL v3, but the canonical GPL list later in this file omits these files and still lists extracted modules documented as deleted. Update the current inventory so redistribution notices identify the actual files and licenses.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@NOTICE` around lines 575 - 583, Update the canonical GPL file inventory in
NOTICE to add HapticManager.java, ui-gameflow.js, and ui-interactions.js, and
remove entries for extracted modules that are documented as deleted. Keep the
inventory synchronized with the round-17 refactor and preserve the existing GPL
v3 attribution format.
src/main/assets/README.license (1)

2018-2018: 🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

Make the worker-pool.js license history internally consistent.

The changed entries label worker-pool.js as GPL v3, matching the current classification stated earlier in this file, but nearby historical text still says the Phase-35 correction changed GPL v3 to AGPL v3 and repeats the opposite transition later. Normalize each historical entry to the license in effect at that date, or update the stale transition notes to the verified classification; do not leave both narratives.

Also applies to: 2738-2742, 2887-2891, 2949-2965, 3191-3195, 3275-3277, 3704-3705, 3724-3724, 3751-3752, 3770-3776, 3785-3787

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/assets/README.license` at line 2018, Normalize all worker-pool.js
history entries identified in the review so their recorded licenses and Phase-35
transition notes consistently reflect the verified classification. Update the
stale GPL v3/AGPL v3 narratives rather than leaving contradictory transitions
across the license history.
src/main/assets/chess.src/README.license (1)

2018-2018: 🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

Make the worker-pool.js license history internally consistent.

The changed entries label worker-pool.js as GPL v3, matching the current classification stated earlier in this file, but nearby historical text still says the Phase-35 correction changed GPL v3 to AGPL v3 and repeats the opposite transition later. Normalize each historical entry to the license in effect at that date, or update the stale transition notes to the verified classification; do not leave both narratives.

Also applies to: 2738-2742, 2887-2891, 2949-2965, 3191-3195, 3275-3277, 3704-3705, 3724-3724, 3751-3752, 3770-3776, 3785-3787

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/assets/chess.src/README.license` at line 2018, Normalize every
worker-pool.js history entry in README.license, including the listed repeated
ranges, so its stated license and Phase-35 transition notes consistently reflect
the verified classification at each date. Remove or correct contradictory GPL
v3/AGPL v3 narratives while preserving unrelated historical details.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@BUILDING.md`:
- Around line 1-2: Confirm July 20 is not intentional against the review date,
then align all round-31/32 documentation dates to July 19, 2026: update
BUILDING.md lines 1-2 and 53, Manual/README.license lines 1-2 and 12-13, both
Manual/Regalia-v1.2.3-manual-en.html and Manual/Regalia-v1.2.3-manual-zh.html
lines 543-544, src/main/java/com/Regalia/README.license lines 1-2 and 37-38, and
src/main/cpp/README.license lines 1-2 and 10-11 consistently.
- Line 1: Update the opening heading in BUILDING.md from the second-level
Round-32 build notes heading to a top-level heading, or restore the document’s
existing top-level heading before it, so the file begins with an H1.

In `@Manual/README.license`:
- Around line 1-11: Update the current-manual classification block in
README.license to identify the v1.2.3 Chinese and English manuals as current,
replacing the stale v1.2.1 references; alternatively, explicitly label the
v1.2.1 manuals as historical.

In `@Manual/Regalia-v1.2.3-manual-en.html`:
- Around line 543-544: The round-32 timestamp-site total is inconsistent with
its breakdown: 11 StockfishNative sites plus 2 EngineHealthMonitor sites plus 1
ChessWebViewClient site equals 14. Update both
Manual/Regalia-v1.2.3-manual-en.html lines 543-544 and
Manual/Regalia-v1.2.3-manual-zh.html lines 543-544 to state 14 additional sites,
leaving the component counts unchanged.

In `@NOTICE`:
- Around line 31-35: Correct the license labels in NOTICE for the listed
entries: change StatsActivity.java and HapticManager.java from AGPL v3 to GPL
v3, and change state-store.js from GPL v3 to AGPL v3. Update all referenced
duplicate or historical classification entries while leaving unrelated
API/Android comments unchanged.

In `@README.md`:
- Around line 6-7: Reconcile the Round-32 site count in README.md so the stated
total matches the per-file breakdown: 11 sites in StockfishNative.java, 2 in
EngineHealthMonitor.java, and 1 in ChessWebViewClient.java. Update either the
“13 additional sites” total or the breakdown, preserving the accurate audit
counts.
- Line 1: Align all Round-31 and Round-32 dates with the actual release date by
replacing or deferring the July 20, 2026 dates in README.md lines 1 and 89,
PRIVACY.md lines 1 and 28, assets/README.license lines 1 and 7,
src/main/README.license lines 1 and 7, and
src/main/assets/chess.src/README.license lines 1 and 29.
- Line 1: Keep the changelog preambles markdownlint-clean: in README.md at lines
1-1, 9-9, 39-39, 60-60, 66-66, 79-79, 84-84, 96-96, 111-111, 125-125, 144-144,
153-153, and 165-165, add or move a top-level heading before the changelog, add
blank lines around each heading, and remove spaces inside emphasis markers at
84-84; in PRIVACY.md at 1-1, place the changelog beneath the existing top-level
privacy-policy heading.

In `@src/main/assets/chess.html`:
- Around line 18687-18737: Apply the SonarCloud complexity reduction to
_renderRvArrowSvg and _triggerPendingPostBatchActions in the chess.src/ui.js
source module rather than the generated chess.html output. Preserve their
existing behavior, then regenerate chess.html from the source so the generated
artifact reflects the durable fix.

In `@src/main/assets/chess.src/game-logic.js`:
- Around line 2511-2537: Reduce cognitive complexity in _scanWinnerMaterial by
extracting the bishop count and bishopParity update from the case'bishop' branch
into a small helper, while preserving all existing material counts and parity
behavior. Apply the source change in src/main/assets/chess.src/game-logic.js at
lines 2511-2537, then rebuild so src/main/assets/chess.html lines 3828-3854
receives the generated update; do not edit the bundle manually.

In `@src/main/assets/README.license`:
- Line 1: Update the release-history entry for v1.2.3 round-32 in the assets
README to use the actual release/commit date, or defer the entry until July 20,
2026; apply the same correction to the corresponding Round-31 and Round-32
entries in the other release-history files.

In `@worklog.md`:
- Line 67: Update the worklog entry to wrap underscored identifiers such as
_evalOrMate, _scanWinnerMaterial, _bishopParityIsUniform, and _stabilizationLock
in Markdown code spans, preventing them from being parsed as emphasis while
preserving the surrounding text.
- Around line 21-27: The unresolved-issue totals and category breakdown in
“PR52_Unresolved_Issues_Latest.docx” are inconsistent with the ten entries under
“真实缺陷”. Reconcile the stated overall count and the CodeRabbit, documentation,
and PR-blocker grouping so all totals add up and match the documented entries.

---

Outside diff comments:
In `@Manual/Regalia-v1.2.3-manual-en.html`:
- Around line 706-711: The architecture diagrams still present ui.js as the sole
UI/interaction module; update both Manual/Regalia-v1.2.3-manual-en.html lines
706-711 and Manual/Regalia-v1.2.3-manual-zh.html lines 704-710 to show
ui-gameflow.js and ui-interactions.js with their respective responsibilities,
keeping the English and Chinese diagrams synchronized.

In `@NOTICE`:
- Around line 575-583: Update the canonical GPL file inventory in NOTICE to add
HapticManager.java, ui-gameflow.js, and ui-interactions.js, and remove entries
for extracted modules that are documented as deleted. Keep the inventory
synchronized with the round-17 refactor and preserve the existing GPL v3
attribution format.

In `@src/main/assets/chess.src/README.license`:
- Line 2018: Normalize every worker-pool.js history entry in README.license,
including the listed repeated ranges, so its stated license and Phase-35
transition notes consistently reflect the verified classification at each date.
Remove or correct contradictory GPL v3/AGPL v3 narratives while preserving
unrelated historical details.

In `@src/main/assets/README.license`:
- Line 2018: Normalize all worker-pool.js history entries identified in the
review so their recorded licenses and Phase-35 transition notes consistently
reflect the verified classification. Update the stale GPL v3/AGPL v3 narratives
rather than leaving contradictory transitions across the license history.

In `@src/main/java/com/Regalia/ChessWebViewClient.java`:
- Around line 83-100: Update the activity launch logic around activityRef.get()
to verify the Activity is usable, not merely non-null, before calling
activity.startActivity(intent). Treat finishing or destroyed activities as
unusable and route those cases through the existing application-context fallback
using view.getContext().getApplicationContext(); preserve the direct Activity
launch for valid lifecycle states.

In `@src/main/java/com/Regalia/HapticManager.java`:
- Around line 80-88: Update the cache refresh condition in HapticManager’s
system haptic lookup to treat _systemHapticCacheTs == 0 as uncached, ensuring
the first lookup reads HAPTIC_FEEDBACK_ENABLED immediately. Preserve the
existing five-second TTL behavior for subsequent refreshes.
- Around line 55-58: Update the HapticManager constructor to store
context.getApplicationContext() instead of the Activity context, while leaving
the existing prefs and mainHandler assignments unchanged.

In `@src/main/java/com/Regalia/MainActivity.java`:
- Around line 361-369: Update the initialization retry logic around
stockfishEngine and scheduleInitRetry() so a null engine is treated the same as
an engine that exists but is not ready. Ensure persistent constructor failures
continue through the retry/exhaustion path, invoke the fallback UI after
INIT_MAX_RETRIES, and preserve the existing behavior for non-null engines.
- Line 369: Update the fallback message at the MainActivity showFallbackUI call
to follow the app’s bilingual messaging pattern, including the corresponding
Chinese and English text. Reuse the established localized-message approach or
matching bilingual format from ChessWebViewClient.java, while preserving the
existing app-name prefix and engine-init failure guidance.
- Around line 76-103: Guard the stabilization lifecycle calls in onResume and
onPause with _stabilizationLock, including their enabled/helper checks and
start()/stop() operations. Preserve the existing exception handling and logging,
ensuring these calls cannot run concurrently with toggleStabilization() or
onDestroy().

In `@src/main/java/com/Regalia/StockfishNative.java`:
- Around line 3026-3035: The restart path around shutdownRequested must not
clear a newer shutdown request after the 500 ms delay. Coordinate the delayed
restart with shutdown() using the existing lifecycle synchronization or a
generation/cancellation token, re-checking cancellation immediately before
resetting shutdownRequested and invoking startEngine(); ensure a shutdown
occurring during the delay prevents executor recreation and engine startup.
- Around line 975-983: Move the _callTimeMs capture in engineGoTimed() to
immediately before invoking _safeExecute(), rather than inside the executor
runnable. Pass that captured timestamp into the runnable so setupElapsedMs
includes any queue wait before execution, preserving the existing clock
deduction behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: bc998af7-7c5f-49b3-a07d-f9ec0c2cfc7e

📥 Commits

Reviewing files that changed from the base of the PR and between 74aa314 and 406b8a1.

⛔ Files ignored due to path filters (1)
  • LICENSE&NOTICE.zip is excluded by !**/*.zip
📒 Files selected for processing (30)
  • BUILDING.md
  • Manual/README.license
  • Manual/Regalia-v1.2.3-manual-en.html
  • Manual/Regalia-v1.2.3-manual-zh.html
  • NOTICE
  • PRIVACY.md
  • README.md
  • assets/README.license
  • src/main/README.license
  • src/main/assets/README.license
  • src/main/assets/chess.html
  • src/main/assets/chess.src/README.license
  • src/main/assets/chess.src/ai-bridge.js
  • src/main/assets/chess.src/eco-data.js
  • src/main/assets/chess.src/game-logic.js
  • src/main/assets/chess.src/pgn-standard.js
  • src/main/assets/chess.src/state-store.js
  • src/main/cpp/README.license
  • src/main/java/com/Regalia/ChessWebViewClient.java
  • src/main/java/com/Regalia/EngineHealthMonitor.java
  • src/main/java/com/Regalia/FileIoHelper.java
  • src/main/java/com/Regalia/HapticManager.java
  • src/main/java/com/Regalia/MainActivity.java
  • src/main/java/com/Regalia/PermissionHelper.java
  • src/main/java/com/Regalia/README.license
  • src/main/java/com/Regalia/StabilizationHelper.java
  • src/main/java/com/Regalia/StatsActivity.java
  • src/main/java/com/Regalia/StockfishNative.java
  • src/main/res/README.license
  • worklog.md
📜 Review details
⏰ Context from checks skipped due to timeout. (2)
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: Gitar
🧰 Additional context used
🪛 ast-grep (0.44.1)
src/main/assets/chess.html

[warning] 7871-7878: Avoid using the initial state variable in setState
Context: setTimeout(()=>{
t.style.opacity='0';
_toastRemoveTimer=setTimeout(()=>{
t.remove();
_toastRemoveTimer=0;
},300);
_toastTimer=0;
},duration)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(setstate-same-var)


[error] 7871-7878: React's useState should not be directly called
Context: setTimeout(()=>{
t.style.opacity='0';
_toastRemoveTimer=setTimeout(()=>{
t.remove();
_toastRemoveTimer=0;
},300);
_toastTimer=0;
},duration)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[error] 8871-8873: React's useState should not be directly called
Context: setTimeout(function(){
try{reviewAnalyzeAll();}catch(e){console.error('openStatsPage: deferred analyze-all trigger failed:',e);}
},1000)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[error] 10890-10896: React's useState should not be directly called
Context: setTimeout(function(){
if(myGen!==_settingsImportGen)return;
showEngineConfig=false;
var dov2=document.querySelector('.dov[role="dialog"]');
if(dov2){dov2.remove();}
render();
},100)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[error] 13085-13085: React's useState should not be directly called
Context: setChess960Mode(true)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[warning] 14766-14766: Avoid using the initial state variable in setState
Context: setInterval(_tickGameClock,200)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(setstate-same-var)


[error] 14766-14766: React's useState should not be directly called
Context: setInterval(_tickGameClock,200)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[warning] 15887-15887: Avoid using the initial state variable in setState
Context: setTimeout(_waitForDialog,200)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(setstate-same-var)


[error] 15887-15887: React's useState should not be directly called
Context: setTimeout(_waitForDialog,200)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[error] 16560-16565: React's useState should not be directly called
Context: setTimeout(function() {
if (typeof _engineReady !== 'undefined' && (_engineReady || document.getElementById('board-grid'))) {
try{localStorage.removeItem('Regalia_recovery');}catch(e){console.warn('[UI]',e?.message?e.message:e);}
try{if(typeof AndroidBridge!=='undefined'&&AndroidBridge.persistentRemove)AndroidBridge.persistentRemove('Regalia_recovery');}catch(e){console.warn('[UI]',e&&e.message?e.message:e);}
}
}, 5000)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[error] 19882-19882: React's useState should not be directly called
Context: setTimeout(()=>{const list=document.querySelector('.op-list');if(list){const active=list.querySelector('.op-btn.act');if(active)active.scrollIntoView({block:'center',behavior:'smooth'})}},50)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[error] 21850-21853: React's useState should not be directly called
Context: setTimeout(function(){
try{_pgnCacheSaveCurrentImpl_SkipCoverageCheck(_pendingSave.name,_pendingSave.includeAnn);}
catch(e){showToast(T('pgn_cache_save_failed'),2500);}
},150)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)


[error] 21857-21860: React's useState should not be directly called
Context: setTimeout(function(){
try{if(typeof openStatsPage==='function')openStatsPage();}
catch(e){console.error('Deferred openStatsPage failed:',e);}
},150)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)

🪛 GitHub Check: SonarCloud Code Analysis
src/main/assets/chess.html

[warning] 3134-3134: Extract this nested ternary operation into an independent statement.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ft0bq4IVm24_IArA&open=AZ94ft0bq4IVm24_IArA&pullRequest=52


[failure] 3828-3828: Refactor this function to reduce its Cognitive Complexity from 16 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ98cQnVrIstupHXrzvo&open=AZ98cQnVrIstupHXrzvo&pullRequest=52


[warning] 3962-3962: This statement will not be executed conditionally; only the first statement will be. The rest will execute unconditionally.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ft0bq4IVm24_IArD&open=AZ94ft0bq4IVm24_IArD&pullRequest=52


[warning] 3962-3962: Extract this nested ternary operation into an independent statement.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ft0bq4IVm24_IArC&open=AZ94ft0bq4IVm24_IArC&pullRequest=52


[warning] 4498-4498: This statement will not be executed conditionally; only the first statement will be. The rest will execute unconditionally.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ft0bq4IVm24_IArG&open=AZ94ft0bq4IVm24_IArG&pullRequest=52


[warning] 4498-4498: This statement will not be executed conditionally; only the first statement will be. The rest will execute unconditionally.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ft0bq4IVm24_IArH&open=AZ94ft0bq4IVm24_IArH&pullRequest=52


[warning] 4498-4498: This statement will not be executed conditionally; only the first statement will be. The rest will execute unconditionally.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ft0bq4IVm24_IArK&open=AZ94ft0bq4IVm24_IArK&pullRequest=52


[warning] 4498-4498: This statement will not be executed conditionally; only the first statement will be. The rest will execute unconditionally.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ft0bq4IVm24_IArE&open=AZ94ft0bq4IVm24_IArE&pullRequest=52


[warning] 4498-4498: This statement will not be executed conditionally; only the first statement will be. The rest will execute unconditionally.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ft0bq4IVm24_IArL&open=AZ94ft0bq4IVm24_IArL&pullRequest=52


[warning] 4498-4498: This statement will not be executed conditionally; only the first statement will be. The rest will execute unconditionally.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ft0bq4IVm24_IArJ&open=AZ94ft0bq4IVm24_IArJ&pullRequest=52


[warning] 4498-4498: This statement will not be executed conditionally; only the first statement will be. The rest will execute unconditionally.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ft0bq4IVm24_IArF&open=AZ94ft0bq4IVm24_IArF&pullRequest=52


[warning] 8624-8624: Compare with undefined directly instead of using typeof.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ft0bq4IVm24_IArM&open=AZ94ft0bq4IVm24_IArM&pullRequest=52


[warning] 14575-14575: Compare with undefined directly instead of using typeof.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ft0bq4IVm24_IArR&open=AZ94ft0bq4IVm24_IArR&pullRequest=52


[warning] 14567-14571: This branch's code block is the same as the block for the branch on line 14565.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ95GXI0q4IVm24_K2c4&open=AZ95GXI0q4IVm24_K2c4&pullRequest=52


[warning] 14739-14739: Compare with undefined directly instead of using typeof.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ft0bq4IVm24_IArT&open=AZ94ft0bq4IVm24_IArT&pullRequest=52


[warning] 14764-14764: Compare with undefined directly instead of using typeof.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ft0bq4IVm24_IArU&open=AZ94ft0bq4IVm24_IArU&pullRequest=52


[warning] 14709-14709: Compare with undefined directly instead of using typeof.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ft0bq4IVm24_IArS&open=AZ94ft0bq4IVm24_IArS&pullRequest=52


[warning] 16511-16511: Use .includes(), rather than .indexOf(), when checking for existence.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ft0bq4IVm24_IArW&open=AZ94ft0bq4IVm24_IArW&pullRequest=52


[warning] 18613-18613: Function '_renderRvBoardCells' has too many parameters (8). Maximum allowed is 7.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ft0bq4IVm24_IArY&open=AZ94ft0bq4IVm24_IArY&pullRequest=52


[failure] 18687-18687: Refactor this function to reduce its Cognitive Complexity from 22 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ft0bq4IVm24_IAra&open=AZ94ft0bq4IVm24_IAra&pullRequest=52


[failure] 21849-21849: Refactor this function to reduce its Cognitive Complexity from 17 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ft0bq4IVm24_IArd&open=AZ94ft0bq4IVm24_IArd&pullRequest=52

src/main/assets/chess.src/game-logic.js

[failure] 2511-2511: Refactor this function to reduce its Cognitive Complexity from 16 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ98cQgTrIstupHXrzvm&open=AZ98cQgTrIstupHXrzvm&pullRequest=52


[warning] 2475-2475: Prefer using an optional chain expression instead, as it's more concise and easier to read.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ95GW78q4IVm24_K2cx&open=AZ95GW78q4IVm24_K2cx&pullRequest=52

🪛 markdownlint-cli2 (0.23.0)
worklog.md

[warning] 67-67: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)

PRIVACY.md

[warning] 1-1: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

BUILDING.md

[warning] 1-1: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

README.md

[warning] 1-1: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)


[warning] 9-9: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 39-39: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 60-60: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 66-66: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 79-79: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 84-84: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)


[warning] 96-96: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 111-111: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 125-125: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 144-144: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 153-153: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 165-165: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)

🔇 Additional comments (37)
src/main/java/com/Regalia/FileIoHelper.java (1)

72-72: LGTM!

Also applies to: 185-192, 218-218, 287-294, 371-387

src/main/java/com/Regalia/HapticManager.java (1)

112-140: LGTM!

Also applies to: 142-440, 442-491, 493-506

src/main/java/com/Regalia/StatsActivity.java (1)

93-96: LGTM!

Also applies to: 118-118, 226-244, 318-325, 390-390, 442-442, 473-473, 599-607

src/main/java/com/Regalia/ChessWebViewClient.java (1)

25-28: LGTM!

Also applies to: 160-166, 176-203, 220-228, 232-251

src/main/java/com/Regalia/EngineHealthMonitor.java (1)

36-36: LGTM!

Also applies to: 53-65, 74-78

src/main/java/com/Regalia/StockfishNative.java (1)

47-47: LGTM!

Also applies to: 167-172, 465-473, 674-689, 758-787, 818-818, 1577-1581, 1801-1801, 1837-1845, 1872-1885, 1898-1898, 1953-1969, 2602-2603, 2646-2654, 2875-2875, 2943-2943, 2968-2972, 2991-2999, 3100-3104, 3728-3732, 3875-3892

worklog.md (2)

20-20: LGTM!

Also applies to: 28-66, 68-339


1-19: 📐 Maintainability & Code Quality

Confirm the shared audit date across both license/worklog records.

Both files record completed round-31/32 work on July 20, 2026, while the current review date is July 19, 2026. Confirm whether this is an intentional timezone-local date; otherwise use July 19, 2026 consistently.

  • worklog.md#L1-L19: correct or clarify the round-31/32 completion date.
  • src/main/res/README.license#L1-L14: synchronize the resource audit entries with the confirmed date.
src/main/res/README.license (1)

15-26: LGTM!

Also applies to: 262-267

src/main/java/com/Regalia/PermissionHelper.java (1)

51-51: LGTM!

Also applies to: 82-82

src/main/java/com/Regalia/MainActivity.java (1)

47-55: LGTM!

Also applies to: 139-139, 290-290, 407-410, 434-441, 460-460, 507-507, 719-729, 833-855, 927-970

src/main/assets/chess.src/ai-bridge.js (3)

3573-3574: The varconst narrowing on info/s here was already raised in a prior review and is now addressed.


4630-4632: LGTM!


4736-4739: LGTM!

src/main/assets/chess.src/game-logic.js (2)

2474-2499: LGTM!


3237-3237: 🗄️ Data Integrity & Integration

No dangling export here. posDesc isn’t called from game-logic.js, and it already lives in ui.js. generateFEN, uciToCoords, and _esc are still used by game-logic.js and are exported from ai-bridge.js.

			> Likely an incorrect or invalid review comment.
src/main/assets/chess.src/pgn-standard.js (2)

765-772: LGTM!


474-497: LGTM!

Also applies to: 844-846

src/main/assets/chess.src/state-store.js (1)

246-255: LGTM!

Also applies to: 298-299, 319-325

src/main/assets/chess.src/eco-data.js (1)

109-134: LGTM!

src/main/assets/chess.html (2)

14700-14771: LGTM!


14548-14582: LGTM!

Also applies to: 8621-8633

BUILDING.md (1)

3-52: LGTM!

Also applies to: 54-111, 1664-1664

Manual/README.license (1)

14-181: LGTM!

Manual/Regalia-v1.2.3-manual-en.html (1)

545-554: LGTM!

Also applies to: 1839-1839, 1880-1911

Manual/Regalia-v1.2.3-manual-zh.html (1)

545-554: LGTM!

Also applies to: 1862-1862, 1905-1934, 1967-1967

src/main/java/com/Regalia/README.license (1)

3-36: LGTM!

Also applies to: 39-309, 322-322, 456-456, 481-481, 542-542, 666-666, 1234-1234, 1258-1258, 1413-1413, 1570-1570, 1580-1580, 1592-1592, 1603-1603

src/main/java/com/Regalia/StabilizationHelper.java (1)

70-70: LGTM!

Also applies to: 141-152, 331-342

src/main/cpp/README.license (1)

3-9: LGTM!

Also applies to: 12-112

NOTICE (1)

1-1: 📐 Maintainability & Code Quality

Verify the Round-32 date before merging.

This entry is dated July 20, 2026, but the supplied PR/review context is dated July 19, 2026. Correct the date or defer the entry until the documented work actually occurred.

PRIVACY.md (1)

115-192: LGTM!

Also applies to: 314-314, 345-380

README.md (2)

277-279: LGTM!

Also applies to: 293-304, 330-333, 351-359, 435-674


348-348: 📐 Maintainability & Code Quality

No change needed: build.gradle already reads ../version.properties, so this README entry is consistent.

			> Likely an incorrect or invalid review comment.
assets/README.license (1)

16-121: LGTM!

src/main/README.license (1)

13-124: LGTM!

Also applies to: 349-358, 577-577

src/main/assets/README.license (1)

198-198: LGTM!

Also applies to: 215-215, 231-231, 306-306, 316-316, 328-328, 340-340, 957-965

src/main/assets/chess.src/README.license (1)

60-60: LGTM!

Also applies to: 198-198, 215-215, 231-231, 306-306, 316-316, 328-328, 340-340, 957-965

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

🛑 Comments failed to post (12)
BUILDING.md (2)

1-1: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use a top-level heading at the start of the file.

BUILDING.md starts with ##, triggering markdownlint MD041. Add a # heading or restore the document’s top-level heading before this section.

🧰 Tools
🪛 markdownlint-cli2 (0.23.0)

[warning] 1-1: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@BUILDING.md` at line 1, Update the opening heading in BUILDING.md from the
second-level Round-32 build notes heading to a top-level heading, or restore the
document’s existing top-level heading before it, so the file begins with an H1.

Source: Linters/SAST tools


1-2: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Align the synchronized round dates. These documentation files all date rounds 31/32 on July 20, 2026, but PR #52 and this review are dated July 19, 2026. Confirm that July 20 is intentional; otherwise update every listed entry consistently.

  • BUILDING.md#L1-L2: correct the round-32 date if July 20 is not intended.
  • BUILDING.md#L53-L53: correct the round-31 date if July 20 is not intended.
  • Manual/README.license#L1-L2: correct the round-32 date if July 20 is not intended.
  • Manual/README.license#L12-L13: correct the round-31 date if July 20 is not intended.
  • Manual/Regalia-v1.2.3-manual-en.html#L543-L544: correct the round-31/32 dates if July 20 is not intended.
  • Manual/Regalia-v1.2.3-manual-zh.html#L543-L544: correct the round-31/32 dates if July 20 is not intended.
  • src/main/java/com/Regalia/README.license#L1-L2: correct the round-32 date if July 20 is not intended.
  • src/main/java/com/Regalia/README.license#L37-L38: correct the round-31 date if July 20 is not intended.
  • src/main/cpp/README.license#L1-L2: correct the round-32 date if July 20 is not intended.
  • src/main/cpp/README.license#L10-L11: correct the round-31 date if July 20 is not intended.
🧰 Tools
🪛 markdownlint-cli2 (0.23.0)

[warning] 1-1: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

📍 Affects 6 files
  • BUILDING.md#L1-L2 (this comment)
  • BUILDING.md#L53-L53
  • Manual/README.license#L1-L2
  • Manual/README.license#L12-L13
  • Manual/Regalia-v1.2.3-manual-en.html#L543-L544
  • Manual/Regalia-v1.2.3-manual-zh.html#L543-L544
  • src/main/java/com/Regalia/README.license#L1-L2
  • src/main/java/com/Regalia/README.license#L37-L38
  • src/main/cpp/README.license#L1-L2
  • src/main/cpp/README.license#L10-L11
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@BUILDING.md` around lines 1 - 2, Confirm July 20 is not intentional against
the review date, then align all round-31/32 documentation dates to July 19,
2026: update BUILDING.md lines 1-2 and 53, Manual/README.license lines 1-2 and
12-13, both Manual/Regalia-v1.2.3-manual-en.html and
Manual/Regalia-v1.2.3-manual-zh.html lines 543-544,
src/main/java/com/Regalia/README.license lines 1-2 and 37-38, and
src/main/cpp/README.license lines 1-2 and 10-11 consistently.
Manual/README.license (1)

1-11: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Refresh the “current” manual filenames.

The new v1.2.3 entries are present at the top, but Lines 400-406 still identify the v1.2.1 manuals as current. Update that classification block to v1.2.3 or explicitly mark v1.2.1 as historical.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Manual/README.license` around lines 1 - 11, Update the current-manual
classification block in README.license to identify the v1.2.3 Chinese and
English manuals as current, replacing the stale v1.2.1 references;
alternatively, explicitly label the v1.2.1 manuals as historical.
Manual/Regalia-v1.2.3-manual-en.html (1)

543-544: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Correct the round-32 site count. Both manuals say there are 13 additional timestamp sites, but their own breakdown is 11 in StockfishNative.java, 2 in EngineHealthMonitor.java, and 1 in ChessWebViewClient.java—14 total.

  • Manual/Regalia-v1.2.3-manual-en.html#L543-L544: change 13 to 14 or correct one component count.
  • Manual/Regalia-v1.2.3-manual-zh.html#L543-L544: make the same count correction in the Chinese entry.
📍 Affects 2 files
  • Manual/Regalia-v1.2.3-manual-en.html#L543-L544 (this comment)
  • Manual/Regalia-v1.2.3-manual-zh.html#L543-L544
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Manual/Regalia-v1.2.3-manual-en.html` around lines 543 - 544, The round-32
timestamp-site total is inconsistent with its breakdown: 11 StockfishNative
sites plus 2 EngineHealthMonitor sites plus 1 ChessWebViewClient site equals 14.
Update both Manual/Regalia-v1.2.3-manual-en.html lines 543-544 and
Manual/Regalia-v1.2.3-manual-zh.html lines 543-544 to state 14 additional sites,
leaving the component counts unchanged.
NOTICE (1)

31-35: 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Correct the inconsistent historical AGPL/GPL labels.

These entries contradict the canonical classifications later in NOTICE:

  • Lines 31-35 and 617-618: StatsActivity.java should be GPL v3, not AGPL v3.
  • Lines 174-176: state-store.js should be AGPL v3, not GPL v3.
  • Lines 466-469: HapticManager.java should be GPL v3, not AGPL v3.

Also applies to: 174-176, 466-469, 617-618

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@NOTICE` around lines 31 - 35, Correct the license labels in NOTICE for the
listed entries: change StatsActivity.java and HapticManager.java from AGPL v3 to
GPL v3, and change state-store.js from GPL v3 to AGPL v3. Update all referenced
duplicate or historical classification entries while leaving unrelated
API/Android comments unchanged.
README.md (2)

1-1: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Align all Round-31/32 timestamps with the actual release dates. These entries are dated July 20, 2026, although this review is dated July 19, 2026.

  • README.md#L1-L1: replace or defer the Round-32 July 20 date.
  • README.md#L89-L89: replace or defer the Round-31 July 20 date.
  • PRIVACY.md#L1-L1: replace or defer the Round-32 July 20 date.
  • PRIVACY.md#L28-L28: replace or defer the Round-31 July 20 date.
  • assets/README.license#L1-L1: replace or defer the Round-32 July 20 date.
  • assets/README.license#L7-L7: replace or defer the Round-31 July 20 date.
  • src/main/README.license#L1-L1: replace or defer the Round-32 July 20 date.
  • src/main/README.license#L7-L7: replace or defer the Round-31 July 20 date.
  • src/main/assets/chess.src/README.license#L1-L1: replace or defer the Round-32 July 20 date.
  • src/main/assets/chess.src/README.license#L29-L29: replace or defer the Round-31 July 20 date.
🧰 Tools
🪛 markdownlint-cli2 (0.23.0)

[warning] 1-1: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

📍 Affects 5 files
  • README.md#L1-L1 (this comment)
  • README.md#L89-L89
  • PRIVACY.md#L1-L1
  • PRIVACY.md#L28-L28
  • assets/README.license#L1-L1
  • assets/README.license#L7-L7
  • src/main/README.license#L1-L1
  • src/main/README.license#L7-L7
  • src/main/assets/chess.src/README.license#L1-L1
  • src/main/assets/chess.src/README.license#L29-L29
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` at line 1, Align all Round-31 and Round-32 dates with the actual
release date by replacing or deferring the July 20, 2026 dates in README.md
lines 1 and 89, PRIVACY.md lines 1 and 28, assets/README.license lines 1 and 7,
src/main/README.license lines 1 and 7, and
src/main/assets/chess.src/README.license lines 1 and 29.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Keep the new changelog preambles markdownlint-clean.

  • README.md#L1-L1: add or move a top-level heading before the changelog.
  • README.md#L9-L9: add blank lines around the heading.
  • README.md#L39-L39: add blank lines around the heading.
  • README.md#L60-L60: add blank lines around the heading.
  • README.md#L66-L66: add blank lines around the heading.
  • README.md#L79-L79: add blank lines around the heading.
  • README.md#L84-L84: remove spaces inside emphasis markers.
  • README.md#L96-L96: add blank lines around the heading.
  • README.md#L111-L111: add blank lines around the heading.
  • README.md#L125-L125: add blank lines around the heading.
  • README.md#L144-L144: add blank lines around the heading.
  • README.md#L153-L153: add blank lines around the heading.
  • README.md#L165-L165: add blank lines around the heading.
  • PRIVACY.md#L1-L1: place the changelog under the existing top-level privacy-policy heading.
🧰 Tools
🪛 markdownlint-cli2 (0.23.0)

[warning] 1-1: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

📍 Affects 2 files
  • README.md#L1-L1 (this comment)
  • README.md#L9-L9
  • README.md#L39-L39
  • README.md#L60-L60
  • README.md#L66-L66
  • README.md#L79-L79
  • README.md#L84-L84
  • README.md#L96-L96
  • README.md#L111-L111
  • README.md#L125-L125
  • README.md#L144-L144
  • README.md#L153-L153
  • README.md#L165-L165
  • PRIVACY.md#L1-L1
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` at line 1, Keep the changelog preambles markdownlint-clean: in
README.md at lines 1-1, 9-9, 39-39, 60-60, 66-66, 79-79, 84-84, 96-96, 111-111,
125-125, 144-144, 153-153, and 165-165, add or move a top-level heading before
the changelog, add blank lines around each heading, and remove spaces inside
emphasis markers at 84-84; in PRIVACY.md at 1-1, place the changelog beneath the
existing top-level privacy-policy heading.

Source: Linters/SAST tools


6-7: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Reconcile the Round-32 site count.

The entry says “13 additional sites,” but the breakdown totals 14: 11 in StockfishNative.java, 2 in EngineHealthMonitor.java, and 1 in ChessWebViewClient.java. Correct either the total or the per-file breakdown so the audit is internally consistent.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 6 - 7, Reconcile the Round-32 site count in README.md
so the stated total matches the per-file breakdown: 11 sites in
StockfishNative.java, 2 in EngineHealthMonitor.java, and 1 in
ChessWebViewClient.java. Update either the “13 additional sites” total or the
breakdown, preserving the accurate audit counts.
src/main/assets/chess.html (1)

18687-18737: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Locate the source-of-truth definitions so the fix lands where it persists
rg -n --pcre2 'function\s+(_renderRvArrowSvg|_triggerPendingPostBatchActions)\s*\(' src/main/assets/chess.src

Repository: YDW99/Regalia

Length of output: 398


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Confirm the bundle is generated from chess.src and inspect the source definitions.
rg -n --pcre2 'build-chess\.py|chess\.src|chess\.html' -g 'build-chess.py' -g '*.py' -g '*.md' -g '*.txt' .
printf '\n---\n'
sed -n '2440,2505p' src/main/assets/chess.src/ui.js
printf '\n---\n'
sed -n '5600,5665p' src/main/assets/chess.src/ui.js

Repository: YDW99/Regalia

Length of output: 50369


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Definitions:\n'
rg -n --pcre2 'function\s+(_renderRvArrowSvg|_triggerPendingPostBatchActions)\s*\(' src/main/assets/chess.src/ui.js
printf '\nModule list:\n'
sed -n '130,150p' build-chess.py
printf '\nSource tree files matching ui-*.js:\n'
fd -a 'ui*.js' src/main/assets/chess.src

Repository: YDW99/Regalia

Length of output: 449


Move the SonarCloud fix to src/main/assets/chess.src/ui.js
_renderRvArrowSvg and _triggerPendingPostBatchActions are defined there; chess.html is regenerated from chess.src, so reducing their complexity in the source module is the durable fix.

🧰 Tools
🪛 GitHub Check: SonarCloud Code Analysis

[failure] 18687-18687: Refactor this function to reduce its Cognitive Complexity from 22 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ94ft0bq4IVm24_IAra&open=AZ94ft0bq4IVm24_IAra&pullRequest=52

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/assets/chess.html` around lines 18687 - 18737, Apply the SonarCloud
complexity reduction to _renderRvArrowSvg and _triggerPendingPostBatchActions in
the chess.src/ui.js source module rather than the generated chess.html output.
Preserve their existing behavior, then regenerate chess.html from the source so
the generated artifact reflects the durable fix.

Source: Linters/SAST tools

src/main/assets/chess.src/game-logic.js (1)

2511-2537: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

_scanWinnerMaterial fails the SonarCloud cognitive-complexity gate (16 > 15) in both the source module and its generated bundle copy. The root cause is the single source definition in game-logic.js; chess.html is the build-chess.py output of it, so one fix in source resolves both.

  • src/main/assets/chess.src/game-logic.js#L2511-L2537: reduce complexity, e.g. extract the bishop-count + parity accumulation (the case'bishop' block) into a small helper, keeping counts otherwise inline.
  • src/main/assets/chess.html#L3828-L3854: no manual edit — rebuild the bundle after fixing the source so this generated copy inherits the reduction.
🧰 Tools
🪛 GitHub Check: SonarCloud Code Analysis

[failure] 2511-2511: Refactor this function to reduce its Cognitive Complexity from 16 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ98cQgTrIstupHXrzvm&open=AZ98cQgTrIstupHXrzvm&pullRequest=52

📍 Affects 2 files
  • src/main/assets/chess.src/game-logic.js#L2511-L2537 (this comment)
  • src/main/assets/chess.html#L3828-L3854
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/assets/chess.src/game-logic.js` around lines 2511 - 2537, Reduce
cognitive complexity in _scanWinnerMaterial by extracting the bishop count and
bishopParity update from the case'bishop' branch into a small helper, while
preserving all existing material counts and parity behavior. Apply the source
change in src/main/assets/chess.src/game-logic.js at lines 2511-2537, then
rebuild so src/main/assets/chess.html lines 3828-3854 receives the generated
update; do not edit the bundle manually.

Source: Linters/SAST tools

src/main/assets/README.license (1)

1-1: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use release-history dates that are not in the future.

Round-31 and Round-32 are dated July 20, 2026, while this review is dated July 19, 2026. Use the actual commit/release dates, or defer these entries until July 20; the same future date appears in the other release-history files.

Also applies to: 7-7

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/assets/README.license` at line 1, Update the release-history entry
for v1.2.3 round-32 in the assets README to use the actual release/commit date,
or defer the entry until July 20, 2026; apply the same correction to the
corresponding Round-31 and Round-32 entries in the other release-history files.
worklog.md (2)

21-27: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Reconcile the unresolved-issue counts.

The text claims 11 items, then describes 9 CodeRabbit + 2 documentation + 2 PR blockers, while the “真实缺陷” section contains 10 numbered entries. Update the totals and grouping so the audit record is arithmetically consistent.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@worklog.md` around lines 21 - 27, The unresolved-issue totals and category
breakdown in “PR52_Unresolved_Issues_Latest.docx” are inconsistent with the ten
entries under “真实缺陷”. Reconcile the stated overall count and the CodeRabbit,
documentation, and PR-blocker grouping so all totals add up and match the
documented entries.

67-67: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use code spans for underscored identifiers.

Markdownlint MD037 is triggered because identifiers such as _evalOrMate and _scanWinnerMaterial are parsed as emphasis. Wrap these identifiers in backticks.

🧰 Tools
🪛 markdownlint-cli2 (0.23.0)

[warning] 67-67: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@worklog.md` at line 67, Update the worklog entry to wrap underscored
identifiers such as _evalOrMate, _scanWinnerMaterial, _bishopParityIsUniform,
and _stabilizationLock in Markdown code spans, preventing them from being parsed
as emphasis while preserving the surrounding text.

Source: Linters/SAST tools

YDW99 and others added 2 commits July 20, 2026 06:59
Signed-off-by: D.W. Yang <1151712579@qq.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (6)
src/main/java/com/Regalia/StockfishNative.java (1)

3058-3081: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Close the post-check shutdown race.

A shutdown can occur after the generation check but before shutdownRequested = false; its true value is then overwritten and a new engine can start after exit. shutdownNow() may interrupt this task too, but the interruption is restored and execution continues.

Serialize generation validation and clearing shutdownRequested with the same lifecycle lock used by shutdown(), or revalidate atomically immediately before the reset/submission.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/Regalia/StockfishNative.java` around lines 3058 - 3081,
Close the race in the restart path between the generation check and resetting
shutdownRequested: use the same lifecycle lock as shutdown() to atomically
revalidate _lifecycleGeneration and clear shutdownRequested, or perform an
equivalent atomic revalidation immediately before the reset and executor
submission. Ensure a concurrent shutdown cannot be overwritten and allow the
restart task to abort after interruption when shutdownNow() has invalidated the
restart.
README.md (2)

484-484: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Add HapticManager.java to the GPL v3 inventory.

The round-33 documentation says HapticManager.java was added to the canonical GPL list, but this README’s GPL v3 file list only adds JsBridgeGateway.java and still omits HapticManager.java. Keep the public license inventory consistent with the canonical list.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` at line 484, Add HapticManager.java to the README’s GPL v3 file
inventory alongside JsBridgeGateway.java, preserving the existing formatting and
ensuring the documented list matches the canonical GPL list.

450-461: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Align the README’s CMake prerequisite with the pinned toolchain.

The changed project tree documents CMake 3.31.6+, but the build prerequisites at Line 340 still instruct contributors to install CMake 3.22.1. BUILDING.md now pins 3.31.6, so following this README can recreate the CMake re-run failure the PR documents. Update the prerequisite and install instructions to 3.31.6.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 450 - 461, Update the README build prerequisite and
installation instructions for CMake from 3.22.1 to the pinned version 3.31.6,
keeping the existing prerequisite structure and commands otherwise unchanged.
Manual/Regalia-v1.2.3-manual-en.html (1)

724-729: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Make the embedded build example match build-chess.py, not just its module list.

The actual script replaces /* __MODULE_SCRIPTS__ */, while both manual examples still replace /*__JS__*/; copying either example leaves the real template placeholder untouched. Update the placeholder and keep the example’s export-stripping behavior aligned with build-chess.py.

  • Manual/Regalia-v1.2.3-manual-en.html#L724-L729: update the English example’s placeholder and replacement logic.
  • Manual/Regalia-v1.2.3-manual-zh.html#L719-L724: apply the same correction to the Chinese example.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Manual/Regalia-v1.2.3-manual-en.html` around lines 724 - 729, Update the
embedded build examples in Manual/Regalia-v1.2.3-manual-en.html lines 724-729
and Manual/Regalia-v1.2.3-manual-zh.html lines 719-724 to replace the actual /*
__MODULE_SCRIPTS__ */ template placeholder, and align their export-stripping
replacement logic with build-chess.py. Apply the same correction to both
language versions.
NOTICE (1)

109-113: 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Synchronize historical license labels with the canonical classifications.

These historical entries contradict the canonical list and can mislead redistribution/compliance decisions:

  • NOTICE#L109-L113: change StatsActivity.java (AGPL v3) to StatsActivity.java (GPL v3).
  • NOTICE#L252-L254: change state-store.js (GPL v3) to state-store.js (AGPL v3).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@NOTICE` around lines 109 - 113, Update the historical license labels in
NOTICE: change StatsActivity.java from AGPL v3 to GPL v3 at lines 109-113, and
change state-store.js from GPL v3 to AGPL v3 at lines 252-254, keeping all other
entries unchanged.
src/main/assets/README.license (1)

153-154: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Resolve the contradictory stats.html provenance statement.

These entries simultaneously describe stats.html as “GPL v3 (DroidFish-derived)” and “not derived from DroidFish or Stockfish.” The current summary at Lines [404]-[408] identifies its PGN parser as DroidFish-derived; keep one authoritative provenance statement for release-license compliance.

Also applies to: 168-169, 179-180

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/assets/README.license` around lines 153 - 154, Resolve the
contradictory provenance wording for stats.html in the license classification
and related entries: retain one authoritative statement consistent with the PGN
parser’s DroidFish-derived origin, and remove or revise the conflicting claim
that it is not derived from DroidFish or Stockfish. Apply the same correction to
all referenced stats.html provenance entries.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@BUILDING.md`:
- Line 1: Add or promote a document-level title before the Round-33
release-history section in BUILDING.md and PRIVACY.md. In README.md, add the
top-level release-history heading and insert blank lines around the headings at
lines 8, 40, 63, 79, and 91. Apply the requested heading hierarchy and spacing
consistently across BUILDING.md lines 1-1, README.md lines 1-91, and PRIVACY.md
lines 1-1.

In `@Manual/README.license`:
- Around line 1-14: Update the current-manual classification records in
README.license to replace the v1.2.1 manual filenames and version descriptions
with Regalia-v1.2.3-manual-zh.html and Regalia-v1.2.3-manual-en.html, matching
the newly distributed entries while preserving their AGPL v3 classification.

In `@NOTICE`:
- Around line 1474-1483: Update the preceding Phase-73 extraction summary to
list only the four implemented manager classes. Remove UciProtocolHandler.java
and EngineConfigManager.java from the implemented-files list, keeping their
separate “NEVER CREATED” historical entries intact.

In `@src/main/java/com/Regalia/MainActivity.java`:
- Around line 376-386: Update the Stockfish initialization retry flow around
stockfishEngine and initRetryCount so constructor failures increment the retry
count and reschedule initialization while the count remains below
INIT_MAX_RETRIES. Once the cap is reached, invoke the existing Log.e and
showFallbackUI fallback instead of stopping with a null engine.

In `@src/main/java/com/Regalia/README.license`:
- Around line 48-54: Normalize the remaining historical StatsActivity.java
license labels in the README.license content around the existing entries so they
consistently identify StatsActivity.java as GPL v3, or explicitly document any
intentional exceptions; ensure no contradictory AGPL v3 labels remain.

In `@worklog.md`:
- Around line 42-48: Update the ordered list in the worklog subsection
containing the state-store.js, eco-data.js, pgn-standard.js, and README.md
entries so its markers are sequentially numbered 1 through 4, preserving the
existing item content and order.
- Around line 104-109: Replace the machine-specific absolute source path in the
release log entries with a repository-relative path or only the relevant
tool/artifact name. Update all corresponding entries, including the additional
locations, while preserving the recorded hashes and deployment/APK artifact
paths.
- Around line 20-30: Correct the inconsistent timestamp-fix count in the
headline and per-file breakdown: make the total match the enumerated
StockfishNative, EngineHealthMonitor, and ChessWebViewClient changes (11 + 2 +
1), while preserving the existing descriptions.

---

Outside diff comments:
In `@Manual/Regalia-v1.2.3-manual-en.html`:
- Around line 724-729: Update the embedded build examples in
Manual/Regalia-v1.2.3-manual-en.html lines 724-729 and
Manual/Regalia-v1.2.3-manual-zh.html lines 719-724 to replace the actual /*
__MODULE_SCRIPTS__ */ template placeholder, and align their export-stripping
replacement logic with build-chess.py. Apply the same correction to both
language versions.

In `@NOTICE`:
- Around line 109-113: Update the historical license labels in NOTICE: change
StatsActivity.java from AGPL v3 to GPL v3 at lines 109-113, and change
state-store.js from GPL v3 to AGPL v3 at lines 252-254, keeping all other
entries unchanged.

In `@README.md`:
- Line 484: Add HapticManager.java to the README’s GPL v3 file inventory
alongside JsBridgeGateway.java, preserving the existing formatting and ensuring
the documented list matches the canonical GPL list.
- Around line 450-461: Update the README build prerequisite and installation
instructions for CMake from 3.22.1 to the pinned version 3.31.6, keeping the
existing prerequisite structure and commands otherwise unchanged.

In `@src/main/assets/README.license`:
- Around line 153-154: Resolve the contradictory provenance wording for
stats.html in the license classification and related entries: retain one
authoritative statement consistent with the PGN parser’s DroidFish-derived
origin, and remove or revise the conflicting claim that it is not derived from
DroidFish or Stockfish. Apply the same correction to all referenced stats.html
provenance entries.

In `@src/main/java/com/Regalia/StockfishNative.java`:
- Around line 3058-3081: Close the race in the restart path between the
generation check and resetting shutdownRequested: use the same lifecycle lock as
shutdown() to atomically revalidate _lifecycleGeneration and clear
shutdownRequested, or perform an equivalent atomic revalidation immediately
before the reset and executor submission. Ensure a concurrent shutdown cannot be
overwritten and allow the restart task to abort after interruption when
shutdownNow() has invalidated the restart.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: d0c2f3aa-d3d7-4415-a6ed-652c686c349c

📥 Commits

Reviewing files that changed from the base of the PR and between 406b8a1 and 49f6987.

⛔ Files ignored due to path filters (1)
  • LICENSE&NOTICE.zip is excluded by !**/*.zip
📒 Files selected for processing (19)
  • BUILDING.md
  • Manual/README.license
  • Manual/Regalia-v1.2.3-manual-en.html
  • Manual/Regalia-v1.2.3-manual-zh.html
  • NOTICE
  • PRIVACY.md
  • README.md
  • assets/README.license
  • src/main/README.license
  • src/main/assets/README.license
  • src/main/assets/chess.src/README.license
  • src/main/cpp/README.license
  • src/main/java/com/Regalia/ChessWebViewClient.java
  • src/main/java/com/Regalia/HapticManager.java
  • src/main/java/com/Regalia/MainActivity.java
  • src/main/java/com/Regalia/README.license
  • src/main/java/com/Regalia/StockfishNative.java
  • src/main/res/README.license
  • worklog.md
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: semgrep-cloud-platform/scan
🧰 Additional context used
🪛 GitHub Check: SonarCloud Code Analysis
src/main/java/com/Regalia/ChessWebViewClient.java

[warning] 91-91: This block of commented-out lines of code should be removed.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ98nH4Wq4IVm24_kXC2&open=AZ98nH4Wq4IVm24_kXC2&pullRequest=52

src/main/java/com/Regalia/StockfishNative.java

[warning] 205-205: Rename this field "_lifecycleGeneration" to match the regular expression '^[a-z][a-zA-Z0-9]*$'.

See more on https://sonarcloud.io/project/issues?id=YDW99_Regalia&issues=AZ98nH_kq4IVm24_kXC3&open=AZ98nH_kq4IVm24_kXC3&pullRequest=52

🪛 HTMLHint (1.9.2)
Manual/Regalia-v1.2.3-manual-en.html

[error] 543-543: Special characters must be escaped : [ > ].

(spec-char-escape)


[error] 543-543: Special characters must be escaped : [ > ].

(spec-char-escape)

Manual/Regalia-v1.2.3-manual-zh.html

[error] 543-543: Special characters must be escaped : [ > ].

(spec-char-escape)


[error] 543-543: Special characters must be escaped : [ > ].

(spec-char-escape)

🪛 markdownlint-cli2 (0.23.0)
worklog.md

[warning] 42-42: Ordered list item prefix
Expected: 1; Actual: 3; Style: 1/2/3

(MD029, ol-prefix)


[warning] 44-44: Ordered list item prefix
Expected: 2; Actual: 4; Style: 1/2/3

(MD029, ol-prefix)


[warning] 46-46: Ordered list item prefix
Expected: 3; Actual: 5; Style: 1/2/3

(MD029, ol-prefix)


[warning] 48-48: Ordered list item prefix
Expected: 4; Actual: 6; Style: 1/2/3

(MD029, ol-prefix)

PRIVACY.md

[warning] 1-1: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

README.md

[warning] 1-1: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)


[warning] 8-8: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 40-40: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 63-63: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 79-79: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 91-91: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)

BUILDING.md

[warning] 1-1: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

🔇 Additional comments (20)
README.md (2)

675-677: Duplicate of the existing release-signing continuity finding.

This history still documents a regenerated release certificate that rejects upgrades over older installs. The signing certificate must remain stable; documenting the mismatch does not resolve the release-blocking compatibility problem.


101-274: LGTM!

Also applies to: 379-381, 395-395, 405-406, 432-435, 537-674, 678-776

BUILDING.md (1)

3-182: LGTM!

Also applies to: 206-244, 294-314, 315-614, 615-757, 793-962, 1735-1735

Manual/README.license (1)

15-195: LGTM!

Manual/Regalia-v1.2.3-manual-en.html (2)

677-711: LGTM!

Also applies to: 1857-1857, 1900-1900, 1917-1917, 1929-1929


543-543: 📐 Maintainability & Code Quality

No escaping change needed for these comparisons. Literal > / >= in paragraph text is valid HTML, so leave both manuals as-is.

			> Likely an incorrect or invalid review comment.
Manual/Regalia-v1.2.3-manual-zh.html (1)

675-706: LGTM!

Also applies to: 1877-1877, 1920-1920, 1937-1937, 1949-1949, 1982-1982

PRIVACY.md (1)

3-86: LGTM!

Also applies to: 143-220, 342-342, 373-408

NOTICE (2)

1-6: 📐 Maintainability & Code Quality

Confirm the changelog date basis before merging.

Both Round-33 and Round-32 are dated July 20, 2026, while the PR context is dated July 19, 2026. If these are Asia/Shanghai-local dates, state that consistently; otherwise this NOTICE advertises future-dated release and verification claims.

Also applies to: 79-85


860-860: LGTM!

Also applies to: 1519-1524, 1540-1554, 2162-2162, 8151-8151

src/main/java/com/Regalia/README.license (2)

377-377: LGTM!

Also applies to: 511-511, 536-536, 597-597, 721-721, 1289-1289, 1313-1313, 1468-1468, 1625-1625, 1635-1635, 1647-1647, 1658-1658


1-2: 📐 Maintainability & Code Quality

No changelog metadata fix is needed. The round-33 / 2026.7.20 entry matches the file’s existing changelog pattern, and the version line is unchanged.

			> Likely an incorrect or invalid review comment.
assets/README.license (1)

1-127: LGTM!

src/main/README.license (1)

1-130: LGTM!

Also applies to: 355-364, 583-583

src/main/assets/README.license (1)

1-152: LGTM!

Also applies to: 155-167, 170-178, 181-190, 207-207, 224-224, 240-240, 315-315, 325-325, 337-337, 349-349, 966-974

src/main/assets/chess.src/README.license (1)

1-71: LGTM!

Also applies to: 2029-2029, 2749-2749, 2898-2898, 2960-2960, 3202-3202, 3286-3286, 3715-3715, 3735-3735, 3762-3762, 3781-3785, 3796-3796

src/main/cpp/README.license (1)

1-119: LGTM!

src/main/res/README.license (1)

1-112: LGTM!

Also applies to: 268-273

worklog.md (2)

1-5: 📐 Maintainability & Code Quality

Verify the release date before merging.

The new entry is dated July 20, 2026, while the supplied PR/context date is July 19, 2026. Confirm that July 20 is an intentional planned release date; otherwise synchronize this log and the matching documentation headers to the actual completion date.


7-19: LGTM!

Also applies to: 31-41, 49-103, 111-134, 156-161

Comment thread BUILDING.md
@@ -1,3 +1,185 @@
## Round-33 build notes (2026-07-20)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fix the Markdown heading hierarchy in the release-history blocks.

All three files begin their changed release-history content with an ## heading instead of a document-level heading; README.md also lacks blank lines around the new subheadings. Add a proper top-level title and normalize blank lines around headings.

  • BUILDING.md#L1-L1: add or promote the document title before the round-33 section.
  • README.md#L1-L91: add the top-level release-history heading and blank lines around the Lines 8, 40, 63, 79, and 91 headings.
  • PRIVACY.md#L1-L1: add or promote the document title before the round-33 section.
🧰 Tools
🪛 markdownlint-cli2 (0.23.0)

[warning] 1-1: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

📍 Affects 3 files
  • BUILDING.md#L1-L1 (this comment)
  • README.md#L1-L91
  • PRIVACY.md#L1-L1
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@BUILDING.md` at line 1, Add or promote a document-level title before the
Round-33 release-history section in BUILDING.md and PRIVACY.md. In README.md,
add the top-level release-history heading and insert blank lines around the
headings at lines 8, 40, 63, 79, and 91. Apply the requested heading hierarchy
and spacing consistently across BUILDING.md lines 1-1, README.md lines 1-91, and
PRIVACY.md lines 1-1.

Source: Linters/SAST tools

Comment thread Manual/README.license
Comment on lines +1 to +14
v1.2.3 round-33 (2026.7.20) — Manuals updated with round-33 changelog entry + UI architecture diagram fix:
- Version: versionCode=123, versionName="1.2.3" (unchanged — fix round).
- Regalia-v1.2.3-manual-zh.html: (1) UI architecture diagram updated to
show ui-gameflow.js + ui-interactions.js as separate modules alongside
ui.js (round-17 God Class split was not reflected in the diagram — the
build script below the diagram already listed the new modules, creating
an inconsistency). (2) Round-33 changelog entry prepended to the
changelog section (newest-first ordering preserved).
- Regalia-v1.2.3-manual-en.html: equivalent English updates.
- Both manuals: content is parallel (non-machine-translated); only the
UI architecture diagram + changelog section changed.
- License classification: both manuals are AGPL v3 (original work of
the Regalia project, not derived from DroidFish or other GPL projects).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Update the current-manual license inventory to v1.2.3.

The new entries identify Regalia-v1.2.3-manual-{zh,en}.html as the current manuals, but the classification block later in this file still lists the v1.2.1 filenames as current. Synchronize those records and version descriptions with the files being distributed.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Manual/README.license` around lines 1 - 14, Update the current-manual
classification records in README.license to replace the v1.2.1 manual filenames
and version descriptions with Regalia-v1.2.3-manual-zh.html and
Regalia-v1.2.3-manual-en.html, matching the newly distributed entries while
preserving their AGPL v3 classification.

Comment thread NOTICE
Comment thread src/main/java/com/Regalia/MainActivity.java Outdated
Comment thread src/main/java/com/Regalia/README.license
Comment thread worklog.md Outdated
Comment thread worklog.md
Comment thread worklog.md Outdated
YDW99 and others added 4 commits July 20, 2026 09:37
Signed-off-by: D.W. Yang <1151712579@qq.com>
Signed-off-by: D.W. Yang <1151712579@qq.com>
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
17.2% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

@gitar-bot

gitar-bot Bot commented Jul 20, 2026

Copy link
Copy Markdown
Code Review ✅ Approved 2 resolved / 2 findings

Engine stability improvements resolve race conditions in Stockfish shutdown and correct the initGameClocks clobbering issue. Documentation for licensing and prerequisites has also been standardized.

✅ 2 resolved
Bug: _restoreClocks clobbers restored clock values via initGameClocks()

📄 src/main/assets/chess.src/ui-interactions.js:92-106 📄 src/main/assets/chess.src/ui-gameflow.js:226-240
In _restoreClocks, the snapshot's per-side remainingSec/displayRemainingSec are written into gameClocks.white/gameClocks.black (ui-interactions.js:92-96), but the call to initGameClocks() at ui-interactions.js:105 then rebuilds the entire gameClocks object from dlgTimeControl, setting remainingSec:base, displayRemainingSec:base for both sides (ui-gameflow.js:235-242). This discards the just-restored values, so undo/redo in a timed game resets both clocks to the full base time instead of the recorded remaining time — defeating the exact round-23/round-28 feature this PR audited. (The comment claiming initGameClocks merely restarts the interval is incorrect; it re-initializes clock state.) Fix by restarting only the tick timer instead of calling initGameClocks().

Bug: null-engine fallback branch is unreachable in scheduleInitRetry

📄 src/main/java/com/Regalia/MainActivity.java:356-370
The new else if (stockfishEngine == null && initRetryCount >= INIT_MAX_RETRIES) branch (MainActivity.java:376) can never fire in the scenario it targets. initRetryCount++ only runs inside the first branch, which is guarded by stockfishEngine != null (line 347-348). When the StockfishNative constructor persistently fails, stockfishEngine stays null on every retry, so initRetryCount never advances past 0 and initRetryCount >= INIT_MAX_RETRIES is always false. Additionally, the null path performs no scheduleInitRetry() reschedule, so the runnable fires only once and then stops silently. The result is that the fallback UI still never appears when the constructor persistently fails — the exact bug (#4.1.3) the change claims to fix. Fix: track recreation attempts with a counter that increments on the null path too (or show the fallback after the first failed recreation), and reschedule the null case until that limit is reached.

Options

Auto-apply is off → Gitar will not commit updates to this branch.
Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Auto-apply Compact
gitar auto-apply:on         
gitar display:verbose         

Important

Your trial ends in 5 days — upgrade now to keep code review, CI analysis, auto-apply, custom automations, and more.

Was this helpful? React with 👍 / 👎 | Gitar

@github-actions

Copy link
Copy Markdown
Contributor

This pull request has been automatically marked as stale because it has not had any activity for 30 days.
It will be closed in 7 days if no further activity occurs.

Please update the PR or comment to keep it open.
此 Pull Request 因 30 天无活动已被自动标记为过期。如 7 天内无进一步活动将被关闭。

@github-actions github-actions Bot added the stale label Aug 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants