Skip to content

Commit f0c2cf5

Browse files
committed
feat(frontend): add one-click retest execution in learning workbench
1 parent eb06a12 commit f0c2cf5

4 files changed

Lines changed: 82 additions & 1 deletion

File tree

src/frontend/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1429,6 +1429,7 @@ <h3>Learning Workbench</h3>
14291429
<button id="btn-refresh-learning-workbench" class="btn-small">Refresh</button>
14301430
<button id="btn-ingest-focus-node" class="btn-small">Ingest Focus</button>
14311431
<button id="btn-run-learning-session" class="btn-small">Run Session</button>
1432+
<button id="btn-run-retest-session" class="btn-small">Run Retest</button>
14321433
</div>
14331434
<div id="learning-workbench-status" class="workbench-status">Ready.</div>
14341435
<div id="learning-workbench-updated-at" class="workbench-updated-at">Last updated: -</div>

src/frontend/path.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ <h3>Learning Workbench</h3>
8888
<button id="btn-refresh-learning-workbench" class="btn-small">Refresh</button>
8989
<button id="btn-ingest-focus-node" class="btn-small">Ingest Focus</button>
9090
<button id="btn-run-learning-session" class="btn-small">Run Session</button>
91+
<button id="btn-run-retest-session" class="btn-small">Run Retest</button>
9192
</div>
9293
<div id="learning-workbench-status" class="workbench-status">Ready.</div>
9394
<div id="learning-workbench-updated-at" class="workbench-updated-at">Last updated: -</div>

src/frontend/path_app.js

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2115,6 +2115,77 @@ window.pathApp = {
21152115
}
21162116
},
21172117

2118+
runLearningWorkbenchRetestSession: async function() {
2119+
if (this.learningWorkbench.loading) {
2120+
return;
2121+
}
2122+
const userId = this._normalizeLearningWorkbenchUserId(this.learningWorkbench.userId);
2123+
const existingExecution = this.learningWorkbench.sessionExecution || null;
2124+
const retestActions = Array.isArray(existingExecution?.retestPlan?.actions)
2125+
? existingExecution.retestPlan.actions
2126+
: [];
2127+
if (retestActions.length === 0) {
2128+
this._setLearningWorkbenchStatus('No immediate retest actions available. Run a session first.', true);
2129+
return;
2130+
}
2131+
const answersByActionId = this._collectOptionalAnswersForSessionActions(retestActions);
2132+
const answerCount = Object.keys(answersByActionId).length;
2133+
const autoAnalyzeAnswer = answerCount > 0;
2134+
const generatedAt = new Date().toISOString();
2135+
const totalEstimatedMinutes = retestActions.reduce(
2136+
(sum, action) => sum + Number(action?.estimatedMinutes || 0),
2137+
0
2138+
);
2139+
const retestSessionPlan = {
2140+
userId,
2141+
generatedAt,
2142+
actions: retestActions,
2143+
signals: {
2144+
misconceptions: [],
2145+
dueRetrainAtoms: Array.from(new Set(retestActions.map((action) => String(action.atomId || '').trim()))),
2146+
masteryPathTargets: [],
2147+
divergenceTargets: [],
2148+
},
2149+
summary: {
2150+
totalActions: retestActions.length,
2151+
totalEstimatedMinutes,
2152+
evidenceCoverageRatio: 1,
2153+
},
2154+
};
2155+
2156+
this.learningWorkbench.loading = true;
2157+
this._setLearningWorkbenchStatus(`Running immediate retest for ${retestActions.length} actions...`);
2158+
this._renderLearningWorkbenchState();
2159+
try {
2160+
const result = await this._requestLearningApi('/api/knowledge/session/execute', {
2161+
userId,
2162+
sessionPlan: retestSessionPlan,
2163+
actionLimit: retestActions.length,
2164+
answersByActionId,
2165+
autoAnalyzeAnswer,
2166+
autoUpdateMasteryFromAnswer: autoAnalyzeAnswer,
2167+
persistMemory: true,
2168+
memoryLayer: 'session',
2169+
includeRetestPlan: false,
2170+
});
2171+
this.learningWorkbench.sessionExecution = {
2172+
...result,
2173+
receivedAt: new Date().toISOString(),
2174+
};
2175+
const summary = result?.summary || {};
2176+
this._setLearningWorkbenchStatus(
2177+
`Retest execution finished: executed ${Number(summary.executedCount || 0)}/${Number(summary.attemptedActions || 0)}, mastery delta ${Number(summary.averageMasteryDelta || 0).toFixed(3)}.`
2178+
);
2179+
} catch (error) {
2180+
const message = String(error?.message || error || 'Unknown retest execution error');
2181+
this.learningWorkbench.lastError = message;
2182+
this._setLearningWorkbenchStatus(`Retest execution failed: ${message}`, true);
2183+
} finally {
2184+
this.learningWorkbench.loading = false;
2185+
this._renderLearningWorkbenchState();
2186+
}
2187+
},
2188+
21182189
_renderLearningWorkbenchState: function() {
21192190
const userIdInput = document.getElementById('learning-user-id');
21202191
if (userIdInput && userIdInput.value !== this.learningWorkbench.userId) {
@@ -2931,6 +3002,7 @@ window.pathApp = {
29313002
const workbenchRefreshBtn = document.getElementById('btn-refresh-learning-workbench');
29323003
const workbenchIngestBtn = document.getElementById('btn-ingest-focus-node');
29333004
const workbenchRunSessionBtn = document.getElementById('btn-run-learning-session');
3005+
const workbenchRunRetestBtn = document.getElementById('btn-run-retest-session');
29343006
const workbenchUserIdInput = document.getElementById('learning-user-id');
29353007
const workbenchActionsList = document.getElementById('learning-session-actions');
29363008

@@ -2993,6 +3065,12 @@ window.pathApp = {
29933065
});
29943066
}
29953067

3068+
if (workbenchRunRetestBtn) {
3069+
workbenchRunRetestBtn.addEventListener('click', () => {
3070+
void this.runLearningWorkbenchRetestSession();
3071+
});
3072+
}
3073+
29963074
if (workbenchUserIdInput) {
29973075
workbenchUserIdInput.value = this.learningWorkbench.userId || 'path_user_default';
29983076
workbenchUserIdInput.addEventListener('change', (event) => {

src/learning/KnowledgeLearningPlatform.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,7 @@ describe('KnowledgeLearningPlatform', () => {
536536
userId: 'user_session_execute',
537537
sessionPlan,
538538
actionLimit: 3,
539+
includeRetestPlan: false,
539540
persistMemory: true,
540541
memoryLayer: 'session',
541542
});
@@ -552,7 +553,7 @@ describe('KnowledgeLearningPlatform', () => {
552553
expect(execution.summary.averageMasteryAfter).toBeGreaterThanOrEqual(0);
553554
expect(execution.masteryDelta.comparedAtoms).toBeGreaterThan(0);
554555
expect(execution.masteryDelta.items.length).toBe(execution.masteryDelta.comparedAtoms);
555-
expect(execution.retestPlan.summary.totalActions).toBeGreaterThanOrEqual(0);
556+
expect(execution.retestPlan.summary.totalActions).toBe(0);
556557

557558
const stateAfterExecution = platform.getKnowledgeState();
558559
expect(stateAfterExecution.sessionActionTelemetry.executionCount).toBeGreaterThanOrEqual(3);

0 commit comments

Comments
 (0)