Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,6 @@ coverage/
*.pid
*.seed
*.pem

# Sentry Config File
.env.sentry-build-plugin
4 changes: 2 additions & 2 deletions .release-please-manifest.develop.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
".": "0.1.0-alpha.11",
"apps/web": "0.1.0-alpha.11",
".": "0.1.0-alpha.13",
"apps/web": "0.1.0-alpha.13",
"apps/worker": "0.1.0-alpha.3"
}
2 changes: 1 addition & 1 deletion Agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ This document provides instructions for AI agents working on the Vibed Coding co
See `docs/PRD.md` for full product requirements and `docs/architecture/inngest-integration.md` for job processing details.

**Key Reference Docs:**
- [How Vibed Works](docs/how-vibed-works.md) β€” Product-friendly explanation of analysis
- [How Vibe Coding Profile Works](docs/how-vibe-coding-profile-works.md) β€” Product-friendly explanation of analysis
- [Vibed Analysis Pipeline](docs/architecture/vibed-analysis-pipeline.md) β€” Technical architecture with algorithms and data flow

---
Expand Down
19 changes: 19 additions & 0 deletions CHANGELOG-DEVELOP.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
# Changelog

## [0.1.0-alpha.13](https://github.com/devakone/vibe-coding-profiler/compare/vibe-coding-profiler-v0.1.0-alpha.12...vibe-coding-profiler-v0.1.0-alpha.13) (2026-02-12)


### Features

* **analysis:** dampen initial/bulk commits in Automation axis ([2c2cf47](https://github.com/devakone/vibe-coding-profiler/commit/2c2cf472c31e24e3ce7e1c6fa5e6b389a4c16a5e))


### Bug Fixes

* add disconnect button to repos settings page ([a349c67](https://github.com/devakone/vibe-coding-profiler/commit/a349c67e5b53aa78fee86bb13f83f2eab22253fa))

## [0.1.0-alpha.12](https://github.com/devakone/vibe-coding-profiler/compare/vibe-coding-profiler-v0.1.0-alpha.11...vibe-coding-profiler-v0.1.0-alpha.12) (2026-02-12)


### Features

* add Sentry error tracking ([71d09da](https://github.com/devakone/vibe-coding-profiler/commit/71d09da398280deb2198635e2a21e050e0624552))

## [0.1.0-alpha.11](https://github.com/devakone/vibe-coding-profiler/compare/vibe-coding-profiler-v0.1.0-alpha.10...vibe-coding-profiler-v0.1.0-alpha.11) (2026-02-01)


Expand Down
19 changes: 19 additions & 0 deletions apps/web/CHANGELOG-DEVELOP.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
# Changelog

## [0.1.0-alpha.13](https://github.com/devakone/vibe-coding-profiler/compare/web-v0.1.0-alpha.12...web-v0.1.0-alpha.13) (2026-02-12)


### Features

* **analysis:** dampen initial/bulk commits in Automation axis ([2c2cf47](https://github.com/devakone/vibe-coding-profiler/commit/2c2cf472c31e24e3ce7e1c6fa5e6b389a4c16a5e))


### Bug Fixes

* add disconnect button to repos settings page ([a349c67](https://github.com/devakone/vibe-coding-profiler/commit/a349c67e5b53aa78fee86bb13f83f2eab22253fa))

## [0.1.0-alpha.12](https://github.com/devakone/vibe-coding-profiler/compare/web-v0.1.0-alpha.11...web-v0.1.0-alpha.12) (2026-02-12)


### Features

* add Sentry error tracking ([71d09da](https://github.com/devakone/vibe-coding-profiler/commit/71d09da398280deb2198635e2a21e050e0624552))

## [0.1.0-alpha.11](https://github.com/devakone/vibe-coding-profiler/compare/web-v0.1.0-alpha.10...web-v0.1.0-alpha.11) (2026-02-01)


Expand Down
31 changes: 31 additions & 0 deletions apps/web/instrumentation-client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// This file configures the initialization of Sentry on the client.
// The added config here will be used whenever a users loads a page in their browser.
// https://docs.sentry.io/platforms/javascript/guides/nextjs/

import * as Sentry from "@sentry/nextjs";

Sentry.init({
dsn: "https://0ddc11d7b3f42d5ca32ecf0b74ff61ef@o4510870266118144.ingest.us.sentry.io/4510870274899968",

// Add optional integrations for additional features
integrations: [Sentry.replayIntegration()],

// Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control.
tracesSampleRate: 1,
// Enable logs to be sent to Sentry
enableLogs: true,

// Define how likely Replay events are sampled.
// This sets the sample rate to be 10%. You may want this to be 100% while
// in development and sample at a lower rate in production
replaysSessionSampleRate: 0.1,

// Define how likely Replay events are sampled when an error occurs.
replaysOnErrorSampleRate: 1.0,

// Enable sending user PII (Personally Identifiable Information)
// https://docs.sentry.io/platforms/javascript/guides/nextjs/configuration/options/#sendDefaultPii
sendDefaultPii: true,
});

export const onRouterTransitionStart = Sentry.captureRouterTransitionStart;
13 changes: 13 additions & 0 deletions apps/web/instrumentation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import * as Sentry from "@sentry/nextjs";

export async function register() {
if (process.env.NEXT_RUNTIME === "nodejs") {
await import("./sentry.server.config");
}

if (process.env.NEXT_RUNTIME === "edge") {
await import("./sentry.edge.config");
}
}

export const onRequestError = Sentry.captureRequestError;
17 changes: 16 additions & 1 deletion apps/web/next.config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { withSentryConfig } from "@sentry/nextjs";
import type { NextConfig } from "next";
import path from "node:path";

Expand Down Expand Up @@ -34,4 +35,18 @@ const nextConfig: NextConfig = {
},
};

export default nextConfig;
export default withSentryConfig(nextConfig, {
// For all available options, see:
// https://www.npmjs.com/package/@sentry/webpack-plugin#options
org: "100kode",
project: "javascript-nextjs",

// Only print logs for uploading source maps in CI
silent: !process.env.CI,

// Upload a larger set of source maps for prettier stack traces (increases build time)
widenClientFileUpload: true,

// Route browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers.
tunnelRoute: "/monitoring",
});
1 change: 1 addition & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"test:watch": "vitest"
},
"dependencies": {
"@sentry/nextjs": "^10.38.0",
"@radix-ui/react-dropdown-menu": "^2.1.16",
"@radix-ui/react-popover": "^1.1.15",
"@radix-ui/react-toast": "^1.2.15",
Expand Down
20 changes: 20 additions & 0 deletions apps/web/sentry.edge.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// This file configures the initialization of Sentry for edge features (middleware, edge routes, and so on).
// The config you add here will be used whenever one of the edge features is loaded.
// Note that this config is unrelated to the Vercel Edge Runtime and is also required when running locally.
// https://docs.sentry.io/platforms/javascript/guides/nextjs/

import * as Sentry from "@sentry/nextjs";

Sentry.init({
dsn: "https://0ddc11d7b3f42d5ca32ecf0b74ff61ef@o4510870266118144.ingest.us.sentry.io/4510870274899968",

// Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control.
tracesSampleRate: 1,

// Enable logs to be sent to Sentry
enableLogs: true,

// Enable sending user PII (Personally Identifiable Information)
// https://docs.sentry.io/platforms/javascript/guides/nextjs/configuration/options/#sendDefaultPii
sendDefaultPii: true,
});
19 changes: 19 additions & 0 deletions apps/web/sentry.server.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// This file configures the initialization of Sentry on the server.
// The config you add here will be used whenever the server handles a request.
// https://docs.sentry.io/platforms/javascript/guides/nextjs/

import * as Sentry from "@sentry/nextjs";

Sentry.init({
dsn: "https://0ddc11d7b3f42d5ca32ecf0b74ff61ef@o4510870266118144.ingest.us.sentry.io/4510870274899968",

// Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control.
tracesSampleRate: 1,

// Enable logs to be sent to Sentry
enableLogs: true,

// Enable sending user PII (Personally Identifiable Information)
// https://docs.sentry.io/platforms/javascript/guides/nextjs/configuration/options/#sendDefaultPii
sendDefaultPii: true,
});
10 changes: 7 additions & 3 deletions apps/web/src/app/methodology/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
id: "A",
name: "Automation",
description:
"Large, wide changes: high files-changed per commit, big commits, big PRs.",
"Large, wide changes: high files-changed per commit, big commits, big PRs. Initial/bulk commits are dampened to avoid skewing small repos.",
},
{
id: "B",
Expand Down Expand Up @@ -186,8 +186,12 @@
copy/paste, refactors between commits), so we infer from what lands in Git.
</li>
<li>
Different projects can pull you into different modes; aggregation may β€œaverage you
out”.
Different projects can pull you into different modes; aggregation may "average you

Check failure on line 189 in apps/web/src/app/methodology/page.tsx

View workflow job for this annotation

GitHub Actions / lint-and-build

`"` can be escaped with `&quot;`, `&ldquo;`, `&#34;`, `&rdquo;`

Check failure on line 189 in apps/web/src/app/methodology/page.tsx

View workflow job for this annotation

GitHub Actions / lint-and-build

`"` can be escaped with `&quot;`, `&ldquo;`, `&#34;`, `&rdquo;`
out".

Check failure on line 190 in apps/web/src/app/methodology/page.tsx

View workflow job for this annotation

GitHub Actions / lint-and-build

`"` can be escaped with `&quot;`, `&ldquo;`, `&#34;`, `&rdquo;`

Check failure on line 190 in apps/web/src/app/methodology/page.tsx

View workflow job for this annotation

GitHub Actions / lint-and-build

`"` can be escaped with `&quot;`, `&ldquo;`, `&#34;`, `&rdquo;`
</li>
<li>
We dampen initial and bulk commits in the Automation axis, but repos with very few
commits (&lt;10) may still show unusual scores.
</li>
</ul>
</section>
Expand Down
74 changes: 60 additions & 14 deletions apps/web/src/app/repos/ReposClient.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { useCallback, useEffect, useMemo, useState } from "react";
import { useRouter } from "next/navigation";
import { ChevronsUpDown, RefreshCw } from "lucide-react";
import { ChevronsUpDown, RefreshCw, Trash2 } from "lucide-react";
import { cn } from "@/lib/utils";
import { wrappedTheme } from "@/lib/theme";
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@/components/ui/command";
Expand Down Expand Up @@ -204,6 +204,39 @@ export default function ReposClient({
}
}

const [disconnecting, setDisconnecting] = useState<string | null>(null);

async function disconnectRepo(repoId: string, repoName: string) {
if (!confirm(`Disconnect "${repoName}"? This will remove it from your profile but won't delete any analysis data.`)) {
return;
}

setDisconnecting(repoId);
try {
const response = await fetch("/api/repos/disconnect", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ repo_id: repoId }),
});

if (!response.ok) {
const body = await response.json();
throw new Error(body.error || "Could not disconnect repo");
}

toast({ title: "Repo disconnected", description: `${repoName} has been removed.` });
router.refresh();
} catch (error) {
toast({
variant: "destructive",
title: "Disconnect failed",
description: error instanceof Error ? error.message : "Please try again",
});
} finally {
setDisconnecting(null);
}
}

const connectedRepos = initialConnected.map((repo) => ({
...repo,
latestJobId: latestJobByRepoId[repo.repo_id] ?? null,
Expand Down Expand Up @@ -300,27 +333,40 @@ export default function ReposClient({
<span className="text-sm font-semibold text-zinc-900">{repo.full_name}</span>
{repo.latestJobId && <span className="text-[11px] text-zinc-500">Analyzed</span>}
</div>
{/* Only show action buttons in vibes mode */}
{mode === "vibes" && (
<div className="flex items-center gap-2">
{repo.latestJobId ? (
{/* Action buttons differ by mode */}
<div className="flex items-center gap-2">
{mode === "vibes" && (
<>
{repo.latestJobId ? (
<button
type="button"
className={cn(wrappedTheme.secondaryButton, "px-3 py-1 text-sm font-semibold")}
onClick={() => router.push(`/analysis/${repo.latestJobId}`)}
>
View vibe
</button>
) : null}
<button
type="button"
className={cn(wrappedTheme.secondaryButton, "px-3 py-1 text-sm font-semibold")}
onClick={() => router.push(`/analysis/${repo.latestJobId}`)}
className="rounded-full border border-zinc-300/80 bg-white/70 px-3 py-1 text-sm font-semibold text-zinc-950 shadow-sm hover:bg-white"
onClick={() => startAnalysis(repo.repo_id, repo.full_name)}
>
View vibe
{repo.latestJobId ? "Re-run" : "Start vibe"}
</button>
) : null}
</>
)}
{mode === "settings" && (
<button
type="button"
className="rounded-full border border-zinc-300/80 bg-white/70 px-3 py-1 text-sm font-semibold text-zinc-950 shadow-sm hover:bg-white"
onClick={() => startAnalysis(repo.repo_id, repo.full_name)}
className="flex items-center gap-1.5 rounded-full border border-red-200 bg-white px-3 py-1 text-sm font-semibold text-red-600 transition hover:bg-red-50 hover:border-red-300 disabled:opacity-50"
onClick={() => disconnectRepo(repo.repo_id, repo.full_name)}
disabled={disconnecting === repo.repo_id}
>
{repo.latestJobId ? "Re-run" : "Start vibe"}
<Trash2 className="h-3.5 w-3.5" />
{disconnecting === repo.repo_id ? "Removing…" : "Remove"}
</button>
</div>
)}
)}
</div>
</div>
))}
</div>
Expand Down
4 changes: 2 additions & 2 deletions docs/architecture/ai-tool-metrics.md
Original file line number Diff line number Diff line change
Expand Up @@ -239,9 +239,9 @@ Returns `null` when `!detected || tools.length === 0`.
## Related Documentation

- [Multi-Agent Detection PRD](../prd/analysis/multi-agent-detection.md) β€” Signal extraction phases
- [Vibe Metrics v2](./vibe-metrics-v2.md) β€” Core axis computation
- [Vibe Coding Profile Metrics v2](./vibe-coding-profile-metrics-v2.md) β€” Core axis computation
- [Analysis Pipeline](./vibed-analysis-pipeline.md) β€” End-to-end architecture
- [How VCP Works](../how-vibed-works.md) β€” Product-facing overview
- [How Vibe Coding Profile Works](../how-vibe-coding-profile-works.md) β€” Product-facing overview

---

Expand Down
2 changes: 1 addition & 1 deletion docs/architecture/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
This document explains how the Vibe Coding Profile stack fits together, how data flows from a logged-in user through Supabase, the worker, and the UI, and which pieces of the codebase (web, worker, packages) own each responsibility. The diagrams use Mermaid syntax so you can paste them into any renderer, but the textual explanations also narrate every interaction.

> **Related Documentation:**
> - [How Vibe Coding Profile Works](../how-vibed-works.md) β€” Product-friendly explanation
> - [How Vibe Coding Profile Works](../how-vibe-coding-profile-works.md) β€” Product-friendly explanation
> - [Vibe Coding Profile Analysis Pipeline](./vibed-analysis-pipeline.md) β€” Detailed analysis algorithms and data flow
> - [Inngest Integration](./inngest-integration.md) β€” Background job processing

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,26 @@ How "agentic" the workflow looks.

**Score formula:**
```
40% - Commit chunkiness (avg_files_changed, commit_size_p90)
40% - PR chunkiness (pr_files_changed_p90, commits_per_pr_p90)
20% - Text templating score
50% - Commit chunkiness (weighted_avg_files_changed, commit_size_p90)
30% - p90 commit size
20% - PR chunkiness (pr_files_changed_p90)
```

**Initial/Bulk Commit Dampening:**

To prevent initial project commits and bulk operations from skewing the Automation score, we apply weight dampening when calculating `weighted_avg_files_changed`:

```typescript
// Weight assignment per commit:
weight = 1.0; // default
if (isFirstCommit) weight = 0.25; // scaffolding likely
else if (files_changed > maxFiles * 0.5 && maxFiles > 20) weight = 0.5; // bulk op

// Then: weighted_avg = sum(files * weight) / sum(weight)
```

This ensures small repos with large initial commits (e.g., committing an entire create-react-app scaffold) don't get marked as "AI-heavy" based on that single data point.

**Evidence examples:**
- "Top 10% PRs change 40+ files"
- "Median commit touches 6 files"
Expand Down
4 changes: 2 additions & 2 deletions docs/architecture/vibed-analysis-pipeline.md
Original file line number Diff line number Diff line change
Expand Up @@ -828,8 +828,8 @@ erDiagram

## Related Documentation

- [How Vibe Coding Profile Works (Product Overview)](../how-vibed-works.md)
- [Vibe Metrics v2](./vibe-metrics-v2.md) β€” Original axis design
- [How Vibe Coding Profile Works (Product Overview)](../how-vibe-coding-profile-works.md)
- [Vibe Coding Profile Metrics v2](./vibe-coding-profile-metrics-v2.md) β€” Original axis design
- [Inngest Integration](./inngest-integration.md) β€” Job processing details
- [Architecture Overview](./overview.md) β€” System components
- [AI Tool Metrics](./ai-tool-metrics.md) β€” Tool detection pipeline and registry
Expand Down
Loading
Loading