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,49 @@
1
+ """Split vibe-badges-v6-board.png into per-profile symbolic badge PNGs."""
2
+ import json
3
+ from pathlib import Path
4
+
5
+ from PIL import Image
6
+
7
+ ROOT = Path(__file__).resolve().parents[1]
8
+ CONFIG = Path(__file__).resolve().parent / "profiles.json"
9
+ OUT_SIZE = 256
10
+
11
+
12
+ def main() -> None:
13
+ config = json.loads(CONFIG.read_text(encoding="utf-8"))
14
+ board = config["badgeBoard"]
15
+ profiles = [p for b in config["boards"] for p in b["profiles"]]
16
+ cols = board["cols"]
17
+
18
+ if len(profiles) != cols:
19
+ raise SystemExit(f"profile count {len(profiles)} != badge columns {cols}")
20
+
21
+ im = Image.open(ROOT / board["file"]).convert("RGBA")
22
+ w, h = im.size
23
+ col_w = w // cols
24
+
25
+ for i, profile in enumerate(profiles):
26
+ x0 = i * col_w
27
+ x1 = (i + 1) * col_w if i < cols - 1 else w
28
+ col = im.crop((x0, 0, x1, h))
29
+
30
+ # Full badge card (vertical), pad to square — keeps symbol + base icon
31
+ y0 = int(h * 0.06)
32
+ y1 = int(h * 0.90)
33
+ badge = col.crop((0, y0, col.width, y1))
34
+ side = max(badge.width, badge.height)
35
+ square = Image.new("RGBA", (side, side), (0, 0, 0, 0))
36
+ ox = (side - badge.width) // 2
37
+ oy = (side - badge.height) // 2
38
+ square.paste(badge, (ox, oy))
39
+ badge = square.resize((OUT_SIZE, OUT_SIZE), Image.LANCZOS)
40
+
41
+ out_dir = ROOT / "badges" / profile["folder"]
42
+ out_dir.mkdir(parents=True, exist_ok=True)
43
+ out_path = out_dir / f"{profile['name']}-badge.png"
44
+ badge.save(out_path, optimize=True)
45
+ print(f"wrote {out_path} ({OUT_SIZE}x{OUT_SIZE}) symbol badge")
46
+
47
+
48
+ if __name__ == "__main__":
49
+ main()
@@ -0,0 +1,38 @@
1
+ """Split v5 reference boards into per-profile mascot PNGs and badge crops."""
2
+ import json
3
+ from pathlib import Path
4
+
5
+ from PIL import Image
6
+
7
+ ROOT = Path(__file__).resolve().parents[1]
8
+ CONFIG = Path(__file__).resolve().parent / "profiles.json"
9
+
10
+
11
+ def split_board(board_path: Path, cols: int, profiles: list[dict]) -> None:
12
+ im = Image.open(board_path).convert("RGBA")
13
+ w, h = im.size
14
+ col_w = w // cols
15
+
16
+ for i, profile in enumerate(profiles):
17
+ x0 = i * col_w
18
+ x1 = (i + 1) * col_w if i < cols - 1 else w
19
+ crop = im.crop((x0, 0, x1, h))
20
+
21
+ char_dir = ROOT / "characters" / profile["folder"]
22
+ char_dir.mkdir(parents=True, exist_ok=True)
23
+
24
+ mascot_name = f"{profile['name']}-mascot.png"
25
+ mascot_path = char_dir / mascot_name
26
+ crop.save(mascot_path, optimize=True)
27
+ print(f"wrote {mascot_path} ({crop.size[0]}x{crop.size[1]})")
28
+
29
+
30
+ def main() -> None:
31
+ config = json.loads(CONFIG.read_text(encoding="utf-8"))
32
+ for board in config["boards"]:
33
+ board_path = ROOT / board["file"]
34
+ split_board(board_path, board["cols"], board["profiles"])
35
+
36
+
37
+ if __name__ == "__main__":
38
+ main()
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Embed banner PNGs as self-contained SVGs (1:1 pixel match, no crop).
3
+ */
4
+ import fs from "fs";
5
+ import path from "path";
6
+ import { fileURLToPath } from "url";
7
+
8
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
+ const root = path.join(__dirname, "..");
10
+ const config = JSON.parse(
11
+ fs.readFileSync(path.join(__dirname, "profiles.json"), "utf8")
12
+ );
13
+
14
+ function pngBase64(filePath) {
15
+ return fs.readFileSync(filePath).toString("base64");
16
+ }
17
+
18
+ function pngSize(filePath) {
19
+ const buf = fs.readFileSync(filePath);
20
+ return { w: buf.readUInt32BE(16), h: buf.readUInt32BE(20) };
21
+ }
22
+
23
+ for (const banner of config.banners) {
24
+ const pngPath = path.join(root, banner.file);
25
+ if (!fs.existsSync(pngPath)) {
26
+ console.error(`Missing ${pngPath} — run: python scripts/compose-banners.py`);
27
+ process.exit(1);
28
+ }
29
+ const { w, h } = pngSize(pngPath);
30
+ const b64 = pngBase64(pngPath);
31
+ const outPath = path.join(root, banner.out);
32
+
33
+ if (w !== banner.width || h !== banner.height) {
34
+ console.warn(
35
+ `warn ${path.basename(pngPath)} is ${w}x${h}, expected ${banner.width}x${banner.height}`
36
+ );
37
+ }
38
+
39
+ const svg = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 ${w} ${h}" fill="none" aria-label="${banner.label}">
40
+ <image width="${w}" height="${h}" href="data:image/png;base64,${b64}"/>
41
+ </svg>
42
+ `;
43
+ fs.writeFileSync(outPath, svg);
44
+ console.log("banner", outPath, `(${w}x${h})`);
45
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * @deprecated Use sync-raster.mjs — vector inlining cannot match reference PNG pixels.
3
+ * Kept for history; regenerates from hand SVG if ever needed.
4
+ */
5
+ import path from "path";
6
+ import { fileURLToPath } from "url";
7
+
8
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
+ const root = path.join(__dirname, "..");
10
+
11
+ const pairs = [
12
+ { folder: "01-builder", code: "SHIP", glow: "rgba(35,214,165,0.18)", tag: "#cfeee6" },
13
+ { folder: "02-debugger", code: "HUNT", glow: "rgba(255,101,150,0.14)", tag: "#f5d0dc" },
14
+ { folder: "03-architect", code: "DRAW", glow: "rgba(92,141,255,0.16)", tag: "#d4e2ff" },
15
+ ];
16
+
17
+ for (const { folder, code, glow, tag } of pairs) {
18
+ const name = folder.split("-")[1];
19
+ const id = folder.split("-")[0];
20
+ const charPath = path.join(root, "characters", folder, `${name}-character.svg`);
21
+ const cardPath = path.join(root, "characters", folder, `${name}-card.svg`);
22
+ const char = fs.readFileSync(charPath, "utf8");
23
+ const inner = char.replace(/<svg[^>]*>/, "").replace(/<\/svg>\s*$/, "");
24
+
25
+ const card = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 310 420" fill="none" aria-label="${name} Vibe card">
26
+ <defs>
27
+ <linearGradient id="cardBg" x1="0.5" y1="0" x2="0.5" y2="1">
28
+ <stop offset="0%" stop-color="#182230"/>
29
+ <stop offset="100%" stop-color="#0d1219"/>
30
+ </linearGradient>
31
+ <radialGradient id="cardGlow" cx="50%" cy="18%" r="38%">
32
+ <stop offset="0%" stop-color="${glow}"/>
33
+ <stop offset="100%" stop-color="rgba(0,0,0,0)"/>
34
+ </radialGradient>
35
+ </defs>
36
+ <rect width="310" height="420" rx="8" fill="url(#cardBg)" stroke="rgba(255,255,255,0.1)" stroke-width="1"/>
37
+ <rect width="310" height="420" rx="8" fill="url(#cardGlow)"/>
38
+ <g transform="translate(18 18)">
39
+ <rect width="72" height="26" rx="13" fill="rgba(17,24,33,0.55)" stroke="rgba(255,255,255,0.12)" stroke-width="1"/>
40
+ <text x="36" y="17" text-anchor="middle" fill="${tag}" font-family="Inter,Segoe UI,sans-serif" font-size="11" font-weight="800" letter-spacing="0.08em">VIBE-${id}</text>
41
+ </g>
42
+ <g transform="translate(50 72)">
43
+ ${inner.trim().split("\n").map((l) => " " + l).join("\n")}
44
+ </g>
45
+ <text x="292" y="396" text-anchor="end" fill="#ffc34d" font-family="Inter,Segoe UI,sans-serif" font-size="36" font-weight="900">${code}</text>
46
+ </svg>
47
+ `;
48
+ fs.writeFileSync(cardPath, card);
49
+ console.log("synced", cardPath);
50
+ }
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Embed mascot PNG slices + symbolic badge PNGs as self-contained SVGs.
3
+ * Run: python scripts/split-reference.py && python scripts/split-badges.py
4
+ */
5
+ import fs from "fs";
6
+ import path from "path";
7
+ import { fileURLToPath } from "url";
8
+
9
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
10
+ const root = path.join(__dirname, "..");
11
+ const config = JSON.parse(
12
+ fs.readFileSync(path.join(__dirname, "profiles.json"), "utf8")
13
+ );
14
+
15
+ const CARD_W = 310;
16
+ const CARD_H = 420;
17
+ const CARD_BG = "#0a0a0f";
18
+ const BADGE_SIZE = 64;
19
+
20
+ function pngBase64(filePath) {
21
+ return fs.readFileSync(filePath).toString("base64");
22
+ }
23
+
24
+ function pngSize(filePath) {
25
+ const buf = fs.readFileSync(filePath);
26
+ return { w: buf.readUInt32BE(16), h: buf.readUInt32BE(20) };
27
+ }
28
+
29
+ function writeCharacter(profile, pngPath, w, h) {
30
+ const b64 = pngBase64(pngPath);
31
+ const out = path.join(
32
+ root,
33
+ "characters",
34
+ profile.folder,
35
+ `${profile.name}-character.svg`
36
+ );
37
+ const svg = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 ${w} ${h}" fill="none" aria-label="${profile.label} (raster)">
38
+ <image width="${w}" height="${h}" preserveAspectRatio="xMidYMid meet" href="data:image/png;base64,${b64}"/>
39
+ </svg>
40
+ `;
41
+ fs.writeFileSync(out, svg);
42
+ console.log("character", out);
43
+ }
44
+
45
+ function writeCard(profile, pngPath, w, h) {
46
+ const b64 = pngBase64(pngPath);
47
+ const scale = Math.min((CARD_W - 20) / w, CARD_H / h);
48
+ const imgW = Math.round(w * scale);
49
+ const imgH = Math.round(h * scale);
50
+ const x = Math.round((CARD_W - imgW) / 2);
51
+ const y = Math.round((CARD_H - imgH) / 2);
52
+ const out = path.join(
53
+ root,
54
+ "characters",
55
+ profile.folder,
56
+ `${profile.name}-card.svg`
57
+ );
58
+ const svg = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 ${CARD_W} ${CARD_H}" fill="none" aria-label="${profile.name} Vibe card (raster)">
59
+ <rect width="${CARD_W}" height="${CARD_H}" rx="8" fill="${CARD_BG}"/>
60
+ <image x="${x}" y="${y}" width="${imgW}" height="${imgH}" preserveAspectRatio="xMidYMid meet" href="data:image/png;base64,${b64}"/>
61
+ <text x="292" y="396" text-anchor="end" fill="#ffc34d" font-family="Inter,Segoe UI,sans-serif" font-size="28" font-weight="900">${profile.code}</text>
62
+ </svg>
63
+ `;
64
+ fs.writeFileSync(out, svg);
65
+ console.log("card", out);
66
+ }
67
+
68
+ function writeBadge(profile, pngPath) {
69
+ const b64 = pngBase64(pngPath);
70
+ const { w, h } = pngSize(pngPath);
71
+ const pad = 4;
72
+ const inner = BADGE_SIZE - pad * 2;
73
+ const out = path.join(
74
+ root,
75
+ "badges",
76
+ profile.folder,
77
+ `${profile.name}-badge.svg`
78
+ );
79
+ const svg = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 ${BADGE_SIZE} ${BADGE_SIZE}" fill="none" aria-label="${profile.label} symbolic badge">
80
+ <rect width="${BADGE_SIZE}" height="${BADGE_SIZE}" rx="14" fill="#111821" stroke="rgba(255,255,255,0.08)" stroke-width="1"/>
81
+ <image x="${pad}" y="${pad}" width="${inner}" height="${inner}" preserveAspectRatio="xMidYMid meet" href="data:image/png;base64,${b64}"/>
82
+ </svg>
83
+ `;
84
+ fs.writeFileSync(out, svg);
85
+ console.log("badge", out, `(symbol ${w}x${h})`);
86
+ }
87
+
88
+ const profiles = config.boards.flatMap((b) => b.profiles);
89
+
90
+ for (const profile of profiles) {
91
+ const mascotPath = path.join(
92
+ root,
93
+ "characters",
94
+ profile.folder,
95
+ `${profile.name}-mascot.png`
96
+ );
97
+ const badgePath = path.join(
98
+ root,
99
+ "badges",
100
+ profile.folder,
101
+ `${profile.name}-badge.png`
102
+ );
103
+
104
+ if (!fs.existsSync(mascotPath)) {
105
+ console.error(`Missing ${mascotPath} — run: python scripts/split-reference.py`);
106
+ process.exit(1);
107
+ }
108
+
109
+ const { w, h } = pngSize(mascotPath);
110
+ writeCharacter(profile, mascotPath, w, h);
111
+ writeCard(profile, mascotPath, w, h);
112
+
113
+ if (!fs.existsSync(badgePath)) {
114
+ console.error(`Missing ${badgePath} — run: python scripts/split-badges.py`);
115
+ process.exit(1);
116
+ }
117
+ writeBadge(profile, badgePath);
118
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "version": "vibe-types-v1",
3
+ "display": "freestanding-figure-no-card-frame",
4
+ "profiles": [
5
+ { "code": "MOVF", "folder": "movf-agent-engineer", "name": "agent-engineer", "label": "Agent Engineer" },
6
+ { "code": "MOVX", "folder": "movx-systems-wrangler", "name": "systems-wrangler", "label": "Systems Wrangler" },
7
+ { "code": "MOSF", "folder": "mosf-yolo-shipper", "name": "yolo-shipper", "label": "YOLO Shipper" },
8
+ { "code": "MOSX", "folder": "mosx-agent-commander", "name": "agent-commander", "label": "Agent Commander" },
9
+ { "code": "MPVF", "folder": "mpvf-debugger", "name": "debugger", "label": "Debugger" },
10
+ { "code": "MPVX", "folder": "mpvx-context-maxxer", "name": "context-maxxer", "label": "Context Maxxer" },
11
+ { "code": "MPSF", "folder": "mpsf-builder", "name": "builder", "label": "Builder" },
12
+ { "code": "MPSX", "folder": "mpsx-tab-hoarder", "name": "tab-hoarder", "label": "Tab Hoarder" },
13
+ { "code": "AOVF", "folder": "aovf-systems-architect", "name": "systems-architect", "label": "Systems Architect" },
14
+ { "code": "AOVX", "folder": "aovx-context-cartographer", "name": "context-cartographer", "label": "Context Cartographer" },
15
+ { "code": "AOSF", "folder": "aosf-strategy-shipper", "name": "strategy-shipper", "label": "Strategy Shipper" },
16
+ { "code": "AOSX", "folder": "aosx-agent-believer", "name": "agent-believer", "label": "Agent Believer" },
17
+ { "code": "APVF", "folder": "apvf-architect", "name": "architect", "label": "Architect" },
18
+ { "code": "APVX", "folder": "apvx-prompt-priest", "name": "prompt-priest", "label": "Prompt Priest" },
19
+ { "code": "APSF", "folder": "apsf-diagram-sprinter", "name": "diagram-sprinter", "label": "Diagram Sprinter" },
20
+ { "code": "APSX", "folder": "apsx-infinite-planner", "name": "infinite-planner", "label": "Infinite Planner" }
21
+ ]
22
+ }
@@ -0,0 +1,50 @@
1
+ # Vibe Profile Visual — Design System (v6 · MBTI flat)
2
+
3
+ Primary style: classic 16Personalities geometric faceted flat vector (Piotr Antkowiak / Zeda Labs language).
4
+
5
+ ## Art style (canonical)
6
+
7
+ - Full-body figures, ~5.5–6 heads tall (slightly oversized head)
8
+ - Geometric faceted color planes, clean silhouettes, **no black outlines / no line art**
9
+ - Simplified faces (dot/oval eyes, minimal nose, simple mouth)
10
+ - Large stylized hair masses as 2–3 shade planes (no strand detail)
11
+ - Muted harmonious palette (~6–10 colors) per type accent
12
+ - Faceted shade planes only — no painterly gradients, grunge, or fabric texture
13
+ - Clothing communicates type; one compact symbolic prop grouping
14
+ - Natural narrative poses
15
+ - Minimal / abstract environment only (product page supplies soft stage blob)
16
+ - **No collectible card frame** on product surfaces
17
+ - Reference boards: `notes/mbti-ref-analysts.jpg`, `notes/mbti-ref-sentinels.jpg`
18
+
19
+ ## Source of truth
20
+
21
+ | Asset | Role |
22
+ |-------|------|
23
+ | `characters/*/*-figure.png` | Freestanding MBTI-style figure (primary) |
24
+ | `characters/*/*-character.svg` | Thin wrapper pointing at figure |
25
+ | `characters/*/*-card.svg` | Alias of character (compat) — not a framed card |
26
+ | `characters/*/*.sbti-archive.svg` | Previous SBTI diamond-card raster embeds |
27
+ | `badges/*/*-badge.svg` | Symbolic badge icons (v6 board) |
28
+
29
+ ## Profiles
30
+
31
+ | Code | Accent | Prop language |
32
+ |------|--------|---------------|
33
+ | SHIP | Mint | Laptop + rocket badge |
34
+ | HUNT | Pink | Rubber duck + error tablet |
35
+ | DRAW | Blue | Flowchart tablet + glasses |
36
+ | FAITH | Purple | Halo terminal |
37
+ | SPELL | Gold | Rules scroll |
38
+ | TABS | Orange | Floating browser tabs |
39
+ | METER | Cyan | Context gauge ~99% |
40
+ | YOLO | Red | Big merge / YOLO button |
41
+
42
+ ## Product display
43
+
44
+ - Roast Result places the figure **on a soft abstract stage blob** — not inside a bordered card.
45
+ - Figure PNGs use `mix-blend-mode: multiply` so light scene canvases dissolve into the page (no rectangular card chrome).
46
+ - Score / tier / signals sit beside/below the figure in the React Roast Result UI (and optional `live-report.html` export).
47
+
48
+ ## Preview
49
+
50
+ Run `npm run serve` and open `http://localhost:7681/` for the live Roast Result. Current figures load from `assests/characters-vibe-types/`; `assests/characters/` is the legacy fallback pack.
@@ -0,0 +1,19 @@
1
+ # Builder — SHIP (MBTI flat)
2
+
3
+ ## Art direction
4
+
5
+ Classic 16personalities geometric flat vector (Piotr Antkowiak language):
6
+ smooth silhouette · large shade planes (not dense low-poly) · no outlines · 5.5 heads · freestanding
7
+
8
+ ## Props
9
+
10
+ - Slim laptop with soft green rocket badge
11
+ - Layered mint hoodie over cream tee
12
+
13
+ ## Pose
14
+
15
+ Slight forward lean, celebratory fist + laptop — deploy-first energy.
16
+
17
+ ## Prompt seed
18
+
19
+ Full-body original MBTI-style flat vector developer, muted mint palette, large hair mass, tiny oval/dot eyes, laptop with rocket badge, narrative pose, cream bg, no outlines, no card frame.
@@ -0,0 +1,17 @@
1
+ # Debugger — HUNT
2
+
3
+ ## v1 (final first deliverable)
4
+
5
+ - Same body layout as Builder (series read)
6
+ - Prop: pink error line in editor + small rubber duck (debug meme, one icon)
7
+ - Hood up, squint + open eye expression
8
+ - Removed: magnifier overlap, floating laptop corner, meaningless bug triangle
9
+
10
+ ## References
11
+
12
+ - Rubber duck debugging
13
+ - IDE error highlight line
14
+
15
+ ## Prompt seed
16
+
17
+ Flat chibi hooded debugger at laptop. Pink error line on screen, tiny yellow rubber duck on keyboard deck. One eye squinting, tired focus. Gray hoodie, bold outlines.
@@ -0,0 +1,16 @@
1
+ # Architect — DRAW
2
+
3
+ ## v1 (final first deliverable)
4
+
5
+ - Blueprint pad replaces laptop in tool zone
6
+ - Prop: three linked boxes with arrows (system design, no text labels)
7
+ - Glasses + calm expression, hands on pad
8
+ - Removed: floating diagrams, clipboard clutter, light pastel pads on dark UI
9
+
10
+ ## References
11
+
12
+ - C4 / flowchart “draw the boxes” trope
13
+
14
+ ## Prompt seed
15
+
16
+ Flat chibi architect in blue outfit with rectangular glasses. Dark blueprint pad with three white-outlined boxes and arrows. Calm smile, hands holding pad. Bold outlines, dark-dashboard friendly.
@@ -0,0 +1,13 @@
1
+ # 04 Codex Believer · FAITH
2
+
3
+ ## Hook
4
+ Prays to the agent — owner-suggested “Codex 信徒” archetype.
5
+
6
+ ## 2026 meme
7
+ Cursor/agent mode culture; Karpathy’s **agentic engineering** vs blind vibe coding.
8
+
9
+ ## Visual (SBTI board v5)
10
+ Purple card · small robot disciple mascot · glowing terminal halo · cross-legged worship pose · diamond card frame · circuit glow.
11
+
12
+ ## Reference column
13
+ Board A, column 4 in `vibe-profiles-v5-board-a.png`.
@@ -0,0 +1,13 @@
1
+ # 05 Prompt Priest · SPELL
2
+
3
+ ## Hook
4
+ `.cursor/rules` and system prompts as holy scroll.
5
+
6
+ ## 2026 meme
7
+ Prompt-engineering / rules-folder culture in agentic IDEs.
8
+
9
+ ## Visual
10
+ Gold card · chibi holding giant scroll of abstract line blocks (no readable text) · proud overwhelmed face.
11
+
12
+ ## Reference column
13
+ Board B, column 1 in `vibe-profiles-v5-board-b.png`.
@@ -0,0 +1,13 @@
1
+ # 06 Tab Hoarder · TABS
2
+
3
+ ## Hook
4
+ Forty-seven tabs, three localhost ports, fan sounds like a jet.
5
+
6
+ ## 2026 meme
7
+ ProgrammerHumor “three servers on 3000/8000/5000 before you know variables” AI dev meme.
8
+
9
+ ## Visual
10
+ Orange card · chibi with dizzy eyes · floating browser tab rectangles · port badge shapes (abstract).
11
+
12
+ ## Reference column
13
+ Board B, column 2 in `vibe-profiles-v5-board-b.png`.
@@ -0,0 +1,13 @@
1
+ # 07 Context Maxxer · METER
2
+
3
+ ## Hook
4
+ Context window / credits gauge permanently at 99%.
5
+
6
+ ## 2026 meme
7
+ ICSE 2026 vibe-coding studies; SaaS credit burn; “almost full” meter anxiety.
8
+
9
+ ## Visual
10
+ Cyan card · chibi sweating · circular gauge nearly maxed · SBTI card frame.
11
+
12
+ ## Reference column
13
+ Board B, column 3 in `vibe-profiles-v5-board-b.png`.
@@ -0,0 +1,13 @@
1
+ # 08 YOLO Shipper · YOLO
2
+
3
+ ## Hook
4
+ `cursor agent --yolo` energy — skip review, ship anyway.
5
+
6
+ ## 2026 meme
7
+ Cursor CLI `--yolo` flag; agentic speed vs production debt discourse (2026).
8
+
9
+ ## Visual
10
+ Red card · chibi slamming oversized red button · chaotic code/agent streams · reckless grin.
11
+
12
+ ## Reference column
13
+ Board B, column 4 in `vibe-profiles-v5-board-b.png`.
@@ -0,0 +1,38 @@
1
+ # Vibe Types — 16-character visual brief
2
+
3
+ These portraits extend the visual language of the eight legacy score archetypes into a sixteen-type system. They are a single coherent series: one centered full-body figure, 2:3 portrait, transparent background, large low-poly flat-vector facets, simplified rectangular face, clean silhouette, no outlines, no texture, no text, no logo, no watermark, no card border, no photorealism, no anime, and no glossy 3D.
4
+
5
+ Every image should make the roast readable before the label is shown. Use one human, one compact prop grouping, one visual joke, empty background, and 5.5–6-head character proportions. Do not turn a role into a multi-character environment or editorial scene.
6
+
7
+ ## Shared generation prompt
8
+
9
+ > Match the attached legacy characters exactly: one single tall slim full-body human, about six heads tall; simple friendly rectangular face with oval eyes and a tiny curved mouth; large clean low-poly vector facets; smooth untextured muted fills; no outlines; sparse details; one compact prop grouping; isolated with the same scale and negative space. Generate on a perfectly flat `#00FF00` chroma-key background, then remove that background to produce a true-alpha PNG. No elaborate environment, complex scene, paper grain, realistic anatomy, cinematic lighting, 3D materials, words, letters, logos, watermark, border, or card frame. 1024×1536 portrait.
10
+
11
+ Append one character direction below to the shared prompt.
12
+
13
+ | Type | Character | Visual direction | Palette |
14
+ |---|---|---|---|
15
+ | MOVF | Agent Engineer | Calm engineer with a control tablet and two tiny Agent cubes: check and wrench. | teal, charcoal |
16
+ | MOVX | Systems Wrangler | Operator holding colored context ribbons attached to two Agent cubes; overfilled file satchel. | sea green, rust, navy |
17
+ | MOSF | YOLO Shipper | Grinning courier holding an oversized merge symbol; unchecked test sheet in pocket. | vermilion, charcoal |
18
+ | MOSX | Agent Commander | Conductor directing three Agent cubes with a baton while balancing coffee. | coral, plum, cyan |
19
+ | MPVF | Debugger | Patient debugger with magnifying glass, tiny bug, error notebook, and rubber duck. | dusty rose, cream, yellow |
20
+ | MPVX | Context Maxxer | Anxious engineer carrying a huge folder stack with an almost-full gauge. | cyan, navy, sand |
21
+ | MPSF | Builder | Practical maker holding a finished play-block and a wrench. | mint, cobalt, charcoal |
22
+ | MPSX | Tab Hoarder | Overwhelmed developer holding a fan of browser-tab cards and reaching for the green one. | orange, turquoise, aubergine |
23
+ | AOVF | Systems Architect | Composed architect with a modular blueprint tablet and one checking Agent cube. | blue, jade, sand |
24
+ | AOVX | Context Cartographer | Explorer holding a folded dependency map with a tiny Agent scout. | slate blue, moss, copper |
25
+ | AOSF | Strategy Shipper | Tactical planner turning a roadmap scroll into a launch ramp for one app cube. | violet, coral, gold |
26
+ | AOSX | Agent Believer | Serene technologist holding an arch-shaped Agent shrine and forgotten checklist. | purple, aqua, rose |
27
+ | APVF | Architect | Severe reviewer measuring a geometric system model with calipers; check tile waits below. | royal blue, brick, cream |
28
+ | APVX | Prompt Priest | Ceremonial prompt writer holding a comically long rules scroll that wraps around a patient robot agent; reverent but self-aware. | mustard, plum, teal |
29
+ | APSF | Diagram Sprinter | Energetic designer carrying rolled blueprints and one small runnable play-block. | terracotta, sky blue, green |
30
+ | APSX | Infinite Planner | Thoughtful planner adding one last sticky to a circular map; dusty start block below. | lavender, mauve, dusty blue |
31
+
32
+ ## Target paths
33
+
34
+ Each final PNG is `1024×1536`, contains a real alpha channel, and lives at:
35
+
36
+ `assests/characters-vibe-types/<lowercase-code>-<slug>/<slug>-figure.png`
37
+
38
+ The exact folders/slugs are defined by `PERSONALITIES` in `src/lib/agent-score.js` and `assests/scripts/vibe-types.json`. The legacy `profiles.json` remains unchanged for the old eight-figure maintenance scripts.