From fb36c0f3ee0d8722809738124adc5b04258da929 Mon Sep 17 00:00:00 2001 From: Zen0space Date: Tue, 10 Mar 2026 09:06:39 +0800 Subject: [PATCH 1/2] fix: align display and merge to our xp.json field names - display.js: fix xpToNextLevel (was xpRequired), align all 4 stat blocks to actual fields - display.js: security/code-review use issuesFixed, docs uses docsWritten, testing uses testsWritten - display.js: remove totalReviews, totalTests, totalAudits, patternsAdded (not in our xp.json) - merge.js: fix preserveFields list to match our xp.json fields - merge.js: remove xpTable assignment (field removed from xp.json) - merge.js: fix level recalculation to use xpToNextLevel (was xpRequired) - merge.js: fix getSmartMergePreserveInfo labels to match our fields --- src/display.js | 58 ++++++++++++++++++++++++-------------------------- src/merge.js | 29 ++++++++++++++----------- 2 files changed, 44 insertions(+), 43 deletions(-) diff --git a/src/display.js b/src/display.js index 84fc981..3332355 100644 --- a/src/display.js +++ b/src/display.js @@ -5,52 +5,50 @@ const CATEGORY_CONFIG = { security: { title: 'SECURITY AGENT', getStats: (data) => { - const totalFixed = (data.issuesFixed?.critical || 0) + - (data.issuesFixed?.high || 0) + - (data.issuesFixed?.medium || 0) + + const totalFixed = (data.issuesFixed?.critical || 0) + + (data.issuesFixed?.high || 0) + + (data.issuesFixed?.medium || 0) + (data.issuesFixed?.low || 0); return [ { label: 'Issues Fixed', value: totalFixed }, - { label: 'Critical', value: data.issuesFixed?.critical || 0 }, - { label: 'High', value: data.issuesFixed?.high || 0 }, - { label: 'Medium', value: data.issuesFixed?.medium || 0 }, - { label: 'Low', value: data.issuesFixed?.low || 0 }, - { label: 'Audits Done', value: data.totalAudits || 0 }, - { label: 'Patterns Added', value: data.patternsAdded || 0 } + { label: 'Critical', value: data.issuesFixed?.critical || 0 }, + { label: 'High', value: data.issuesFixed?.high || 0 }, + { label: 'Medium', value: data.issuesFixed?.medium || 0 }, + { label: 'Low', value: data.issuesFixed?.low || 0 }, ]; } }, testing: { title: 'TESTING AGENT', getStats: (data) => [ - { label: 'Tests Written', value: data.totalTests || 0 }, - { label: 'Unit Tests', value: data.testsWritten?.unit || 0 }, - { label: 'Integration', value: data.testsWritten?.integration || 0 }, - { label: 'E2E Tests', value: data.testsWritten?.e2e || 0 }, - { label: 'Tests Fixed', value: data.testsFixed || 0 }, - { label: 'Patterns Added', value: data.patternsAdded || 0 } + { label: 'Unit Tests', value: data.testsWritten?.unit || 0 }, + { label: 'Integration', value: data.testsWritten?.integration || 0 }, + { label: 'E2E Tests', value: data.testsWritten?.e2e || 0 }, + { label: 'Tests Fixed', value: data.testsFixed || 0 }, ] }, 'code-review': { title: 'CODE REVIEW AGENT', - getStats: (data) => [ - { label: 'Total Reviews', value: data.totalReviews || 0 }, - { label: 'Critical Found', value: data.issuesFound?.critical || 0 }, - { label: 'High Found', value: data.issuesFound?.high || 0 }, - { label: 'Medium Found', value: data.issuesFound?.medium || 0 }, - { label: 'Low Found', value: data.issuesFound?.low || 0 }, - { label: 'Patterns Added', value: data.patternsAdded || 0 } - ] + getStats: (data) => { + const totalFixed = (data.issuesFixed?.critical || 0) + + (data.issuesFixed?.high || 0) + + (data.issuesFixed?.medium || 0) + + (data.issuesFixed?.low || 0); + return [ + { label: 'Issues Fixed', value: totalFixed }, + { label: 'Critical', value: data.issuesFixed?.critical || 0 }, + { label: 'High', value: data.issuesFixed?.high || 0 }, + { label: 'Medium', value: data.issuesFixed?.medium || 0 }, + { label: 'Low', value: data.issuesFixed?.low || 0 }, + ]; + } }, docs: { title: 'DOCUMENTATION AGENT', getStats: (data) => [ - { label: 'Total Docs', value: data.totalDocsWritten || 0 }, - { label: 'New Sections', value: data.docsStats?.newSections || 0 }, - { label: 'Improvements', value: data.docsStats?.improvements || 0 }, - { label: 'Code Examples', value: data.docsStats?.codeExamples || 0 }, - { label: 'Tutorials', value: data.docsStats?.tutorials || 0 }, - { label: 'API Docs', value: data.docsStats?.apiDocs || 0 } + { label: 'Sections', value: data.docsWritten?.sections || 0 }, + { label: 'Tutorials', value: data.docsWritten?.tutorials || 0 }, + { label: 'API Docs', value: data.docsWritten?.apiDocs || 0 }, ] } }; @@ -65,7 +63,7 @@ export function progressBar(current, max, width = 16) { export function getNextLevelXp(currentLevel, levelThresholds) { const nextLevel = levelThresholds?.find(t => t.level === currentLevel + 1); - return nextLevel ? nextLevel.xpRequired : null; + return nextLevel ? nextLevel.xpToNextLevel : null; } function line(content) { diff --git a/src/merge.js b/src/merge.js index b0d138c..60d8783 100644 --- a/src/merge.js +++ b/src/merge.js @@ -166,10 +166,12 @@ function compareVersion(v1, v2) { function smartMergeXp(userXp, templateXp) { const preserveFields = [ - 'xp', 'totalTests', 'totalAudits', - 'testsWritten', 'issuesFixed', 'testsFixed', 'patternsAdded', - 'completedSuites', 'completedAudits', 'seenPatterns', 'seenIssues', - 'mistakes', 'mistakeHistory', 'levelHistory' + 'xp', 'level', 'title', + 'testsWritten', 'testsFixed', + 'issuesFixed', + 'docsWritten', + 'seenIssues', 'seenPatterns', + 'mistakes', 'mistakeHistory' ]; let merged = { ...templateXp }; @@ -180,7 +182,6 @@ function smartMergeXp(userXp, templateXp) { } } - merged.xpTable = templateXp.xpTable; merged.levelThresholds = templateXp.levelThresholds; const userXpValue = userXp.xp || 0; @@ -190,7 +191,7 @@ function smartMergeXp(userXp, templateXp) { let newLevel = 1; let newTitle = 'Novice'; for (let i = thresholds.length - 1; i >= 0; i--) { - if (userXpValue >= thresholds[i].xpRequired) { + if (userXpValue >= thresholds[i].xpToNextLevel) { newLevel = thresholds[i].level; newTitle = thresholds[i].title; break; @@ -204,8 +205,9 @@ function smartMergeXp(userXp, templateXp) { function getSmartMergePreserveInfo(userXp, templateXp) { const preserveFields = [ - 'xp', 'level', 'title', 'totalTests', 'totalAudits', - 'testsWritten', 'issuesFixed', 'testsFixed', 'patternsAdded' + 'xp', 'level', 'title', + 'testsWritten', 'testsFixed', + 'issuesFixed', 'docsWritten', ]; const preserved = []; @@ -217,16 +219,17 @@ function getSmartMergePreserveInfo(userXp, templateXp) { preserved.push(`level ${userXp[field]}`); } else if (field === 'title') { preserved.push(`title: ${userXp[field]}`); - } else if (field === 'totalTests') { - preserved.push(`tests: ${userXp[field]}`); - } else if (field === 'testsWritten' && userXp.testsWritten) { + } else if (field === 'testsWritten' && userXp.testsWritten) { const total = (userXp.testsWritten.unit || 0) + (userXp.testsWritten.integration || 0) + (userXp.testsWritten.e2e || 0); if (total > 0) preserved.push(`tests: ${total}`); + } else if (field === 'testsFixed' && userXp.testsFixed > 0) { + preserved.push(`fixed: ${userXp.testsFixed}`); } else if (field === 'issuesFixed' && userXp.issuesFixed) { const total = (userXp.issuesFixed.critical || 0) + (userXp.issuesFixed.high || 0) + (userXp.issuesFixed.medium || 0) + (userXp.issuesFixed.low || 0); if (total > 0) preserved.push(`fixed: ${total}`); - } else if (field === 'patternsAdded' && userXp.patternsAdded > 0) { - preserved.push(`patterns: ${userXp[field]}`); + } else if (field === 'docsWritten' && userXp.docsWritten) { + const total = (userXp.docsWritten.sections || 0) + (userXp.docsWritten.tutorials || 0) + (userXp.docsWritten.apiDocs || 0); + if (total > 0) preserved.push(`docs: ${total}`); } } } From d38e8091c863440734389664c99cec90cfe58986 Mon Sep 17 00:00:00 2001 From: Zen0space Date: Tue, 10 Mar 2026 09:07:43 +0800 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20bump=20to=20v1.3.2=20=E2=80=94=20sta?= =?UTF-8?q?ts=20display=20and=20smart=20merge=20field=20alignment?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- templates/.ocs-version | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 7bb2f4b..9f12377 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ocs-stats", - "version": "1.3.1", + "version": "1.3.2", "description": "OpenCode Skills - One-click installer with gamified XP stats", "type": "module", "bin": { diff --git a/templates/.ocs-version b/templates/.ocs-version index 0b31fda..17aee20 100644 --- a/templates/.ocs-version +++ b/templates/.ocs-version @@ -1,3 +1,4 @@ +1.3.2: Fix stats display and smart merge to use correct xp.json field names 1.3.1: Fix version display showing undefined after update check 1.3.0: Smarter agents — Phase 1/2 system, cumulative levels, no-commit rule, dynamic knowledge base 1.2.6: Smart merge for agent files - preserve user mode/tools