vibe-roast 0.98.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. package/README.md +418 -0
  2. package/assests/README.md +43 -0
  3. package/assests/badges/.gitkeep +0 -0
  4. package/assests/badges/01-builder/builder-badge.png +0 -0
  5. package/assests/badges/01-builder/builder-badge.svg +4 -0
  6. package/assests/badges/02-debugger/debugger-badge.png +0 -0
  7. package/assests/badges/02-debugger/debugger-badge.svg +4 -0
  8. package/assests/badges/03-architect/architect-badge.png +0 -0
  9. package/assests/badges/03-architect/architect-badge.svg +4 -0
  10. package/assests/badges/04-codex-believer/codex-believer-badge.png +0 -0
  11. package/assests/badges/04-codex-believer/codex-believer-badge.svg +4 -0
  12. package/assests/badges/05-prompt-priest/prompt-priest-badge.png +0 -0
  13. package/assests/badges/05-prompt-priest/prompt-priest-badge.svg +4 -0
  14. package/assests/badges/06-tab-hoarder/tab-hoarder-badge.png +0 -0
  15. package/assests/badges/06-tab-hoarder/tab-hoarder-badge.svg +4 -0
  16. package/assests/badges/07-context-maxxer/context-maxxer-badge.png +0 -0
  17. package/assests/badges/07-context-maxxer/context-maxxer-badge.svg +4 -0
  18. package/assests/badges/08-yolo-shipper/yolo-shipper-badge.png +0 -0
  19. package/assests/badges/08-yolo-shipper/yolo-shipper-badge.svg +4 -0
  20. package/assests/banners/.gitkeep +0 -0
  21. package/assests/banners/home-hero.png +0 -0
  22. package/assests/banners/home-hero.svg +3 -0
  23. package/assests/banners/result-header.png +0 -0
  24. package/assests/banners/result-header.svg +3 -0
  25. package/assests/banners/share-strip.png +0 -0
  26. package/assests/banners/share-strip.svg +3 -0
  27. package/assests/characters/01-builder/builder-card.sbti-archive.svg +5 -0
  28. package/assests/characters/01-builder/builder-card.svg +3 -0
  29. package/assests/characters/01-builder/builder-character.sbti-archive.svg +3 -0
  30. package/assests/characters/01-builder/builder-character.svg +3 -0
  31. package/assests/characters/01-builder/builder-figure.png +0 -0
  32. package/assests/characters/01-builder/builder-mascot.png +0 -0
  33. package/assests/characters/02-debugger/debugger-card.sbti-archive.svg +5 -0
  34. package/assests/characters/02-debugger/debugger-card.svg +3 -0
  35. package/assests/characters/02-debugger/debugger-character.sbti-archive.svg +3 -0
  36. package/assests/characters/02-debugger/debugger-character.svg +3 -0
  37. package/assests/characters/02-debugger/debugger-figure.png +0 -0
  38. package/assests/characters/02-debugger/debugger-mascot.png +0 -0
  39. package/assests/characters/03-architect/architect-card.sbti-archive.svg +5 -0
  40. package/assests/characters/03-architect/architect-card.svg +3 -0
  41. package/assests/characters/03-architect/architect-character.sbti-archive.svg +3 -0
  42. package/assests/characters/03-architect/architect-character.svg +3 -0
  43. package/assests/characters/03-architect/architect-figure.png +0 -0
  44. package/assests/characters/03-architect/architect-mascot.png +0 -0
  45. package/assests/characters/04-codex-believer/codex-believer-card.sbti-archive.svg +5 -0
  46. package/assests/characters/04-codex-believer/codex-believer-card.svg +3 -0
  47. package/assests/characters/04-codex-believer/codex-believer-character.sbti-archive.svg +3 -0
  48. package/assests/characters/04-codex-believer/codex-believer-character.svg +3 -0
  49. package/assests/characters/04-codex-believer/codex-believer-figure.png +0 -0
  50. package/assests/characters/04-codex-believer/codex-believer-mascot.png +0 -0
  51. package/assests/characters/05-prompt-priest/prompt-priest-card.sbti-archive.svg +5 -0
  52. package/assests/characters/05-prompt-priest/prompt-priest-card.svg +3 -0
  53. package/assests/characters/05-prompt-priest/prompt-priest-character.sbti-archive.svg +3 -0
  54. package/assests/characters/05-prompt-priest/prompt-priest-character.svg +3 -0
  55. package/assests/characters/05-prompt-priest/prompt-priest-figure.png +0 -0
  56. package/assests/characters/05-prompt-priest/prompt-priest-mascot.png +0 -0
  57. package/assests/characters/06-tab-hoarder/tab-hoarder-card.sbti-archive.svg +5 -0
  58. package/assests/characters/06-tab-hoarder/tab-hoarder-card.svg +3 -0
  59. package/assests/characters/06-tab-hoarder/tab-hoarder-character.sbti-archive.svg +3 -0
  60. package/assests/characters/06-tab-hoarder/tab-hoarder-character.svg +3 -0
  61. package/assests/characters/06-tab-hoarder/tab-hoarder-figure.png +0 -0
  62. package/assests/characters/06-tab-hoarder/tab-hoarder-mascot.png +0 -0
  63. package/assests/characters/07-context-maxxer/context-maxxer-card.sbti-archive.svg +5 -0
  64. package/assests/characters/07-context-maxxer/context-maxxer-card.svg +3 -0
  65. package/assests/characters/07-context-maxxer/context-maxxer-character.sbti-archive.svg +3 -0
  66. package/assests/characters/07-context-maxxer/context-maxxer-character.svg +3 -0
  67. package/assests/characters/07-context-maxxer/context-maxxer-figure.png +0 -0
  68. package/assests/characters/07-context-maxxer/context-maxxer-mascot.png +0 -0
  69. package/assests/characters/08-yolo-shipper/yolo-shipper-card.sbti-archive.svg +5 -0
  70. package/assests/characters/08-yolo-shipper/yolo-shipper-card.svg +3 -0
  71. package/assests/characters/08-yolo-shipper/yolo-shipper-character.sbti-archive.svg +3 -0
  72. package/assests/characters/08-yolo-shipper/yolo-shipper-character.svg +3 -0
  73. package/assests/characters/08-yolo-shipper/yolo-shipper-figure.png +0 -0
  74. package/assests/characters/08-yolo-shipper/yolo-shipper-mascot.png +0 -0
  75. package/assests/characters-vibe-types/aosf-strategy-shipper/strategy-shipper-figure.png +0 -0
  76. package/assests/characters-vibe-types/aosx-agent-believer/agent-believer-figure.png +0 -0
  77. package/assests/characters-vibe-types/aovf-systems-architect/systems-architect-figure.png +0 -0
  78. package/assests/characters-vibe-types/aovx-context-cartographer/context-cartographer-figure.png +0 -0
  79. package/assests/characters-vibe-types/apsf-diagram-sprinter/diagram-sprinter-figure.png +0 -0
  80. package/assests/characters-vibe-types/apsx-infinite-planner/infinite-planner-figure.png +0 -0
  81. package/assests/characters-vibe-types/apvf-architect/architect-figure.png +0 -0
  82. package/assests/characters-vibe-types/apvx-prompt-priest/prompt-priest-figure.png +0 -0
  83. package/assests/characters-vibe-types/mosf-yolo-shipper/yolo-shipper-figure.png +0 -0
  84. package/assests/characters-vibe-types/mosx-agent-commander/agent-commander-figure.png +0 -0
  85. package/assests/characters-vibe-types/movf-agent-engineer/agent-engineer-figure.png +0 -0
  86. package/assests/characters-vibe-types/movx-systems-wrangler/systems-wrangler-figure.png +0 -0
  87. package/assests/characters-vibe-types/mpsf-builder/builder-figure.png +0 -0
  88. package/assests/characters-vibe-types/mpsx-tab-hoarder/tab-hoarder-figure.png +0 -0
  89. package/assests/characters-vibe-types/mpvf-debugger/debugger-figure.png +0 -0
  90. package/assests/characters-vibe-types/mpvx-context-maxxer/context-maxxer-figure.png +0 -0
  91. package/assests/live-report.html +1403 -0
  92. package/assests/notes/live-inspect-summary.json +3487 -0
  93. package/assests/scripts/compose-banners.py +148 -0
  94. package/assests/scripts/live-report-boot.js +2 -0
  95. package/assests/scripts/profiles.json +104 -0
  96. package/assests/scripts/qa-faces.mjs +72 -0
  97. package/assests/scripts/roast-extras.js +619 -0
  98. package/assests/scripts/score-engine.js +62 -0
  99. package/assests/scripts/split-badges.py +49 -0
  100. package/assests/scripts/split-reference.py +38 -0
  101. package/assests/scripts/sync-banners.mjs +45 -0
  102. package/assests/scripts/sync-cards.mjs +50 -0
  103. package/assests/scripts/sync-raster.mjs +118 -0
  104. package/assests/scripts/vibe-types.json +22 -0
  105. package/assests/source/design-system.md +50 -0
  106. package/assests/source/prompts/01-builder.md +19 -0
  107. package/assests/source/prompts/02-debugger.md +17 -0
  108. package/assests/source/prompts/03-architect.md +16 -0
  109. package/assests/source/prompts/04-codex-believer.md +13 -0
  110. package/assests/source/prompts/05-prompt-priest.md +13 -0
  111. package/assests/source/prompts/06-tab-hoarder.md +13 -0
  112. package/assests/source/prompts/07-context-maxxer.md +13 -0
  113. package/assests/source/prompts/08-yolo-shipper.md +13 -0
  114. package/assests/source/references/sbti-style-reference-board.png +0 -0
  115. package/assests/source/references/vibe-badges-v6-board.png +0 -0
  116. package/assests/source/references/vibe-mascots-v4-reference.png +0 -0
  117. package/assests/source/references/vibe-profiles-v5-board-a.png +0 -0
  118. package/assests/source/references/vibe-profiles-v5-board-b.png +0 -0
  119. package/assests/source/vibe-types-visual-brief.md +38 -0
  120. package/bin/hook.js +121 -0
  121. package/bin/vibe-roast.js +98 -0
  122. package/bin/vibe-wrapper.js +4 -0
  123. package/dashboard/dist/assets/index-DlBycTcO.css +1 -0
  124. package/dashboard/dist/assets/index-t8m64Hm9.js +168 -0
  125. package/dashboard/dist/index.html +32 -0
  126. package/package.json +58 -0
  127. package/src/extract/environment.js +160 -0
  128. package/src/extract/phrase-stats.js +684 -0
  129. package/src/extract/prompt-analysis.js +368 -0
  130. package/src/extract/text.js +30 -0
  131. package/src/hooks/install.js +184 -0
  132. package/src/inspect.js +261 -0
  133. package/src/lib/activity-metrics.js +238 -0
  134. package/src/lib/agent-score.js +187 -0
  135. package/src/lib/ai-roast.js +446 -0
  136. package/src/lib/dates.js +43 -0
  137. package/src/lib/hashtags.js +150 -0
  138. package/src/lib/jsonl.js +48 -0
  139. package/src/lib/load-env.js +59 -0
  140. package/src/lib/roast-evidence.js +186 -0
  141. package/src/lib/roast-snapshot.js +58 -0
  142. package/src/server.js +644 -0
  143. package/src/sources/aider.js +150 -0
  144. package/src/sources/amazonq.js +113 -0
  145. package/src/sources/antigravity.js +147 -0
  146. package/src/sources/claude.js +262 -0
  147. package/src/sources/cline.js +11 -0
  148. package/src/sources/codex.js +222 -0
  149. package/src/sources/common.js +133 -0
  150. package/src/sources/continue.js +67 -0
  151. package/src/sources/copilot.js +170 -0
  152. package/src/sources/cursor.js +238 -0
  153. package/src/sources/gemini.js +75 -0
  154. package/src/sources/index.js +61 -0
  155. package/src/sources/roo.js +11 -0
  156. package/src/sources/token-tracker.js +171 -0
  157. package/src/sources/vibe-tracker.js +79 -0
  158. package/src/sources/vscode-tasks.js +142 -0
  159. package/src/sources/windsurf.js +109 -0
  160. package/worker/README.md +96 -0
  161. package/worker/package-lock.json +1547 -0
  162. package/worker/package.json +20 -0
  163. package/worker/src/index.mjs +694 -0
  164. package/worker/wrangler.jsonc +40 -0
@@ -0,0 +1,32 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Vibe Roaster</title>
7
+ <meta name="description" content="Local-first vibe coding personality analyzer" />
8
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
9
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
10
+ <link href="https://fonts.googleapis.com/css2?family=Great+Vibes&display=swap" rel="stylesheet" />
11
+ <link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><text y='24' font-size='24'>✦</text></svg>" />
12
+ <meta name="theme-color" content="#f3f1ec" media="(prefers-color-scheme: light)" />
13
+ <meta name="theme-color" content="#0a0a0a" media="(prefers-color-scheme: dark)" />
14
+ <script>
15
+ (function(){
16
+ var t;
17
+ try { t = localStorage.getItem("vibe-theme"); } catch(e) {}
18
+ var dark = t === "dark" || (t !== "light" && matchMedia("(prefers-color-scheme:dark)").matches);
19
+ if (dark) document.documentElement.classList.add("dark");
20
+ })();
21
+ </script>
22
+ <style>
23
+ html { background: #f3f1ec; }
24
+ html.dark { background: #0a0a0a; }
25
+ </style>
26
+ <script type="module" crossorigin src="/assets/index-t8m64Hm9.js"></script>
27
+ <link rel="stylesheet" crossorigin href="/assets/index-DlBycTcO.css">
28
+ </head>
29
+ <body>
30
+ <div id="root"></div>
31
+ </body>
32
+ </html>
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "vibe-roast",
3
+ "version": "0.98.0",
4
+ "description": "Local-first AI coding personality profiler, usage dashboard, and evidence-grounded roast.",
5
+ "type": "commonjs",
6
+ "bin": {
7
+ "vibe-roast": "bin/vibe-roast.js",
8
+ "vibe-wrapper": "bin/vibe-wrapper.js"
9
+ },
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/PinkR1ver/vibe-roast.git"
13
+ },
14
+ "homepage": "https://github.com/PinkR1ver/vibe-roast#readme",
15
+ "bugs": {
16
+ "url": "https://github.com/PinkR1ver/vibe-roast/issues"
17
+ },
18
+ "keywords": [
19
+ "ai",
20
+ "coding-agent",
21
+ "codex",
22
+ "claude-code",
23
+ "cursor",
24
+ "developer-tools",
25
+ "roast"
26
+ ],
27
+ "files": [
28
+ "bin/",
29
+ "src/",
30
+ "worker/README.md",
31
+ "worker/package.json",
32
+ "worker/package-lock.json",
33
+ "worker/wrangler.jsonc",
34
+ "worker/src/",
35
+ "dashboard/dist/",
36
+ "assests/",
37
+ "README.md"
38
+ ],
39
+ "scripts": {
40
+ "test": "node --test test/*.test.js",
41
+ "inspect": "node bin/vibe-roast.js inspect",
42
+ "serve": "node bin/vibe-roast.js serve",
43
+ "worker:login": "npm --prefix worker run login",
44
+ "worker:dev": "npm --prefix worker run dev",
45
+ "worker:deploy": "npm --prefix worker run deploy",
46
+ "worker:secret:github": "npm --prefix worker run secret:github",
47
+ "worker:secret:session": "npm --prefix worker run secret:session",
48
+ "build": "cd dashboard && npm install && npm run build",
49
+ "dev": "cd dashboard && npm run dev",
50
+ "prepack": "npm run build"
51
+ },
52
+ "engines": {
53
+ "node": ">=20"
54
+ },
55
+ "publishConfig": {
56
+ "access": "public"
57
+ }
58
+ }
@@ -0,0 +1,160 @@
1
+ const fs = require("node:fs/promises");
2
+ const path = require("node:path");
3
+ const os = require("node:os");
4
+
5
+ async function inspectEnvironment({ home = os.homedir(), codexHome } = {}) {
6
+ const resolvedCodexHome = codexHome || process.env.CODEX_HOME || path.join(home, ".codex");
7
+ const [skills, config, customInstructions] = await Promise.all([
8
+ inspectSkills(resolvedCodexHome),
9
+ inspectCodexConfig(path.join(resolvedCodexHome, "config.toml")),
10
+ inspectCustomInstructions(path.join(resolvedCodexHome, "AGENTS.md")),
11
+ ]);
12
+
13
+ return {
14
+ codex: {
15
+ home: resolvedCodexHome,
16
+ skills,
17
+ mcp_servers: config.mcp_servers,
18
+ plugins: config.plugins,
19
+ config: config.config,
20
+ custom_instructions: customInstructions,
21
+ system_prompt: customInstructions,
22
+ },
23
+ };
24
+ }
25
+
26
+ async function inspectSkills(codexHome) {
27
+ const userFiles = await walkFiles(path.join(codexHome, "skills"), (filePath) =>
28
+ filePath.endsWith("SKILL.md"),
29
+ );
30
+ const pluginFiles = await walkFiles(path.join(codexHome, "plugins", "cache"), (filePath) =>
31
+ /[/\\]skills[/\\][^/\\]+[/\\]SKILL\.md$/.test(filePath),
32
+ );
33
+ const userNames = await skillNames(userFiles);
34
+ const pluginNames = await skillNames(pluginFiles);
35
+ const names = Array.from(new Set([...userNames, ...pluginNames])).sort((a, b) =>
36
+ a.localeCompare(b),
37
+ );
38
+ return {
39
+ count: names.length,
40
+ user_count: userNames.length,
41
+ plugin_count: pluginNames.length,
42
+ names,
43
+ user_names: userNames,
44
+ plugin_names: pluginNames,
45
+ };
46
+ }
47
+
48
+ async function skillNames(files) {
49
+ const names = [];
50
+ for (const file of files) {
51
+ const name = (await readSkillName(file)) || path.basename(path.dirname(file));
52
+ names.push(name);
53
+ }
54
+ names.sort((a, b) => a.localeCompare(b));
55
+ return names;
56
+ }
57
+
58
+ async function inspectCodexConfig(configPath) {
59
+ const text = await fs.readFile(configPath, "utf8").catch(() => "");
60
+ return {
61
+ mcp_servers: {
62
+ count: sectionNames(text, "mcp_servers").length,
63
+ names: sectionNames(text, "mcp_servers"),
64
+ },
65
+ plugins: inspectPlugins(text),
66
+ config: {
67
+ present: Boolean(text),
68
+ model: scalarValue(text, "model"),
69
+ personality: scalarValue(text, "personality"),
70
+ sandbox_mode: scalarValue(text, "sandbox_mode"),
71
+ approval_policy: scalarValue(text, "approval_policy"),
72
+ },
73
+ };
74
+ }
75
+
76
+ function inspectPlugins(text) {
77
+ const names = sectionNames(text, "plugins");
78
+ let enabledCount = 0;
79
+ for (const name of names) {
80
+ const block = sectionBlock(text, `plugins.${JSON.stringify(name)}`) || sectionBlock(text, `plugins."${name}"`);
81
+ if (/^\s*enabled\s*=\s*true\s*$/m.test(block)) enabledCount += 1;
82
+ }
83
+ return { count: names.length, enabled_count: enabledCount, names };
84
+ }
85
+
86
+ async function inspectCustomInstructions(filePath) {
87
+ const text = await fs.readFile(filePath, "utf8").catch(() => "");
88
+ return {
89
+ present: Boolean(text.trim()),
90
+ path: filePath,
91
+ char_count: text.length,
92
+ line_count: text ? text.split(/\r?\n/).length : 0,
93
+ preview: text.trim().slice(0, 500),
94
+ };
95
+ }
96
+
97
+ function sectionNames(text, prefix) {
98
+ const re = new RegExp(`^\\s*\\[${escapeRegExp(prefix)}\\.(?:"([^"]+)"|([^\\]]+))\\]\\s*$`, "gm");
99
+ const names = [];
100
+ let match;
101
+ while ((match = re.exec(text))) {
102
+ const raw = (match[1] || match[2] || "").trim();
103
+ const name = raw.split(".")[0].replace(/^"|"$/g, "");
104
+ if (name && !names.includes(name)) names.push(name);
105
+ }
106
+ names.sort((a, b) => a.localeCompare(b));
107
+ return names;
108
+ }
109
+
110
+ function sectionBlock(text, sectionName) {
111
+ const lines = text.split(/\r?\n/);
112
+ const header = `[${sectionName}]`;
113
+ const start = lines.findIndex((line) => line.trim() === header);
114
+ if (start === -1) return "";
115
+ const out = [];
116
+ for (let i = start + 1; i < lines.length; i++) {
117
+ if (/^\s*\[/.test(lines[i])) break;
118
+ out.push(lines[i]);
119
+ }
120
+ return out.join("\n");
121
+ }
122
+
123
+ function scalarValue(text, key) {
124
+ const re = new RegExp(`^\\s*${escapeRegExp(key)}\\s*=\\s*"(.*)"\\s*$`, "m");
125
+ const match = text.match(re);
126
+ return match ? match[1] : null;
127
+ }
128
+
129
+ async function readSkillName(filePath) {
130
+ const text = await fs.readFile(filePath, "utf8").catch(() => "");
131
+ const match = text.match(/^name:\s*(.+)\s*$/m);
132
+ return match ? match[1].trim().replace(/^["']|["']$/g, "") : null;
133
+ }
134
+
135
+ async function walkFiles(rootDir, predicate) {
136
+ const out = [];
137
+ const stack = [rootDir];
138
+ while (stack.length > 0) {
139
+ const dir = stack.pop();
140
+ let entries;
141
+ try {
142
+ entries = await fs.readdir(dir, { withFileTypes: true });
143
+ } catch {
144
+ continue;
145
+ }
146
+ for (const entry of entries) {
147
+ const filePath = path.join(dir, entry.name);
148
+ if (entry.isDirectory()) stack.push(filePath);
149
+ else if (entry.isFile() && predicate(filePath)) out.push(filePath);
150
+ }
151
+ }
152
+ out.sort((a, b) => a.localeCompare(b));
153
+ return out;
154
+ }
155
+
156
+ function escapeRegExp(value) {
157
+ return String(value).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
158
+ }
159
+
160
+ module.exports = { inspectEnvironment };