Skip to content

refactor: use classification#18

Merged
MatteoGabriele merged 3 commits intomainfrom
dev
Mar 10, 2026
Merged

refactor: use classification#18
MatteoGabriele merged 3 commits intomainfrom
dev

Conversation

@MatteoGabriele
Copy link
Copy Markdown
Owner

@MatteoGabriele MatteoGabriele commented Mar 10, 2026

use classification instead of score calculation

Summary by CodeRabbit

  • Refactor
    • Switched from score-based to explicit classification display (organic, mixed, automation) for clearer analysis results.
    • Updated UI visuals and icons to reflect classification labels directly instead of numeric thresholds.
    • When classification is unavailable, the component now shows a clear "Analysis unavailable" fallback message.

@netlify
Copy link
Copy Markdown

netlify bot commented Mar 10, 2026

Deploy Preview for agentscan ready!

Name Link
🔨 Latest commit 4d9b4c9
🔍 Latest deploy log https://app.netlify.com/projects/agentscan/deploys/69afdc5d595e70000850e80b
😎 Deploy Preview https://deploy-preview-18--agentscan.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 10, 2026

📝 Walkthrough

Walkthrough

Migrates logic from numeric score thresholds to string-based IdentityClassification values ("organic" | "mixed" | "automation"); updates types, the identifyReplicant output, the composable API, and the Analysis Card component to consume and render based on classification strings.

Changes

Cohort / File(s) Summary
Type Definitions & Classifier
shared/types/identity.ts, shared/utils/voight-kampff-test/identify-replicant.ts
Renamed IdentityClassification literals from `"human"
Composable
app/composables/useClassificationDetails.ts
Signature changed to accept `IdentityClassification
UI Component
app/components/Analysis/Card.vue
Removed computed numeric score; added computed classification usage. Styling and icon selection now driven by classification equality checks ("organic", "mixed", default) via new ScoreStyle type. Calls useClassificationDetails(classification). CONFIG import/threshold logic removed.

Sequence Diagram(s)

sequenceDiagram
    participant Replicant as "identifyReplicant\n(shared util)"
    participant Composable as "useClassificationDetails\n(app/composables)"
    participant Component as "Analysis Card\n(app/components/Analysis/Card.vue)"

    rect rgba(200,230,255,0.5)
    Component->>Replicant: Request identity analysis (previously produced score)
    Replicant-->>Component: Return IdentityClassification ("organic"|"mixed"|"automation")
    end

    rect rgba(200,255,220,0.5)
    Component->>Composable: useClassificationDetails(classification)
    Composable-->>Component: Return label + description (or fallback)
    end

    rect rgba(255,240,200,0.5)
    Component->>Component: Render UI using classification -> select icon, text, border classes
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 I hopped from numbers to names in spring,
Organic bounces, mixed birds sing,
Automation hums a steady beat,
Icons and borders tap their feet,
A rabbit cheers this tidy string! 🥕✨

🚥 Pre-merge checks | ✅ 2 | ❌ 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 (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'refactor: use classification' directly summarizes the main change in the changeset, which is a comprehensive refactor replacing score-based logic with classification-based logic across multiple files.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dev

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.

Caution

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

⚠️ Outside diff range comments (1)
app/composables/useClassificationDetails.ts (1)

1-25: ⚠️ Potential issue | 🟡 Minor

Handle undefined separately from "automation".

The parameter explicitly allows undefined, but the fallback branch renders that as "Automation signals". That turns missing or partial analysis data into a false-positive classification. Add an explicit unavailable state here, and keep app/components/Analysis/Card.vue:42-92 aligned with the same branch.

Possible fix
 export function useClassificationDetails(
   classification: MaybeRefOrGetter<IdentityClassification | undefined>,
 ) {
   const classificationDetails = computed(() => {
     const classificationValue = toValue(classification);
+
+    if (!classificationValue) {
+      return {
+        label: "Analysis unavailable",
+        description: "Classification is not available for this account.",
+      };
+    }
 
     if (classificationValue === "organic") {
       return {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/composables/useClassificationDetails.ts` around lines 1 - 25, The
computed classificationDetails in useClassificationDetails currently treats
undefined the same as "automation"; update useClassificationDetails to add an
explicit branch for classificationValue === undefined (or null) that returns an
"Unavailable" or "Analysis incomplete" label/description so missing data is not
shown as "Automation signals"; keep the existing branches for "organic",
"mixed", and "automation" (or default) intact and ensure the returned shape
matches what app/components/Analysis/Card.vue expects so the Card.vue logic
(lines ~42-92) can render the unavailable state instead of a false positive.
🧹 Nitpick comments (2)
app/components/Analysis/Card.vue (1)

57-57: Remove the leftover debug log before merging.

This will fire during normal classification updates and adds avoidable console noise in production.

Cleanup
-  console.log(classification.value);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/components/Analysis/Card.vue` at line 57, Remove the leftover debug log
by deleting the console.log call that references classification.value in the
Analysis Card component; specifically remove the line
"console.log(classification.value)" from the Card.vue script so classification
updates no longer produce noisy console output in production.
shared/types/identity.ts (1)

21-21: Treat the renamed union as a contract change.

analysis.classification now serializes different literal values. If anything outside this app consumes that response, ship a compatibility note or version this change instead of treating it as a no-op refactor.

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

In `@shared/types/identity.ts` at line 21, The union type IdentityClassification
was changed to new literal values which is a contract-breaking change for any
external consumers reading analysis.classification; either revert the rename to
preserve the original literals or implement a backward-compatible serialization
layer that maps the new IdentityClassification values to the previous values at
output (e.g., in the code that serializes analysis.classification), and add a
compatibility note / API version bump; locate the type IdentityClassification
and any serialization paths that emit analysis.classification and update them to
perform the mapping or revert the type change accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@app/composables/useClassificationDetails.ts`:
- Around line 1-25: The computed classificationDetails in
useClassificationDetails currently treats undefined the same as "automation";
update useClassificationDetails to add an explicit branch for
classificationValue === undefined (or null) that returns an "Unavailable" or
"Analysis incomplete" label/description so missing data is not shown as
"Automation signals"; keep the existing branches for "organic", "mixed", and
"automation" (or default) intact and ensure the returned shape matches what
app/components/Analysis/Card.vue expects so the Card.vue logic (lines ~42-92)
can render the unavailable state instead of a false positive.

---

Nitpick comments:
In `@app/components/Analysis/Card.vue`:
- Line 57: Remove the leftover debug log by deleting the console.log call that
references classification.value in the Analysis Card component; specifically
remove the line "console.log(classification.value)" from the Card.vue script so
classification updates no longer produce noisy console output in production.

In `@shared/types/identity.ts`:
- Line 21: The union type IdentityClassification was changed to new literal
values which is a contract-breaking change for any external consumers reading
analysis.classification; either revert the rename to preserve the original
literals or implement a backward-compatible serialization layer that maps the
new IdentityClassification values to the previous values at output (e.g., in the
code that serializes analysis.classification), and add a compatibility note /
API version bump; locate the type IdentityClassification and any serialization
paths that emit analysis.classification and update them to perform the mapping
or revert the type change accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4c048606-4d75-440f-8134-d276fafbaa65

📥 Commits

Reviewing files that changed from the base of the PR and between d22d20e and 98a3d4e.

⛔ Files ignored due to path filters (1)
  • test/__snapshots__/verified-automations.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (4)
  • app/components/Analysis/Card.vue
  • app/composables/useClassificationDetails.ts
  • shared/types/identity.ts
  • shared/utils/voight-kampff-test/identify-replicant.ts

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.

🧹 Nitpick comments (2)
app/components/Analysis/Card.vue (1)

48-98: Collapse the visual state into classification metadata.

ScoreStyle / scoreStyle still use the old score terminology, and the "organic" / "mixed" branching is duplicated across both scoreStyle and classificationIcon. A single classification visual map would make this easier to extend and harder to drift.

♻️ Suggested refactor
-type ScoreStyle = {
+type ClassificationVisual = {
   text: string;
   border: string;
+  icon: string;
 };
 
-const scoreStyle = computed<ScoreStyle>(() => {
-  if (hasCommunityFlag.value) {
-    return {
-      text: "text-gh-danger",
-      border: "border-gh-danger",
-    };
-  }
-
-  if (!classification.value) {
-    return {
-      text: "text-gray-500",
-      border: "border-gray-500",
-    };
-  }
-
-  if (classification.value === "organic") {
-    return {
-      text: "text-green-500",
-      border: "border-green-500",
-    };
-  }
-
-  if (classification.value === "mixed") {
-    return {
-      text: "text-amber-500",
-      border: "border-amber-500",
-    };
-  }
-
-  return {
-    text: "text-orange-500",
-    border: "border-orange-500",
-  };
-});
-
-const classificationIcon = computed<string>(() => {
-  if (classification.value === "organic") {
-    return "i-carbon:growth";
-  }
-
-  if (classification.value === "mixed") {
-    return "i-carbon:activity";
-  }
-
-  return "i-carbon:meter-alt";
-});
+const CLASSIFICATION_VISUALS: Record<
+  IdentityClassification,
+  ClassificationVisual
+> = {
+  organic: {
+    text: "text-green-500",
+    border: "border-green-500",
+    icon: "i-carbon:growth",
+  },
+  mixed: {
+    text: "text-amber-500",
+    border: "border-amber-500",
+    icon: "i-carbon:activity",
+  },
+  automation: {
+    text: "text-orange-500",
+    border: "border-orange-500",
+    icon: "i-carbon:meter-alt",
+  },
+};
+
+const classificationVisual = computed<ClassificationVisual>(() => {
+  if (hasCommunityFlag.value) {
+    return {
+      text: "text-gh-danger",
+      border: "border-gh-danger",
+      icon: "i-carbon:meter-alt",
+    };
+  }
+
+  if (!classification.value) {
+    return {
+      text: "text-gray-500",
+      border: "border-gray-500",
+      icon: "i-carbon:meter-alt",
+    };
+  }
+
+  return CLASSIFICATION_VISUALS[classification.value];
+});

Then update the template bindings to classificationVisual.border, classificationVisual.text, and classificationVisual.icon.

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

In `@app/components/Analysis/Card.vue` around lines 48 - 98, The UI state is
duplicated between ScoreStyle/scoreStyle and classificationIcon; replace them
with a single classificationVisual map/object keyed by classification values
(and community flag) that returns { text, border, icon } to centralize visuals,
update references from scoreStyle and classificationIcon to
classificationVisual, and change template bindings to use
classificationVisual.border, classificationVisual.text, and
classificationVisual.icon (ensure you still handle the hasCommunityFlag override
in the new mapping).
app/composables/useClassificationDetails.ts (1)

19-37: Make this mapping exhaustive instead of defaulting to automation.

The final fallback currently treats every non-"organic"/"mixed" value as automation. That works for the current union, but it will silently mislabel future literals or stale payloads after another enum rename. A typed Record<IdentityClassification, ClassificationDetails> would keep this compile-time checked.

♻️ Suggested refactor
+const CLASSIFICATION_DETAILS: Record<
+  IdentityClassification,
+  ClassificationDetails
+> = {
+  organic: {
+    label: "Organic activity",
+    description: "No automation signals detected in the analyzed events.",
+  },
+  mixed: {
+    label: "Mixed activity",
+    description:
+      "Activity patterns show a mix of organic and automated signals.",
+  },
+  automation: {
+    label: "Automation signals",
+    description: "Activity patterns show signs of automation.",
+  },
+};
+
 export function useClassificationDetails(
   classification: MaybeRefOrGetter<IdentityClassification | undefined>,
 ) {
   const classificationDetails = computed<ClassificationDetails>(() => {
     const classificationValue = toValue(classification);
@@
-    if (classificationValue === "organic") {
-      return {
-        label: "Organic activity",
-        description: "No automation signals detected in the analyzed events.",
-      };
-    }
-
-    if (classificationValue === "mixed") {
-      return {
-        label: "Mixed activity",
-        description:
-          "Activity patterns show a mix of organic and automated signals.",
-      };
-    }
-
-    return {
-      label: "Automation signals",
-      description: "Activity patterns show signs of automation.",
-    };
+    return CLASSIFICATION_DETAILS[classificationValue];
   });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/composables/useClassificationDetails.ts` around lines 19 - 37, Replace
the ad-hoc if/return chain in useClassificationDetails (the classificationValue
handling) with a typed mapping: define a const mapping of type
Record<IdentityClassification, ClassificationDetails> that explicitly lists
entries for each IdentityClassification literal (e.g., "organic", "mixed",
"automation" or whatever the union contains), then return
mapping[classificationValue]; add a safe fallback for unknown values (e.g.,
return a neutral/unknown ClassificationDetails or throw an error) so future/new
enum literals won’t be silently treated as automation. Ensure you reference the
types IdentityClassification and ClassificationDetails for compile-time
exhaustiveness.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@app/components/Analysis/Card.vue`:
- Around line 48-98: The UI state is duplicated between ScoreStyle/scoreStyle
and classificationIcon; replace them with a single classificationVisual
map/object keyed by classification values (and community flag) that returns {
text, border, icon } to centralize visuals, update references from scoreStyle
and classificationIcon to classificationVisual, and change template bindings to
use classificationVisual.border, classificationVisual.text, and
classificationVisual.icon (ensure you still handle the hasCommunityFlag override
in the new mapping).

In `@app/composables/useClassificationDetails.ts`:
- Around line 19-37: Replace the ad-hoc if/return chain in
useClassificationDetails (the classificationValue handling) with a typed
mapping: define a const mapping of type Record<IdentityClassification,
ClassificationDetails> that explicitly lists entries for each
IdentityClassification literal (e.g., "organic", "mixed", "automation" or
whatever the union contains), then return mapping[classificationValue]; add a
safe fallback for unknown values (e.g., return a neutral/unknown
ClassificationDetails or throw an error) so future/new enum literals won’t be
silently treated as automation. Ensure you reference the types
IdentityClassification and ClassificationDetails for compile-time
exhaustiveness.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 84bf9615-1d0d-4238-8377-59f10de03d4d

📥 Commits

Reviewing files that changed from the base of the PR and between 98a3d4e and 4d9b4c9.

📒 Files selected for processing (2)
  • app/components/Analysis/Card.vue
  • app/composables/useClassificationDetails.ts

@MatteoGabriele MatteoGabriele merged commit 1daf9e2 into main Mar 10, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant