Skip to content

✨ Source component suggestions#787

Open
C-Valen wants to merge 4 commits into
mainfrom
feature/OSIDB-4996-aegis-component-suggestions
Open

✨ Source component suggestions#787
C-Valen wants to merge 4 commits into
mainfrom
feature/OSIDB-4996-aegis-component-suggestions

Conversation

@C-Valen
Copy link
Copy Markdown
Member

@C-Valen C-Valen commented May 26, 2026

Checklist:

  • Commits consolidated
  • Changelog updated
  • Test cases added/updated
  • Integration tests updated

Summary

Add manual Source Component field suggestions.

Changes

  • Add useAegisSuggestComponents composable
  • Create AegisComponentActions following existing Aegis patterns
  • Integrate manual suggestions into FlawForm replacing previous bot-only approach

Considerations

  • Requires aiComponentSuggestions feature flag to be enabled

@C-Valen C-Valen self-assigned this May 26, 2026
@C-Valen C-Valen added the enhancement New feature or request label May 26, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 26, 2026

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

Adds AI-driven manual component suggestions: new Aegis feature and types, a composable to fetch/apply/revert/send-feedback for component suggestions, watcher and composable integrations, a UI wrapper component with tests, FlawForm integration replacing the old modal flow, minor AegisActions tooltip/layout fixes, and a changelog entry.

Changes

Component Suggestions Feature

Layer / File(s) Summary
Type contracts and feature definition
src/types/aegisAI.ts
Adds 'suggest-affected-components' to AegisAIComponentFeatureNameType and defines ComponentsSuggestionDetails with components: Nullable<string[]>; updates AegisFeatureResponseMap.
Core suggestion composable implementation
src/composables/aegis/useAegisSuggestComponents.ts
Implements useAegisSuggestComponents to validate CVE IDs, call Aegis AI for suggest-affected-components, manage selection/revert/metadata, and expose feedback/suggestion state and handlers.
AISuggestions watcher widening
src/composables/aegis/useAISuggestionsWatcher.ts
Widens watcher and applyAISuggestion to accept string[], serializes arrays for AI metadata tracking, and preserves revert semantics.
useAegisSuggestion integration
src/composables/aegis/useAegisSuggestion.ts
Extends useAegisSuggestion to support components: broadens value types to string[], initializes components: null in details, adds suggestComponents() and includes components handling in get/revert flows.
Component UI wrapper and styles
src/components/Aegis/AegisComponentActions.vue
Adds AegisComponentActions that wraps the composable, computes tooltips, wires feedback handlers, and exposes isFetchingSuggestion; includes scoped SCSS.
Component tests and interaction
src/components/Aegis/__tests__/AegisComponentActions.spec.ts
Snapshot and interaction tests: verifies rendering, that AegisActions is present, isFetchingSuggestion is exposed, and selectSuggestion wiring calls the composable handler.
AegisActions tooltip & layout tweaks
src/components/Aegis/AegisActions.vue
Adds safeTooltipText (escapes HTML, converts newlines to <br>) and switches v-html to use it; reformats revert/feedback span condition and applies inline-flex alignment style.
FlawForm integration
src/components/FlawForm/FlawForm.vue
Replaces prior components tooltip + feedback modal with AegisComponentActions in the Source Component label slot; removes useComponentsFeedback import and modal markup; simplifies metadata tracking to isFieldValueAIBot.
Test updates: suggestComponents stubs & expectations
src/components/Aegis/__tests__/*, src/composables/__tests__/useAegisSuggestion.spec.ts
Adds suggestComponents: vi.fn() to multiple useAegisSuggestion mocks and updates useAegisSuggestion tests to expect components: null in details.value for several scenarios.
Feature documentation
CHANGELOG.md
Documents manual component suggestions for the Source Component field under Unreleased → Added, referenced OSIDB-4996.

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Source component suggestions' clearly describes the main change: adding AI-powered suggestions for the Source Component field.
Description check ✅ Passed The PR description includes most required sections from the template: a completed checklist, a summary of changes, detailed list of changes made, and considerations about the feature flag requirement.
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.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/OSIDB-4996-aegis-component-suggestions

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

@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: 4

🧹 Nitpick comments (1)
src/components/Aegis/__tests__/AegisComponentActions.spec.ts (1)

79-114: ⚡ Quick win

Add a non-zero selection assertion to catch index-mapping regressions.

This test passes even when component logic ignores user-selected indices.

Proposed test hardening
-    await aegisActions.vm.$emit('selectSuggestion', 0);
-
-    expect(mockSelectSuggestion).toHaveBeenCalledWith(0);
+    await aegisActions.vm.$emit('selectSuggestion', 1);
+    expect(mockSelectSuggestion).toHaveBeenCalledWith(1);

As per coding guidelines, "**: -Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity."

🤖 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/components/Aegis/__tests__/AegisComponentActions.spec.ts` around lines 79
- 114, The test currently only asserts a zero index selection which can mask
index-mapping bugs; update the mocked useAegisSuggestComponents so
selectedSuggestionIndex is a non-zero value (e.g., computed(() => 1)), ensure
suggestedComponents/allSuggestions include at least two entries, then emit a
non-zero selection from the AegisActions component (e.g.,
aegisActions.vm.$emit('selectSuggestion', 1)) and assert mockSelectSuggestion
was called with that non-zero index (mockSelectSuggestion
toHaveBeenCalledWith(1)) to catch regressions in index handling.
🤖 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/components/Aegis/AegisActions.vue`:
- Line 123: Remove the trailing whitespace on the empty/partial tag near the
<span in AegisActions.vue (the fragment shown in the diff) so the line contains
no trailing spaces; edit the <span line to trim the trailing spaces and save to
satisfy the linter.

In `@src/components/Aegis/AegisComponentActions.vue`:
- Around line 38-48: handleSelectSuggestion currently hardcodes
selectSuggestion(0), dropping the original set/item indices and preventing
choosing alternate suggestion sets; change it to map the incoming _flatIndex
back to the corresponding suggestion-set index and item-index using
allSuggestions (or flatSuggestions with offsets) and call selectSuggestion with
the correct set index (and item index if selectSuggestion accepts it) so the UI
selection matches the flattened index; locate handleSelectSuggestion,
flatSuggestions and selectSuggestion to implement this index-mapping logic and
update any callers accordingly.

In `@src/components/FlawComments/FlawComments.vue`:
- Line 182: The CSS in FlawComments.vue currently sets "white-space: pre-line"
for rendered comment text which collapses repeated spaces/tabs and breaks
user-aligned formatting; replace that rule with "white-space: pre-wrap" (or
"white-space: pre" if wrapping must be avoided) in the same selector so line
breaks are preserved while still allowing wrapping, ensuring comment text and
code/log snippets keep their original spacing. Locate the white-space rule in
FlawComments.vue and update it to pre-wrap and verify comment history renders
aligned text correctly.

In `@src/composables/aegis/useAegisSuggestComponents.ts`:
- Around line 111-116: selectSuggestion currently assigns previousValue on every
invocation, which overwrites the original baseline and breaks revert; change the
logic in selectSuggestion (and the similar block around the later 126-131
region) so previousValue is only set when it is null/undefined (i.e., only on
the first selection in the session) and do not reassign it on subsequent calls;
refer to function selectSuggestion, the previousValue ref, and the revert logic
to ensure revert uses the preserved original value.

---

Nitpick comments:
In `@src/components/Aegis/__tests__/AegisComponentActions.spec.ts`:
- Around line 79-114: The test currently only asserts a zero index selection
which can mask index-mapping bugs; update the mocked useAegisSuggestComponents
so selectedSuggestionIndex is a non-zero value (e.g., computed(() => 1)), ensure
suggestedComponents/allSuggestions include at least two entries, then emit a
non-zero selection from the AegisActions component (e.g.,
aegisActions.vm.$emit('selectSuggestion', 1)) and assert mockSelectSuggestion
was called with that non-zero index (mockSelectSuggestion
toHaveBeenCalledWith(1)) to catch regressions in index handling.
🪄 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: CHILL

Plan: Enterprise

Run ID: 8ee179c7-6874-4109-8777-124ae175dc7e

📥 Commits

Reviewing files that changed from the base of the PR and between 4bc2e80 and b507299.

⛔ Files ignored due to path filters (3)
  • src/components/Aegis/__tests__/__snapshots__/AegisComponentActions.spec.ts.snap is excluded by !**/*.snap
  • src/components/__tests__/__snapshots__/FlawForm.spec.ts.snap is excluded by !**/*.snap
  • src/views/__tests__/__snapshots__/FlawCreateView.spec.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (9)
  • CHANGELOG.md
  • src/components/Aegis/AegisActions.vue
  • src/components/Aegis/AegisComponentActions.vue
  • src/components/Aegis/__tests__/AegisComponentActions.spec.ts
  • src/components/FlawComments/FlawComments.vue
  • src/components/FlawForm/FlawForm.vue
  • src/composables/aegis/__tests__/useAegisSuggestComponents.spec.ts
  • src/composables/aegis/useAegisSuggestComponents.ts
  • src/types/aegisAI.ts

Comment thread src/components/Aegis/AegisActions.vue Outdated
Comment thread src/components/Aegis/AegisComponentActions.vue Outdated
Comment thread src/components/FlawComments/FlawComments.vue Outdated
Comment thread src/composables/aegis/useAegisSuggestComponents.ts
@C-Valen C-Valen marked this pull request as draft May 26, 2026 10:53
@C-Valen C-Valen force-pushed the feature/OSIDB-4996-aegis-component-suggestions branch from b507299 to 1e2192e Compare May 26, 2026 11:48
@C-Valen C-Valen marked this pull request as ready for review May 26, 2026 11:48
Copy link
Copy Markdown

@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

🧹 Nitpick comments (1)
src/composables/aegis/__tests__/useAegisSuggestComponents.spec.ts (1)

57-65: ⚡ Quick win

Add regression tests for apply/revert state transitions (not just method existence).

The suite currently misses assertions for the core behavior of suggestComponents() + revert(). Add cases that verify baseline restoration for [] and undefined so revert regressions are caught.

Example direction
+it('restores an empty-array baseline after revert', async () => {
+  mockValueRef.value = [];
+  // mock service response with one suggestion
+  // await result.suggestComponents()
+  // result.revert()
+  // expect(mockValueRef.value).toEqual([])
+});
+
+it('restores an undefined baseline after revert', async () => {
+  mockValueRef.value = undefined;
+  // mock service response with one suggestion
+  // await result.suggestComponents()
+  // result.revert()
+  // expect(mockValueRef.value).toBeUndefined()
+});

Also applies to: 79-85

🤖 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/composables/aegis/__tests__/useAegisSuggestComponents.spec.ts` around
lines 57 - 65, Add regression tests in useAegisSuggestComponents.spec.ts to
assert actual state transitions for suggestComponents() and revert(): call
useAegisSuggestComponents(mockContext, mockValueRef), invoke
result.suggestComponents(...) to apply suggestions and assert that
result.allSuggestions.value, result.hasAppliedSuggestion.value,
result.selectedSuggestionIndex.value, and result.canShowFeedback.value reflect
the applied state, then call result.revert() and assert the baseline is restored
for two cases — when the original value ref was [] and when it was undefined —
ensuring revert returns all affected refs to their original values; add parallel
tests where applicable around the existing initialization test and the block
around lines 79–85 so both scenarios are covered.
🤖 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/components/Aegis/AegisComponentActions.vue`:
- Around line 68-76: The tooltip strings produced by the computed
suggestionTooltip (using hasAppliedSuggestion,
componentsSuggestionDetails.explanation, and getAIBotTooltip('components')) are
untrusted and later rendered with v-html in AegisActions, so sanitize/escape
them before returning: update suggestionTooltip to run the text through a safe
HTML sanitizer or escape function (e.g., strip or encode tags/entities) and
preserve newline replacements, or return a sanitized string variant for
AegisActions to render; ensure all branches (the title+explanation branch and
the aiBotTooltip branch) use the sanitizer/escape so no raw HTML reaches v-html.

In `@src/composables/aegis/useAegisSuggestComponents.ts`:
- Around line 36-37: The revert logic for the suggest component is mutating and
coercing baseline values (turning [] into null and forcing undefined to null);
update the stored baseline types and restore logic so the original value is
captured and restored exactly (preserve undefined vs null vs empty array).
Change previousValue to allow undefined (ref<string[] | null | undefined>), stop
coercing when saving baseline (store the raw value from the source field), and
update revert() to assign back the stored baseline exactly to the target field
(no conversion to null or []) while leaving selectedSuggestionIndex handling
unchanged.

---

Nitpick comments:
In `@src/composables/aegis/__tests__/useAegisSuggestComponents.spec.ts`:
- Around line 57-65: Add regression tests in useAegisSuggestComponents.spec.ts
to assert actual state transitions for suggestComponents() and revert(): call
useAegisSuggestComponents(mockContext, mockValueRef), invoke
result.suggestComponents(...) to apply suggestions and assert that
result.allSuggestions.value, result.hasAppliedSuggestion.value,
result.selectedSuggestionIndex.value, and result.canShowFeedback.value reflect
the applied state, then call result.revert() and assert the baseline is restored
for two cases — when the original value ref was [] and when it was undefined —
ensuring revert returns all affected refs to their original values; add parallel
tests where applicable around the existing initialization test and the block
around lines 79–85 so both scenarios are covered.
🪄 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: CHILL

Plan: Enterprise

Run ID: 0bc07bd8-3821-4a43-9931-7a14d8be1bf2

📥 Commits

Reviewing files that changed from the base of the PR and between b507299 and 1e2192e.

⛔ Files ignored due to path filters (3)
  • src/components/Aegis/__tests__/__snapshots__/AegisComponentActions.spec.ts.snap is excluded by !**/*.snap
  • src/components/__tests__/__snapshots__/FlawForm.spec.ts.snap is excluded by !**/*.snap
  • src/views/__tests__/__snapshots__/FlawCreateView.spec.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (8)
  • CHANGELOG.md
  • src/components/Aegis/AegisActions.vue
  • src/components/Aegis/AegisComponentActions.vue
  • src/components/Aegis/__tests__/AegisComponentActions.spec.ts
  • src/components/FlawForm/FlawForm.vue
  • src/composables/aegis/__tests__/useAegisSuggestComponents.spec.ts
  • src/composables/aegis/useAegisSuggestComponents.ts
  • src/types/aegisAI.ts

Comment on lines +68 to +76
const suggestionTooltip = computed(() => {
if (hasAppliedSuggestion.value && componentsSuggestionDetails.value?.explanation) {
const title = isComponentsAIBot.value ? 'Generated by Aegis-AI-Bot' : 'Generated by Aegis-AI';
return `${title}\n\n${componentsSuggestionDetails.value.explanation}`;
}
const aiBotTooltip = getAIBotTooltip('components');
if (aiBotTooltip && aiBotTooltip !== 'Generated by Aegis-AI-Bot') {
return aiBotTooltip.replace(/<br><br>/g, '\n\n');
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Escape tooltip content before it reaches v-html.

These tooltip strings are untrusted and are later rendered via v-html in AegisActions, which creates an XSS path if HTML is present.

🔒 Suggested fix
+const escapeHtml = (value: string) => value
+  .replace(/&/g, '&amp;')
+  .replace(/</g, '&lt;')
+  .replace(/>/g, '&gt;')
+  .replace(/"/g, '&quot;')
+  .replace(/'/g, '&`#39`;');
+
 const suggestionTooltip = computed(() => {
   if (hasAppliedSuggestion.value && componentsSuggestionDetails.value?.explanation) {
     const title = isComponentsAIBot.value ? 'Generated by Aegis-AI-Bot' : 'Generated by Aegis-AI';
-    return `${title}\n\n${componentsSuggestionDetails.value.explanation}`;
+    return `${title}\n\n${escapeHtml(componentsSuggestionDetails.value.explanation)}`;
   }
   const aiBotTooltip = getAIBotTooltip('components');
   if (aiBotTooltip && aiBotTooltip !== 'Generated by Aegis-AI-Bot') {
-    return aiBotTooltip.replace(/<br><br>/g, '\n\n');
+    return escapeHtml(aiBotTooltip).replace(/&lt;br&gt;&lt;br&gt;/g, '\n\n');
   }
   return '';
 });
🤖 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/components/Aegis/AegisComponentActions.vue` around lines 68 - 76, The
tooltip strings produced by the computed suggestionTooltip (using
hasAppliedSuggestion, componentsSuggestionDetails.explanation, and
getAIBotTooltip('components')) are untrusted and later rendered with v-html in
AegisActions, so sanitize/escape them before returning: update suggestionTooltip
to run the text through a safe HTML sanitizer or escape function (e.g., strip or
encode tags/entities) and preserve newline replacements, or return a sanitized
string variant for AegisActions to render; ensure all branches (the
title+explanation branch and the aiBotTooltip branch) use the sanitizer/escape
so no raw HTML reaches v-html.

Comment thread src/composables/aegis/useAegisSuggestComponents.ts Outdated
@C-Valen C-Valen force-pushed the feature/OSIDB-4996-aegis-component-suggestions branch from 1e2192e to c6b0028 Compare May 26, 2026 12:36
@C-Valen C-Valen marked this pull request as draft May 26, 2026 12:46
@C-Valen C-Valen marked this pull request as ready for review May 26, 2026 13:30
Copy link
Copy Markdown

@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 (2)
src/composables/aegis/__tests__/useAegisSuggestComponents.spec.ts (1)

57-85: ⚡ Quick win

Add behavioral tests for apply/revert/feedback flows, not just API shape.

Current tests only verify defaults and function presence. Please add focused cases for: successful suggestion apply, exact revert for undefined/null/[], and one-time feedback gating after 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/composables/aegis/__tests__/useAegisSuggestComponents.spec.ts` around
lines 57 - 85, Add behavioral tests to useAegisSuggestComponents: write tests
that cover applying a suggestion (call selectSuggestion or applySuggestion and
assert allSuggestions changes, hasAppliedSuggestion becomes true,
selectedSuggestionIndex updates, and mockValueRef reflects applied value),
reverting behavior (set value to undefined/null/[] then call revert and assert
value is restored exactly and hasAppliedSuggestion resets), and feedback gating
(call submitFeedback once and assert canShowFeedback toggles so subsequent
feedback attempts are blocked and hasAppliedSuggestion/feedback state reflect
the one-time submission). Use existing symbols: useAegisSuggestComponents,
selectSuggestion/applySuggestion, revert, submitFeedback, canShowFeedback,
hasAppliedSuggestion, selectedSuggestionIndex, allSuggestions, mockContext and
mockValueRef to locate methods and state to assert.
src/components/Aegis/AegisComponentActions.vue (1)

33-34: ⚡ Quick win

Avoid null-unsafe casting for aegisContext before passing into the composable.

aegisContext is nullable by prop contract, but this cast erases that and weakens type safety at the integration boundary. Prefer handling null explicitly (or updating the composable signature to accept nullable input) instead of forcing a non-null type.

As per coding guidelines, "**: -Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity."

🤖 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/components/Aegis/AegisComponentActions.vue` around lines 33 - 34, The
code unsafely casts props.aegisContext to AegisSuggestionContextRefs before
passing it into the composable; remove the non-null assertion and handle the
nullable prop explicitly by either (a) only invoking the composable or passing
the context when props.aegisContext is non-null (e.g., guard with if
(props.aegisContext) { /* call composable with props.aegisContext */ }), or (b)
update the composable's parameter type to accept AegisSuggestionContextRefs |
null/undefined and handle null inside the composable; target the symbol
props.aegisContext and the composable call site (the function that currently
receives AegisSuggestionContextRefs) and apply one of these fixes to preserve
type safety.
🤖 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/composables/aegis/useAegisSuggestComponents.ts`:
- Around line 96-103: getSuggestion() currently trusts the untyped API response
and assigns data.components directly, which can be a non-array and later break
selectSuggestion() when it spreads components; add a runtime guard in
getSuggestion() to validate that data.components is an Array and every item is a
string (use Array.isArray(data.components) && data.components.every(item =>
typeof item === 'string')); if the check fails, set components to null (or an
empty array if preferred) before returning the ComponentsSuggestionDetails so
selectSuggestion() and valueRef spreading cannot be corrupted. Ensure you
reference the returned property name "components" and the type
ComponentsSuggestionDetails when applying the guard and mapping/casting the
validated value.

---

Nitpick comments:
In `@src/components/Aegis/AegisComponentActions.vue`:
- Around line 33-34: The code unsafely casts props.aegisContext to
AegisSuggestionContextRefs before passing it into the composable; remove the
non-null assertion and handle the nullable prop explicitly by either (a) only
invoking the composable or passing the context when props.aegisContext is
non-null (e.g., guard with if (props.aegisContext) { /* call composable with
props.aegisContext */ }), or (b) update the composable's parameter type to
accept AegisSuggestionContextRefs | null/undefined and handle null inside the
composable; target the symbol props.aegisContext and the composable call site
(the function that currently receives AegisSuggestionContextRefs) and apply one
of these fixes to preserve type safety.

In `@src/composables/aegis/__tests__/useAegisSuggestComponents.spec.ts`:
- Around line 57-85: Add behavioral tests to useAegisSuggestComponents: write
tests that cover applying a suggestion (call selectSuggestion or applySuggestion
and assert allSuggestions changes, hasAppliedSuggestion becomes true,
selectedSuggestionIndex updates, and mockValueRef reflects applied value),
reverting behavior (set value to undefined/null/[] then call revert and assert
value is restored exactly and hasAppliedSuggestion resets), and feedback gating
(call submitFeedback once and assert canShowFeedback toggles so subsequent
feedback attempts are blocked and hasAppliedSuggestion/feedback state reflect
the one-time submission). Use existing symbols: useAegisSuggestComponents,
selectSuggestion/applySuggestion, revert, submitFeedback, canShowFeedback,
hasAppliedSuggestion, selectedSuggestionIndex, allSuggestions, mockContext and
mockValueRef to locate methods and state to assert.
🪄 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: CHILL

Plan: Enterprise

Run ID: a41888ca-128d-4157-87b3-0a77326a99c0

📥 Commits

Reviewing files that changed from the base of the PR and between 1e2192e and c6b0028.

⛔ Files ignored due to path filters (3)
  • src/components/Aegis/__tests__/__snapshots__/AegisComponentActions.spec.ts.snap is excluded by !**/*.snap
  • src/components/__tests__/__snapshots__/FlawForm.spec.ts.snap is excluded by !**/*.snap
  • src/views/__tests__/__snapshots__/FlawCreateView.spec.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (8)
  • CHANGELOG.md
  • src/components/Aegis/AegisActions.vue
  • src/components/Aegis/AegisComponentActions.vue
  • src/components/Aegis/__tests__/AegisComponentActions.spec.ts
  • src/components/FlawForm/FlawForm.vue
  • src/composables/aegis/__tests__/useAegisSuggestComponents.spec.ts
  • src/composables/aegis/useAegisSuggestComponents.ts
  • src/types/aegisAI.ts
✅ Files skipped from review due to trivial changes (1)
  • CHANGELOG.md

Comment thread src/composables/aegis/useAegisSuggestComponents.ts
@C-Valen C-Valen force-pushed the feature/OSIDB-4996-aegis-component-suggestions branch from c6b0028 to 34e92c9 Compare May 26, 2026 14:25
@C-Valen C-Valen requested a review from a team May 26, 2026 15:14
import { useToastStore } from '@/stores/ToastStore';
import type { ComponentsSuggestionDetails } from '@/types/aegisAI';

export type UseAegisSuggestComponentsReturn = {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think this type isn't needed, since it just enforces the return type of a function used locally. I think if we want to pay the maintenance cost of having a more generic interface for suggestions composables, then that would add more value.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

if hasMultipleSuggestions is only gating logic that deals with interactions between allsuggestions then it could be runtime rather than type logic allSuggestions.value[0].length === 1 and could therefore be a function.

Copy link
Copy Markdown
Collaborator

@superbuggy superbuggy left a comment

Choose a reason for hiding this comment

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

One suggestion that isn't a change request; feel free to disagree. Looks good otherwise.

@C-Valen C-Valen force-pushed the feature/OSIDB-4996-aegis-component-suggestions branch 2 times, most recently from 1414e27 to 42b2e8c Compare June 4, 2026 12:31
Copy link
Copy Markdown

@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 (1)
src/composables/aegis/useAegisSuggestion.ts (1)

269-273: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Prevent applying a scalar string to the components string[] model.

For fieldName === 'components', Line 275 turns each component into a selectable suggestion item, and Line 272 applies currentSuggestion directly. That can write a single string into the modelValue contract (string[] | null | undefined in src/components/Aegis/AegisComponentActions.vue, Line 17), causing type-shape drift in form state.

As per coding guidelines, "**: -Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity."

Proposed fix
@@
   function selectSuggestion(index: number) {
     if (!allSuggestions.value?.[index]) return;
     selectedSuggestionIndex.value = index;
+    if (fieldName === 'components') {
+      const componentsSuggestion = details.value.components;
+      if (Array.isArray(componentsSuggestion) && componentsSuggestion.length > 0) {
+        aegisSuggestionWatcher.applyAISuggestion(componentsSuggestion);
+      }
+      return;
+    }
     if (currentSuggestion.value) aegisSuggestionWatcher.applyAISuggestion(currentSuggestion.value);
   }
@@
-  const hasMultipleSuggestions = computed(() => allSuggestions.value.length > 1);
+  const hasMultipleSuggestions = computed(
+    () => (fieldName === 'components' ? false : allSuggestions.value.length > 1),
+  );

Also applies to: 275-279, 290-290

🤖 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/composables/aegis/useAegisSuggestion.ts` around lines 269 - 273,
selectSuggestion may call aegisSuggestionWatcher.applyAISuggestion with
currentSuggestion that is a scalar string when fieldName === 'components', which
can violate the component's model type (expects string[] | null | undefined);
update selectSuggestion (and other places noted: the block around lines handling
components, and where currentSuggestion is applied) to detect when fieldName ===
'components' and currentSuggestion is a string and instead pass an array (e.g.,
wrap the string in [currentSuggestion]) or otherwise convert to the expected
string[] shape before calling aegisSuggestionWatcher.applyAISuggestion so the
modelValue contract is preserved.
🤖 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/composables/aegis/useAegisSuggestion.ts`:
- Around line 170-177: The suggestComponents flow is too strict and mismatches
the API contract: update suggestComponents (and the call site that invokes
analyzeCVEWithContext for "suggest-affected-components") to (1) unwrap the
actual payload (check for data.output and use that when present), (2) validate
that data.components is an array of strings (every item typeof === 'string' and
length > 0) instead of only checking Array.isArray/length, and (3) when calling
analyzeCVEWithContext for the affected-components path include detail: true in
the options so the analyzer returns the detailed structure — mirror the handling
used in useAegisSuggestComponents.ts (lines around its validate/unwrapping
logic) to avoid rejecting valid responses and silently suppressing suggestions.

In `@src/composables/aegis/useAISuggestionsWatcher.ts`:
- Around line 14-19: The watcher in useAISuggestionsWatcher uses strict
reference inequality (newValue !== originalSuggestion.value && newValue !==
oldValue), which misses in-place mutations for string[] fields (e.g., fieldName
'components'); change the comparison to deep/value equality: compute normalized
representations (e.g., for arrays use JSON.stringify or a deepEqual helper) and
compare those strings/values instead of references when checking against
originalSuggestion.value and oldValue, while keeping the rest of the logic
(hasAppliedSuggestion, hasPartialModification, hasTrackedPartialChange,
trackAIChange) the same; also use the same normalization when building
metadataValue so array changes are detected and tracked correctly.

---

Outside diff comments:
In `@src/composables/aegis/useAegisSuggestion.ts`:
- Around line 269-273: selectSuggestion may call
aegisSuggestionWatcher.applyAISuggestion with currentSuggestion that is a scalar
string when fieldName === 'components', which can violate the component's model
type (expects string[] | null | undefined); update selectSuggestion (and other
places noted: the block around lines handling components, and where
currentSuggestion is applied) to detect when fieldName === 'components' and
currentSuggestion is a string and instead pass an array (e.g., wrap the string
in [currentSuggestion]) or otherwise convert to the expected string[] shape
before calling aegisSuggestionWatcher.applyAISuggestion so the modelValue
contract is preserved.
🪄 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: CHILL

Plan: Enterprise

Run ID: 7d37f425-80c7-427e-a297-d7036a3a0318

📥 Commits

Reviewing files that changed from the base of the PR and between c6b0028 and 1414e27.

⛔ Files ignored due to path filters (2)
  • src/components/Aegis/__tests__/__snapshots__/AegisComponentActions.spec.ts.snap is excluded by !**/*.snap
  • src/views/__tests__/__snapshots__/FlawCreateView.spec.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (16)
  • CHANGELOG.md
  • src/components/Aegis/AegisActions.vue
  • src/components/Aegis/AegisComponentActions.vue
  • src/components/Aegis/__tests__/AegisComponentActions.spec.ts
  • src/components/Aegis/__tests__/AegisCvssActions.spec.ts
  • src/components/Aegis/__tests__/AegisCweActions.spec.ts
  • src/components/Aegis/__tests__/AegisImpactActions.spec.ts
  • src/components/Aegis/__tests__/AegisMitigationActions.spec.ts
  • src/components/Aegis/__tests__/AegisStatementActions.spec.ts
  • src/components/FlawForm/FlawForm.vue
  • src/composables/__tests__/useAegisSuggestion.spec.ts
  • src/composables/aegis/__tests__/useAegisSuggestComponents.spec.ts
  • src/composables/aegis/useAISuggestionsWatcher.ts
  • src/composables/aegis/useAegisSuggestComponents.ts
  • src/composables/aegis/useAegisSuggestion.ts
  • src/types/aegisAI.ts
✅ Files skipped from review due to trivial changes (2)
  • CHANGELOG.md
  • src/composables/tests/useAegisSuggestion.spec.ts
🚧 Files skipped from review as they are similar to previous changes (6)
  • src/types/aegisAI.ts
  • src/components/Aegis/tests/AegisComponentActions.spec.ts
  • src/components/FlawForm/FlawForm.vue
  • src/composables/aegis/tests/useAegisSuggestComponents.spec.ts
  • src/components/Aegis/AegisActions.vue
  • src/composables/aegis/useAegisSuggestComponents.ts

Comment thread src/composables/aegis/useAegisSuggestion.ts
Comment thread src/composables/aegis/useAISuggestionsWatcher.ts
@C-Valen C-Valen force-pushed the feature/OSIDB-4996-aegis-component-suggestions branch from 42b2e8c to b0313c2 Compare June 4, 2026 14:16
Copy link
Copy Markdown

@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

Caution

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

⚠️ Outside diff range comments (1)
src/composables/aegis/useAegisSuggestion.ts (1)

287-291: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

components suggestions are flattened into per-item suggestions instead of one grouped suggestion.

For fieldName === 'components', Line 290 returns string[] directly. This makes currentSuggestion resolve to a single component string, so selection/feedback paths can operate on one item rather than the full suggested component set.

Proposed fix
 const allSuggestions = computed(() => {
   const fieldValue = details.value?.[detailsField];
   if (fieldValue === null || fieldValue === undefined) return [];
-  return Array.isArray(fieldValue) ? fieldValue : [fieldValue];
+  if (fieldName === 'components') {
+    return Array.isArray(fieldValue) ? [fieldValue] : [];
+  }
+  return Array.isArray(fieldValue) ? fieldValue : [fieldValue];
 });

Also applies to: 293-307

🤖 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/composables/aegis/useAegisSuggestion.ts` around lines 287 - 291, The
computed allSuggestions currently flattens the components array into individual
string suggestions, causing currentSuggestion to treat each component
separately; change the logic so when detailsField (or fieldName) ===
'components' you do not flatten arrays — if fieldValue is an array return
[fieldValue] (a single grouped suggestion) instead of fieldValue, and apply the
same grouping change in the similar block at lines 293-307 so selection/feedback
operate on the whole suggested component set rather than individual items.
🤖 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/composables/aegis/useAegisSuggestComponents.ts`:
- Around line 144-159: The sendFeedback function currently sets
userFeedbackSent.value = true unconditionally, so failures from sendFeedbackApi
block retries; modify sendFeedback (the async function sendFeedback in
useAegisSuggestComponents.ts) to only mark userFeedbackSent true when
sendFeedbackApi succeeds: call sendFeedbackApi inside a try/catch (or inspect
its returned result), set userFeedbackSent.value = true only on success, and
handle/log or rethrow errors in the catch so the UI can allow retries instead of
permanently marking feedback as sent.

---

Outside diff comments:
In `@src/composables/aegis/useAegisSuggestion.ts`:
- Around line 287-291: The computed allSuggestions currently flattens the
components array into individual string suggestions, causing currentSuggestion
to treat each component separately; change the logic so when detailsField (or
fieldName) === 'components' you do not flatten arrays — if fieldValue is an
array return [fieldValue] (a single grouped suggestion) instead of fieldValue,
and apply the same grouping change in the similar block at lines 293-307 so
selection/feedback operate on the whole suggested component set rather than
individual items.
🪄 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: CHILL

Plan: Enterprise

Run ID: 6d4c4a94-fb3e-4476-bcda-03325d8d9d18

📥 Commits

Reviewing files that changed from the base of the PR and between 1414e27 and b0313c2.

⛔ Files ignored due to path filters (3)
  • src/components/Aegis/__tests__/__snapshots__/AegisComponentActions.spec.ts.snap is excluded by !**/*.snap
  • src/components/__tests__/__snapshots__/FlawForm.spec.ts.snap is excluded by !**/*.snap
  • src/views/__tests__/__snapshots__/FlawCreateView.spec.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (16)
  • CHANGELOG.md
  • src/components/Aegis/AegisActions.vue
  • src/components/Aegis/AegisComponentActions.vue
  • src/components/Aegis/__tests__/AegisComponentActions.spec.ts
  • src/components/Aegis/__tests__/AegisCvssActions.spec.ts
  • src/components/Aegis/__tests__/AegisCweActions.spec.ts
  • src/components/Aegis/__tests__/AegisImpactActions.spec.ts
  • src/components/Aegis/__tests__/AegisMitigationActions.spec.ts
  • src/components/Aegis/__tests__/AegisStatementActions.spec.ts
  • src/components/FlawForm/FlawForm.vue
  • src/composables/__tests__/useAegisSuggestion.spec.ts
  • src/composables/aegis/__tests__/useAegisSuggestComponents.spec.ts
  • src/composables/aegis/useAISuggestionsWatcher.ts
  • src/composables/aegis/useAegisSuggestComponents.ts
  • src/composables/aegis/useAegisSuggestion.ts
  • src/types/aegisAI.ts
✅ Files skipped from review due to trivial changes (3)
  • CHANGELOG.md
  • src/composables/tests/useAegisSuggestion.spec.ts
  • src/components/Aegis/tests/AegisCweActions.spec.ts
🚧 Files skipped from review as they are similar to previous changes (10)
  • src/components/Aegis/tests/AegisImpactActions.spec.ts
  • src/components/Aegis/tests/AegisStatementActions.spec.ts
  • src/components/Aegis/tests/AegisMitigationActions.spec.ts
  • src/components/Aegis/AegisActions.vue
  • src/components/Aegis/tests/AegisCvssActions.spec.ts
  • src/composables/aegis/tests/useAegisSuggestComponents.spec.ts
  • src/components/FlawForm/FlawForm.vue
  • src/components/Aegis/tests/AegisComponentActions.spec.ts
  • src/types/aegisAI.ts
  • src/components/Aegis/AegisComponentActions.vue

Comment thread src/composables/aegis/useAegisSuggestComponents.ts
C-Valen and others added 4 commits June 4, 2026 17:04
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@C-Valen C-Valen force-pushed the feature/OSIDB-4996-aegis-component-suggestions branch from b0313c2 to 5a76eb6 Compare June 4, 2026 15:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants