Skip to content

Hyperion: Fix instructor checklist bugs and improve UI/UX#12546

Open
HawKhiem wants to merge 26 commits intodevelopfrom
bugfix/hyperion/fix-instructor-checklist-bugs-and-improve-ui
Open

Hyperion: Fix instructor checklist bugs and improve UI/UX#12546
HawKhiem wants to merge 26 commits intodevelopfrom
bugfix/hyperion/fix-instructor-checklist-bugs-and-improve-ui

Conversation

@HawKhiem
Copy link
Copy Markdown
Contributor

@HawKhiem HawKhiem commented Apr 16, 2026

Summary

Fix several bugs and usability issues in the Hyperion instructor checklist discovered during testing. The main issues were: (1) backend analysis timing out due to a single shared timeout cancelling all three concurrent LLM calls, (2) LLM responses wrapped in markdown code blocks causing JSON parse failures, (3) no way to individually select/manage inferred learning goals, (4) diff view resize handle being hidden behind diff headers, (5) a misleading success alert after applying difficulty changes, and (6) stale task/test counts and declared difficulty in the Difficulty Assessment section.

Checklist

General

Server

  • Important: I implemented the changes with a very good performance and prevented too many (unnecessary) and too complex database calls.
  • I strictly followed the principle of data economy for all database calls.
  • I strictly followed the server coding and design guidelines and the REST API guidelines.
  • I added multiple integration tests (Spring) related to the features (with a high test coverage).
  • I documented the Java code using JavaDoc style.

Client

  • Important: I implemented the changes with a very good performance, prevented too many (unnecessary) REST calls and made sure the UI is responsive, even with large data (e.g. using paging).
  • I strictly followed the principle of data economy for all client-server REST calls.
  • I strictly followed the client coding guidelines.
  • Following the theming guidelines, I specified colors only in the theming variable files and checked that the changes look consistent in both the light and the dark theme.
  • I added multiple integration tests (Vitest) related to the features (with a high test coverage), while following the test guidelines.
  • I added multiple screenshots/screencasts of my UI changes.
  • I translated all newly inserted strings into English and German.

Motivation and Context

The Hyperion instructor checklist (Analyze Problem Statement) was unreliable during testing:

  • The analysis frequently failed silently because a single 60-second Mono.zip().timeout() cancelled all three concurrent LLM calls (competency inference, difficulty assessment, quality analysis) as soon as any one of them was slow, causing InterruptedException in the Azure OpenAI SDK. This is mentioned in issue Hyperion: Instructor checklist analysis result empty #12565
  • Even when LLM calls succeeded, parsing occasionally failed because some models wrap JSON responses in markdown code fences (```json ... ```), which the ObjectMapper could not parse directly.
  • The inferred learning goals section offered no granular control — users could only apply or discard all competencies at once, unlike the quality issues section.
  • Entering diff mode in the markdown editor pushed the Monaco editor below the resize handle, making it impossible to resize. This is mentioned in issue Hyperion: Resize draggable pushed out of visible field when in diff mode #12404
  • After applying a difficulty change, a misleading "success" alert was shown even though the problem statement still needed manual review. Misaligned notification when adapting problem statement to difficulty with hyperion #12402
  • The Tasks and Tests counts in the Difficulty Assessment section showed stale values from the last AI analysis, not reflecting subsequent manual edits to the problem statement.
  • The "vs. Declared" row in the Difficulty Assessment section did not react to difficulty changes made either via the "Adapt to" buttons or via the exercise difficulty dropdown — it would only update after a full re-analysis.

Description

Server — HyperionChecklistService.java:

  • Fix analysis timeout: Moved .timeout(ANALYSIS_TIMEOUT) from Mono.zip() to each individual Mono (competenciesMono, difficultyMono, qualityMono). This ensures a slow call only affects itself — the other two analyses complete independently. Increased timeout from 60 seconds to 5 minutes to accommodate slower LLM responses.
  • Defensive JSON extraction: Added extractJsonPayload() method with a compiled JSON_CODE_BLOCK_PATTERN regex (now lazy to avoid over-matching). It tries three strategies in order: (1) extract from markdown code fences, (2) extract embedded {...} substring, (3) fall back to raw text. Applied to all three analysis methods.
  • Debug logging: Added structured debug/warn logs in all three analysis pipelines (competency, difficulty, quality) to trace raw LLM responses and parsing outcomes.

Server tests — HyperionChecklistServiceTest.java:

  • Added two unit tests: analyzeChecklist_handlesJsonWrappedInCodeBlock and analyzeChecklist_handlesJsonWithLeadingText verifying the JSON extraction handles wrapped/embedded responses correctly.

Client — checklist-panel.component.ts/html/scss:

  • Competency multi-select: Added selectedCompetencyIndices signal and 8 new methods (toggleCompetencySelection, isCompetencySelected, selectAllCompetencies, deselectAllCompetencies, allCompetenciesSelected, discardCompetency, discardSelectedCompetencies, applySelectedCompetencies). The UI now includes a toolbar with Select All checkbox, Apply Selected, Discard Selected, and Apply All buttons. Each competency item has an individual checkbox, expand toggle, and discard button.
  • Unlink on discard: Discarding an inferred competency now also removes any exercise competency links that were created for it, keeping the competency links list in sync without requiring a manual step.
  • Live Tasks/Tests counts: The Tasks and Tests badges in the Difficulty Assessment section are now driven by localTaskTestCounts, a computed() signal that parses [task] markers from the live problem statement. The counts update immediately on every problem statement edit — no re-analysis required.
  • Live "vs. Declared" display: Added a declaredDifficulty input (primitive string) and a localDeclaredDifficulty signal. The "vs. Declared" row now shows a badge with the current declared difficulty level and reacts immediately to both: (a) clicking an "Adapt to" button in the checklist panel, and (b) changing the difficulty in the exercise form outside the panel. The "Adapt to" buttons also update their highlighted/disabled state instantly.
  • Alert tone: Changed alertService.success() to alertService.info() in applyAction() and updated the message to prompt review before saving.

Client — markdown-editor-monaco.component.ts/html:

  • Diff view resize fix: Added a viewChild('diffHeader') signal to track the diff pane header element. Updated getEditorHeight() to subtract the header's height from the available space, preventing the Monaco editor from overflowing below the resize handle. Renamed diffSashMoved output to diffOriginalPaneLayoutChanged for clarity.
  • Signal-based viewChild() migration: Migrated all @ViewChild decorators in markdown-editor-monaco.component.ts to Angular's signal-based viewChild() API. Mixing decorator-based @ViewChild with signal-based viewChild() in the same component caused ng-mocks to fail during test compilation, so a full migration of the component was necessary. This required updating several consumer components and their tests that reference the editor's view children (e.g., programming-exercise-editable-instruction.component.ts, posting-markdown-editor.component.ts, short-answer-question-edit.component.ts, multiple-choice-question-edit.component.spec.ts, monaco-editor.component.ts).

Translations — en/de programmingExercise.json:

  • Added 8 new keys for competency multi-select actions (applyAll, applySelected, selectAll, deselectAll, discardSelected, discarded, discardedMultiple, discardCompetency).
  • Updated actions.success message in both languages to prompt the user to review changes.

SCSS — monaco-editor.component.scss:

  • Fix CSS import path: Changed @import 'node_modules/@vscode/codicons/dist/codicon.css' to @import '@vscode/codicons/dist/codicon.css', removing the hardcoded node_modules/ prefix so the SCSS resolver can find the package in CI environments where the working directory differs from the project root.

Steps for Testing

Prerequisites:

  • 1 Instructor
  • 1 Programming Exercise (any language)
  • Hyperion (AI) feature enabled on the server

Bug fix — Analysis timeout:

  1. Log in as Instructor, navigate to a programming exercise's Edit page.
  2. Click "Analyze Problem Statement" in the Instructor Checklist panel.
  3. Verify that all three sections (Quality Assessment, Estimated Learning Goals, Difficulty Assessment) populate successfully, even if individual sections take several seconds.
  4. Verify that if one section is slow, the other two still return results (check browser network tab or server logs).

Bug fix — JSON code block parsing:

  1. This is handled internally. Verify via server unit tests: ./gradlew test --tests HyperionChecklistServiceTest -x webapp

Feature — Competency multi-select:

  1. After analysis completes, expand the "Estimated Learning Goals" section.
  2. Verify each competency has a checkbox and a trash (discard) button.
  3. Select individual competencies using checkboxes and click "Apply Selected" — verify only selected ones are linked.
  4. Use "Select All" checkbox in the toolbar, then "Discard Selected" — verify all competencies are removed from the list.
  5. Click "Apply All" — verify all remaining competencies are linked at once.
  6. Discard an inferred competency that was previously linked — verify the corresponding exercise competency link is also removed.
image

Bug fix — Diff view resize handle:

  1. In the checklist, trigger an AI action that modifies the problem statement (e.g., fix a quality issue).
  2. The markdown editor should enter diff mode with "Your Original" / "AI Suggestion" headers.
  3. Verify the resize handle at the bottom of the editor is still visible and functional.
image

Bug fix — Alert tone:

  1. In the Difficulty Assessment section, click "Adapt Difficulty" (or any action that modifies the problem statement).
  2. Verify an info alert (blue) is shown saying "Changes proposed — please review the updated problem statement above before saving."
  3. Verify it is NOT a green success alert.
image

Improvement — Live Tasks/Tests counts:

  1. Run an analysis to populate the Difficulty Assessment section.
  2. Note the Tasks and Tests badge values.
  3. Edit the problem statement: add or remove a [task] marker.
  4. Verify the Tasks badge updates immediately without re-running the analysis.

Improvement — Live "vs. Declared" difficulty:

  1. Run an analysis to populate the Difficulty Assessment section.
  2. Note the "vs. Declared" badge (e.g., "MEDIUM").
  3. In the Difficulty Assessment section, click an "Adapt to" button (e.g., "Adapt to HARD") — verify the declared badge updates to "HARD" immediately and the delta label recalculates.
  4. Without re-analyzing, change the difficulty in the exercise form's difficulty dropdown — verify the "vs. Declared" badge updates to match the new selection.

Testserver States

You can manage test servers using Helios. Check environment statuses in the environment list. To deploy to a test server, go to the CI/CD page, find your PR or branch, and trigger the deployment.

Review Progress

Performance Review

  • I (as a reviewer) confirm that the client changes (in particular related to REST calls and UI responsiveness) are implemented with a very good performance even for very large courses with more than 2000 students.
  • I (as a reviewer) confirm that the server changes (in particular related to database calls) are implemented with a very good performance even for very large courses with more than 2000 students.

Code Review

  • Code Review 1
  • Code Review 2

Manual Tests

  • Test 1
  • Test 2

Test Coverage

Client

Class/File Line Coverage Lines Expects Ratio
posting-markdown-editor.component.ts 78.46% 172 52 30.2
programming-exercise-editable-instruction.component.ts 92.15% 427 73 17.1
checklist-panel.component.ts not found (modified) 832 175 21.0
short-answer-question-edit.component.ts 93.43% 474 51 10.8
markdown-editor-monaco.component.ts 89.12% 755 76 10.1
monaco-editor.component.ts 88.51% 758 104 13.7

Server

Class/File Line Coverage Lines
HyperionChecklistService.java 77.60% 598

Last updated: 2026-04-21 15:01:24 UTC

Screenshots

@HawKhiem HawKhiem requested review from a team and krusche as code owners April 16, 2026 21:58
@github-project-automation github-project-automation Bot moved this to Work In Progress in Artemis Development Apr 16, 2026
@github-actions github-actions Bot added tests server Pull requests that update Java code. (Added Automatically!) client Pull requests that update TypeScript code. (Added Automatically!) programming Pull requests that affect the corresponding module hyperion labels Apr 16, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 16, 2026

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

Adds robust JSON extraction/parsing for LLM checklist analysis with longer per-task timeouts; implements competency multi-select (select/deselect all, apply selected, dismiss selected) with UI, logic, styles, and tests; migrates several components to callable viewChilds for Monaco editor access and updates related tests and i18n strings.

Changes

Cohort / File(s) Summary
Backend LLM parsing
src/main/java/.../HyperionChecklistService.java
Added regex-based JSON extraction helper and compiled pattern; parse from jsonPayload instead of raw text; added debug/warn logs; changed ANALYSIS_TIMEOUT 60s→5min and applied timeout per analysis Mono; removed overall Mono.zip timeout.
Backend tests (LLM parsing)
src/test/java/.../HyperionChecklistServiceTest.java
Added tests that mock ChatModel.call(...) returning JSON wrapped in Markdown fences or with leading explanatory text; assert parsing into inferred competencies, difficulty suggestion, and quality issues.
Competency multi-select template
src/main/webapp/app/programming/manage/update/.../checklist-panel.component.html
Replaced single “Apply Competencies” action with selection UI: per-item checkboxes, select/deselect-all control, conditional “Apply Selected”/“Dismiss Selected” buttons, per-item discard button, and let i = $index usage.
Competency multi-select logic & tests
src/main/webapp/app/programming/manage/update/.../checklist-panel.component.ts, .../checklist-panel.component.spec.ts
Added selectedCompetencyIndices and selection helpers; optimistic discard (discardCompetency, discardSelectedCompetencies); applySelectedCompetencies() and refactored apply pipeline to applyCompetenciesFromList(...); tests for selection, discard, apply-selected, and selection reset on reanalysis.
Competency styling
src/main/webapp/app/programming/manage/update/.../checklist-panel.component.scss
Added .competency-toolbar, .competency-toolbar-start/.end, .competency-toolbar-label, .competency-selected styling and .competency-actions.
Monaco diff header & viewChild migration
src/main/webapp/app/shared/markdown-editor/monaco/markdown-editor-monaco.component.html, .../markdown-editor-monaco.component.ts
Added #diffHeader template ref; migrated ViewChild usage to signal-style callables (viewChild(...)); subtract diffHeader height from editor height calculation.
Monaco callable migration — cross-component updates & tests
multiple src/main/webapp/app/**/...monaco..., .../posting-markdown-editor..., .../short-answer-question..., .../programming-exercise-editable-instruction...
Replaced @ViewChild property access with callable viewChild(...) across components; updated call sites/tests to invoke monacoEditor() (or similar) and adjusted mocks to return editor objects via functions.
i18n updates
src/main/webapp/i18n/en/programmingExercise.json, src/main/webapp/i18n/de/programmingExercise.json
Added competency selection/discard/apply localization keys and updated instructorChecklist.actions.success text in both locales.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~65 minutes

Possibly related PRs

Suggested labels

ready for review

Suggested reviewers

  • JohannesStoehr
  • SimonEntholzer
  • az108
  • egekurt123
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main objective of the PR: fixing bugs in the Hyperion instructor checklist and improving its UI/UX through competency multi-select, timeout fixes, and visual refinements.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch bugfix/hyperion/fix-instructor-checklist-bugs-and-improve-ui

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

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

⚠️ Outside diff range comments (2)
src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.html (2)

363-417: ⚠️ Potential issue | 🟠 Major

Add accessible names to the new per-competency controls.

The row checkbox has no associated label, and the trash button is icon-only with just a title. That makes selecting or dismissing a specific competency hard to use with screen readers.

Suggested fix
                                         <p-checkbox
                                             [binary]="true"
                                             [ngModel]="isCompetencySelected(i)"
                                             (ngModelChange)="toggleCompetencySelection(i)"
                                             [disabled]="isLoading() || isApplyingAction() || isSyncingCompetencies() || sectionLoading().size > 0"
                                             [inputId]="'competency-select-' + i"
+                                            [ariaLabel]="comp.competencyTitle"
                                             [attr.data-testid]="'competency-checkbox-' + i"
                                         />
@@
                                     <button
                                         pButton
                                         severity="secondary"
                                         size="small"
                                         [text]="true"
                                         [disabled]="isLoading() || isApplyingAction() || isSyncingCompetencies() || sectionLoading().size > 0"
                                         (click)="discardCompetency(i)"
+                                        [attr.aria-label]="('artemisApp.programmingExercise.instructorChecklist.competencies.discardCompetency' | artemisTranslate) + ': ' + comp.competencyTitle"
                                         [attr.title]="'artemisApp.programmingExercise.instructorChecklist.competencies.discardCompetency' | artemisTranslate"
                                         [attr.data-testid]="'discard-competency-' + i"
                                     >
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.html`
around lines 363 - 417, The checkbox and icon-only trash button lack accessible
names; update the p-checkbox (used with
isCompetencySelected/toggleCompetencySelection) to include an aria-label or
aria-labelledby that identifies the competency (e.g., aria-label="Select
competency {{ comp.competencyTitle }}" or aria-labelledby pointing to a
visually-hidden span containing comp.competencyTitle), and add an explicit
accessible name to the discard button (discardCompetency) by adding
aria-label="Discard competency {{ comp.competencyTitle }}" or a visually-hidden
text node tied with aria-labelledby; ensure any new visually-hidden spans use a
consistent sr-only class so screen readers get the competency context while
visual layout remains unchanged.

358-420: ⚠️ Potential issue | 🟠 Major

Don't key mutable competency state by $index.

The new selection/expand/discard flow is all index-based here. If discardCompetency(i) or a re-analysis removes/reorders an earlier item, the checked/expanded state can shift to a different competency on the next render, and bulk actions can target the wrong rows. Please switch this state to a stable competency key instead of $index.

Verify whether the component currently reindexes these sets after every mutation. Expected result: either a stable identifier is used for selection/expansion state, or all stored indices are updated after remove/reorder operations.

#!/bin/bash
set -euo pipefail

FILE="src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.ts"

echo "== Relevant state and handlers =="
rg -n -C3 'selectedCompetencyIndices|toggleCompetencySelection|selectAllCompetencies|deselectAllCompetencies|discardCompetency|discardSelectedCompetencies|isCompetencyExpanded|toggleCompetencyExpand|applySelectedCompetencies' "$FILE"

echo
echo "== Full method bodies around discard / selection logic =="
sed -n '/selectedCompetencyIndices/,+80p' "$FILE"
sed -n '/discardCompetency/,+80p' "$FILE"
sed -n '/discardSelectedCompetencies/,+80p' "$FILE"
sed -n '/toggleCompetencyExpand/,+40p' "$FILE"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.html`
around lines 358 - 420, The template and component currently key
selection/expansion by $index (used in selectedCompetencyIndices,
toggleCompetencySelection, isCompetencyExpanded, toggleCompetencyExpand,
discardCompetency, discardSelectedCompetencies, applySelectedCompetencies),
which will mis-assign state after removals/reorders; change these to use a
stable competency identifier (e.g., comp.id or comp.competencyId) instead of
$index in the template and store selection/expanded state as sets/maps of that
id in the component; update toggleCompetencySelection, toggleCompetencyExpand,
discardCompetency, discardSelectedCompetencies and any bulk actions to operate
on ids (or to remap stored indices to new indices immediately after any
mutation), and ensure the *ngFor uses a trackBy that returns the stable id for
result.inferredCompetencies; finally, verify whether the component currently
reindexes after mutations by checking selectedCompetencyIndices and the handlers
listed above and confirm either ids are used or all stored indices are updated
on remove/reorder.
🧹 Nitpick comments (1)
src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.ts (1)

632-717: Consider extracting a shared selection/discard helper to deduplicate with quality-issue logic.

The new competency methods (toggleCompetencySelection, isCompetencySelected, selectAllCompetencies, deselectAllCompetencies, allCompetenciesSelected, discardCompetency, discardSelectedCompetencies) mirror the corresponding quality-issue methods (toggleIssueSelection, isIssueSelected, selectAllIssues, deselectAllIssues, allIssuesSelected, discardQualityIssue, discardSelectedIssues) almost line-for-line, including the identical re-indexing logic on discard. A generic helper parameterized by the selection signal and a (response) => T[] accessor would remove this duplication and keep the two flows in sync if the pattern is extended further (e.g., a third list later on). Not blocking — happy to defer to a follow-up.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.ts`
around lines 632 - 717, The competency selection/discard methods duplicate the
quality-issue methods; extract a generic helper (e.g., createSelectionHelpers)
that accepts a selection signal (like selectedCompetencyIndices /
selectedQualityIssueIndices) and an accessor function for the list (e.g., (r) =>
r.inferredCompetencies or (r) => r.qualityIssues) and implements toggle,
isSelected, selectAll, deselectAll, allSelected, discard(index) and
discardSelected(), then replace toggleCompetencySelection, isCompetencySelected,
selectAllCompetencies, deselectAllCompetencies, allCompetenciesSelected,
discardCompetency and discardSelectedCompetencies to delegate to the appropriate
helper instance so the re-indexing logic and optimistic update call sites
(updateAnalysisOptimistically, alertService.success) are reused.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.ts`:
- Line 406: The change replaced alertService.success with alertService.info
inside applyAction, which unintentionally makes all AI apply actions show an
info (blue) alert; restore success for quality-fix actions and only use info for
adaptDifficulty by adding a boolean flag (e.g., useInfoAlert) to applyAction and
its callers; update callers fixQualityIssue, fixAllQualityIssues,
fixSelectedIssues to call applyAction(..., useInfoAlert = false) and
adaptDifficulty to call applyAction(..., useInfoAlert = true), then branch
inside applyAction to call alertService.success(...) when useInfoAlert is false
and alertService.info(...) when true so behavior matches
discardCompetency/discardQualityIssue consistency.
- Around line 708-717: The method applySelectedCompetencies builds
selectedInferred but can pass an empty array into applyCompetenciesFromList
which triggers a full sync and a misleading "allLinked" warning; add an
early-return after computing selectedInferred in applySelectedCompetencies: if
selectedInferred.length === 0 return; so you don't call
applyCompetenciesFromList([]) (which leads to
loadCourseCompetencies/reconcileCompetencies/finishApply showing the warning).

---

Outside diff comments:
In
`@src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.html`:
- Around line 363-417: The checkbox and icon-only trash button lack accessible
names; update the p-checkbox (used with
isCompetencySelected/toggleCompetencySelection) to include an aria-label or
aria-labelledby that identifies the competency (e.g., aria-label="Select
competency {{ comp.competencyTitle }}" or aria-labelledby pointing to a
visually-hidden span containing comp.competencyTitle), and add an explicit
accessible name to the discard button (discardCompetency) by adding
aria-label="Discard competency {{ comp.competencyTitle }}" or a visually-hidden
text node tied with aria-labelledby; ensure any new visually-hidden spans use a
consistent sr-only class so screen readers get the competency context while
visual layout remains unchanged.
- Around line 358-420: The template and component currently key
selection/expansion by $index (used in selectedCompetencyIndices,
toggleCompetencySelection, isCompetencyExpanded, toggleCompetencyExpand,
discardCompetency, discardSelectedCompetencies, applySelectedCompetencies),
which will mis-assign state after removals/reorders; change these to use a
stable competency identifier (e.g., comp.id or comp.competencyId) instead of
$index in the template and store selection/expanded state as sets/maps of that
id in the component; update toggleCompetencySelection, toggleCompetencyExpand,
discardCompetency, discardSelectedCompetencies and any bulk actions to operate
on ids (or to remap stored indices to new indices immediately after any
mutation), and ensure the *ngFor uses a trackBy that returns the stable id for
result.inferredCompetencies; finally, verify whether the component currently
reindexes after mutations by checking selectedCompetencyIndices and the handlers
listed above and confirm either ids are used or all stored indices are updated
on remove/reorder.

---

Nitpick comments:
In
`@src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.ts`:
- Around line 632-717: The competency selection/discard methods duplicate the
quality-issue methods; extract a generic helper (e.g., createSelectionHelpers)
that accepts a selection signal (like selectedCompetencyIndices /
selectedQualityIssueIndices) and an accessor function for the list (e.g., (r) =>
r.inferredCompetencies or (r) => r.qualityIssues) and implements toggle,
isSelected, selectAll, deselectAll, allSelected, discard(index) and
discardSelected(), then replace toggleCompetencySelection, isCompetencySelected,
selectAllCompetencies, deselectAllCompetencies, allCompetenciesSelected,
discardCompetency and discardSelectedCompetencies to delegate to the appropriate
helper instance so the re-indexing logic and optimistic update call sites
(updateAnalysisOptimistically, alertService.success) are reused.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 720a4e96-226b-45d7-8e5d-0ae5c3b476ce

📥 Commits

Reviewing files that changed from the base of the PR and between df32496 and 2ea12c7.

📒 Files selected for processing (9)
  • src/main/java/de/tum/cit/aet/artemis/hyperion/service/HyperionChecklistService.java
  • src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.html
  • src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.scss
  • src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.ts
  • src/main/webapp/app/shared/markdown-editor/monaco/markdown-editor-monaco.component.html
  • src/main/webapp/app/shared/markdown-editor/monaco/markdown-editor-monaco.component.ts
  • src/main/webapp/i18n/de/programmingExercise.json
  • src/main/webapp/i18n/en/programmingExercise.json
  • src/test/java/de/tum/cit/aet/artemis/hyperion/service/HyperionChecklistServiceTest.java

@github-project-automation github-project-automation Bot moved this from Work In Progress to Ready For Review in Artemis Development Apr 16, 2026
@github-actions
Copy link
Copy Markdown

@HawKhiem Test coverage could not be fully measured because some tests failed. Please check the workflow logs for details.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 16, 2026

End-to-End Test Results

Phase Status Details
Phase 1 (Relevant) ✅ Passed
TestsPassed ✅Skipped ⚠️FailedTime ⏱
Phase 1: E2E Test Report55 ran53 passed2 skipped0 failed6m 41s
Phase 2 (Remaining) ✅ Passed
TestsPassed ✅SkippedFailedTime ⏱
Phase 2: E2E Test Report197 ran197 passed0 skipped0 failed16m 26s

Test Strategy: Two-phase execution

  • Phase 1: e2e/Login.spec.ts e2e/Logout.spec.ts e2e/SystemHealth.spec.ts e2e/course/CourseMessages.spec.ts e2e/exercise/programming/ e2e/exercise/quiz-exercise/
  • Phase 2: e2e/atlas/ e2e/course/CourseChannelMessages.spec.ts e2e/course/CourseDirectMessages.spec.ts e2e/course/CourseExercise.spec.ts e2e/course/CourseGroupChatMessages.spec.ts e2e/course/CourseManagement.spec.ts e2e/course/CourseMessageInteractions.spec.ts e2e/course/CourseOnboarding.spec.ts e2e/exam/ExamAssessment.spec.ts e2e/exam/ExamChecklists.spec.ts e2e/exam/ExamCreationDeletion.spec.ts e2e/exam/ExamDateVerification.spec.ts e2e/exam/ExamManagement.spec.ts e2e/exam/ExamParticipation.spec.ts e2e/exam/ExamResults.spec.ts e2e/exam/ExamTestRun.spec.ts e2e/exam/test-exam/ e2e/exercise/ExerciseImport.spec.ts e2e/exercise/file-upload/ e2e/exercise/modeling/ e2e/exercise/text/ e2e/lecture/

Overall: ✅ All E2E tests passed (both phases)

🔗 Workflow Run · 📊 Test Report

@github-actions
Copy link
Copy Markdown

@HawKhiem Test coverage could not be fully measured because some tests failed. Please check the workflow logs for details.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.ts (1)

632-703: Consider extracting the selection/discard boilerplate into reusable helpers.

The new competency multi-select API (toggleCompetencySelection, isCompetencySelected, selectAllCompetencies, deselectAllCompetencies, allCompetenciesSelected, discardCompetency, discardSelectedCompetencies) is an almost verbatim copy of the existing quality-issue counterparts (toggleIssueSelection at Line 548, isIssueSelected at Line 563, selectAllIssues/deselectAllIssues/allIssuesSelected at Lines 570–588, and the reindex-on-discard block at Lines 533–541). The two sets only differ by which signal and which list on analysisResult() they touch.

A small generic helper would remove the duplication and keep future behavioral tweaks (e.g., how selections are reindexed after discard) in one place, e.g.:

private toggleInSet<T>(sig: WritableSignal<Set<T>>, item: T) { ... }
private reindexAfterRemoval(sig: WritableSignal<Set<number>>, removedIndex: number) { ... }
private allSelected(sig: WritableSignal<Set<number>>, count: number): boolean { ... }

Non-blocking; safe to defer.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.ts`
around lines 632 - 703, The competency selection/discard methods duplicate the
quality-issue counterparts (e.g., toggleCompetencySelection vs
toggleIssueSelection, discardCompetency vs the reindex-on-discard block) —
extract shared helpers to remove boilerplate: add a generic toggleInSet<T>(sig:
WritableSignal<Set<T>>, item: T) and reuse it from
toggleCompetencySelection/toggleIssueSelection; add reindexAfterRemoval(sig:
WritableSignal<Set<number>>, removedIndex: number) to centralize the reindex
loop used in discardCompetency and the issue discard path; add helpers
allSelected(sig: WritableSignal<Set<number>>, count: number), selectAll(sig:
WritableSignal<Set<number>>, count: number) and deselectAll(sig:
WritableSignal<Set<number>>) and replace implementations that touch
selectedCompetencyIndices/selectedIssueIndices and updateAnalysisOptimistically
to call these helpers so behavior stays identical but duplication is removed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.html`:
- Around line 409-423: The expand/collapse state stored in the
expandedCompetencies Set isn't reindexed when items are removed, so
discardCompetency(i) and discardSelectedCompetencies(...) should update
expandedCompetencies the same way selectedCompetencyIndices is adjusted: when
removing a single index in discardCompetency(i), create a new Set remapping each
stored index > i to index-1 (and discarding the removed index); when removing
multiple selected indices in discardSelectedCompetencies, rebuild
expandedCompetencies by skipping removed indices and shifting higher indices
down according to how many removed indices precede them. Update the code paths
in discardCompetency and discardSelectedCompetencies to perform this reindexing
so isCompetencyExpanded($index) and toggleCompetencyExpand($index) remain
consistent.

---

Nitpick comments:
In
`@src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.ts`:
- Around line 632-703: The competency selection/discard methods duplicate the
quality-issue counterparts (e.g., toggleCompetencySelection vs
toggleIssueSelection, discardCompetency vs the reindex-on-discard block) —
extract shared helpers to remove boilerplate: add a generic toggleInSet<T>(sig:
WritableSignal<Set<T>>, item: T) and reuse it from
toggleCompetencySelection/toggleIssueSelection; add reindexAfterRemoval(sig:
WritableSignal<Set<number>>, removedIndex: number) to centralize the reindex
loop used in discardCompetency and the issue discard path; add helpers
allSelected(sig: WritableSignal<Set<number>>, count: number), selectAll(sig:
WritableSignal<Set<number>>, count: number) and deselectAll(sig:
WritableSignal<Set<number>>) and replace implementations that touch
selectedCompetencyIndices/selectedIssueIndices and updateAnalysisOptimistically
to call these helpers so behavior stays identical but duplication is removed.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f899eb2b-fc77-4838-830f-36771400d8a6

📥 Commits

Reviewing files that changed from the base of the PR and between 2ea12c7 and 0428f24.

📒 Files selected for processing (6)
  • src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.html
  • src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.spec.ts
  • src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.ts
  • src/main/webapp/app/shared/markdown-editor/monaco/markdown-editor-monaco.component.ts
  • src/main/webapp/i18n/de/programmingExercise.json
  • src/main/webapp/i18n/en/programmingExercise.json
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/main/webapp/app/shared/markdown-editor/monaco/markdown-editor-monaco.component.ts
  • src/main/webapp/i18n/en/programmingExercise.json
  • src/main/webapp/i18n/de/programmingExercise.json

@github-actions
Copy link
Copy Markdown

@HawKhiem Test coverage has been automatically updated in the PR description.

1 similar comment
@github-actions
Copy link
Copy Markdown

@HawKhiem Test coverage has been automatically updated in the PR description.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.spec.ts (1)

1022-1039: Assert the created competency request uses the selected item.

Line 1023 returns Sorting for every create() call, so this test could still pass if the implementation accidentally creates unselected Recursion and receives the mocked Sorting response. Capture the spy and assert the request payload targets Sorting.

Proposed test tightening
-            vi.spyOn(competencyService, 'create').mockReturnValue(of(new HttpResponse({ body: createdSorting })) as any);
+            const createSpy = vi.spyOn(competencyService, 'create').mockReturnValue(of(new HttpResponse({ body: createdSorting })) as any);
@@
             expect(competencyService.getAllForCourse).toHaveBeenCalledWith(courseId);
+            expect(createSpy).toHaveBeenCalledTimes(1);
+            expect(createSpy).toHaveBeenCalledWith(expect.objectContaining({ title: 'Sorting' }), courseId);
             expect(emitSpy).toHaveBeenCalled();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.spec.ts`
around lines 1022 - 1039, The test currently stubs competencyService.create to
always return a Competency titled "Sorting", masking whether the code actually
created the selected item; update the spec to capture and assert the create call
payload: replace the static mockReturnValue with a spy/mockImplementation that
records the argument (or keep the spy and inspect
competencyService.create.mock.calls), then after
component.applySelectedCompetencies() assert that competencyService.create was
invoked with an object representing the selected competency (title 'Sorting' or
the exact competency instance from the selected index) and that no create call
was made for 'Recursion'; reference component.applySelectedCompetencies and
competencyService.create when locating the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.spec.ts`:
- Around line 1022-1039: The test currently stubs competencyService.create to
always return a Competency titled "Sorting", masking whether the code actually
created the selected item; update the spec to capture and assert the create call
payload: replace the static mockReturnValue with a spy/mockImplementation that
records the argument (or keep the spy and inspect
competencyService.create.mock.calls), then after
component.applySelectedCompetencies() assert that competencyService.create was
invoked with an object representing the selected competency (title 'Sorting' or
the exact competency instance from the selected index) and that no create call
was made for 'Recursion'; reference component.applySelectedCompetencies and
competencyService.create when locating the change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 91af568d-609b-4c9a-9558-bbf8a1419d39

📥 Commits

Reviewing files that changed from the base of the PR and between 0428f24 and 757938a.

📒 Files selected for processing (3)
  • src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.spec.ts
  • src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.ts
  • src/main/webapp/app/shared/markdown-editor/monaco/markdown-editor-monaco.component.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/webapp/app/shared/markdown-editor/monaco/markdown-editor-monaco.component.ts

@HawKhiem HawKhiem moved this from Todo to In Progress in Communication Webclient Apr 20, 2026
@HawKhiem HawKhiem moved this from Backlog to Ready For Review in Hyperion Team Apr 20, 2026
@github-actions
Copy link
Copy Markdown

@HawKhiem Test coverage has been automatically updated in the PR description.

@github-actions
Copy link
Copy Markdown

@HawKhiem Test coverage has been automatically updated in the PR description.

@github-actions
Copy link
Copy Markdown

@HawKhiem Test coverage has been automatically updated in the PR description.

1 similar comment
@github-actions
Copy link
Copy Markdown

@HawKhiem Test coverage has been automatically updated in the PR description.

@github-actions
Copy link
Copy Markdown

@HawKhiem Test coverage has been automatically updated in the PR description.

1 similar comment
@github-actions
Copy link
Copy Markdown

@HawKhiem Test coverage has been automatically updated in the PR description.

@HawKhiem HawKhiem changed the title Hyperion: Fix instructor checklist bugs and improve UI Hyperion: Fix instructor checklist bugs and improve UI/UX Apr 20, 2026
Copy link
Copy Markdown
Contributor

@Claudia-Anthropica Claudia-Anthropica left a comment

Choose a reason for hiding this comment

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

@HawKhiem Clean work — the per-Mono timeout fix correctly isolates failures, the defensive JSON extraction handles the common LLM wrapping cases well, and the competency multi-select is well-implemented with proper index reindexing. The viewChild signal migration is comprehensive and correct. Just one minor nit inline.

@github-actions
Copy link
Copy Markdown

@HawKhiem Test coverage has been automatically updated in the PR description.

Copy link
Copy Markdown
Contributor

@Claudia-Anthropica Claudia-Anthropica left a comment

Choose a reason for hiding this comment

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

@HawKhiem Solid work. The timeout isolation fix, JSON extraction, viewChild migration, and competency multi-select are all clean and well-tested. Approving as-is.

@github-actions
Copy link
Copy Markdown

@HawKhiem Test coverage has been automatically updated in the PR description.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

client Pull requests that update TypeScript code. (Added Automatically!) communication Pull requests that affect the corresponding module hyperion programming Pull requests that affect the corresponding module quiz Pull requests that affect the corresponding module ready for review server Pull requests that update Java code. (Added Automatically!) tests

Projects

Status: Ready For Review
Status: In Progress
Status: Ready For Review

2 participants