buildpartner 0.3.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 (109) hide show
  1. package/dist/bin/cli.d.ts +2 -0
  2. package/dist/bin/cli.js +44 -0
  3. package/dist/bin/cli.js.map +1 -0
  4. package/dist/src/api-client.d.ts +18 -0
  5. package/dist/src/api-client.js +74 -0
  6. package/dist/src/api-client.js.map +1 -0
  7. package/dist/src/classifiers/activity-classifier.d.ts +12 -0
  8. package/dist/src/classifiers/activity-classifier.js +300 -0
  9. package/dist/src/classifiers/activity-classifier.js.map +1 -0
  10. package/dist/src/classifiers/path-detector.d.ts +33 -0
  11. package/dist/src/classifiers/path-detector.js +98 -0
  12. package/dist/src/classifiers/path-detector.js.map +1 -0
  13. package/dist/src/commands/log-session.d.ts +10 -0
  14. package/dist/src/commands/log-session.js +162 -0
  15. package/dist/src/commands/log-session.js.map +1 -0
  16. package/dist/src/commands/serve.d.ts +1 -0
  17. package/dist/src/commands/serve.js +5 -0
  18. package/dist/src/commands/serve.js.map +1 -0
  19. package/dist/src/commands/setup.d.ts +1 -0
  20. package/dist/src/commands/setup.js +578 -0
  21. package/dist/src/commands/setup.js.map +1 -0
  22. package/dist/src/constants.d.ts +9 -0
  23. package/dist/src/constants.js +12 -0
  24. package/dist/src/constants.js.map +1 -0
  25. package/dist/src/installer/hook-installer.d.ts +19 -0
  26. package/dist/src/installer/hook-installer.js +114 -0
  27. package/dist/src/installer/hook-installer.js.map +1 -0
  28. package/dist/src/installer/mcp-installer.d.ts +9 -0
  29. package/dist/src/installer/mcp-installer.js +80 -0
  30. package/dist/src/installer/mcp-installer.js.map +1 -0
  31. package/dist/src/installer/skill-installer.d.ts +5 -0
  32. package/dist/src/installer/skill-installer.js +55 -0
  33. package/dist/src/installer/skill-installer.js.map +1 -0
  34. package/dist/src/installer/skill-sync.d.ts +10 -0
  35. package/dist/src/installer/skill-sync.js +76 -0
  36. package/dist/src/installer/skill-sync.js.map +1 -0
  37. package/dist/src/mcp/server.d.ts +3 -0
  38. package/dist/src/mcp/server.js +106 -0
  39. package/dist/src/mcp/server.js.map +1 -0
  40. package/dist/src/mcp/subscription-gate.d.ts +19 -0
  41. package/dist/src/mcp/subscription-gate.js +74 -0
  42. package/dist/src/mcp/subscription-gate.js.map +1 -0
  43. package/dist/src/mcp/tools/ai-profile.d.ts +88 -0
  44. package/dist/src/mcp/tools/ai-profile.js +123 -0
  45. package/dist/src/mcp/tools/ai-profile.js.map +1 -0
  46. package/dist/src/mcp/tools/classify-session.d.ts +31 -0
  47. package/dist/src/mcp/tools/classify-session.js +34 -0
  48. package/dist/src/mcp/tools/classify-session.js.map +1 -0
  49. package/dist/src/mcp/tools/get-knowledge.d.ts +25 -0
  50. package/dist/src/mcp/tools/get-knowledge.js +31 -0
  51. package/dist/src/mcp/tools/get-knowledge.js.map +1 -0
  52. package/dist/src/mcp/tools/get-profile.d.ts +1 -0
  53. package/dist/src/mcp/tools/get-profile.js +77 -0
  54. package/dist/src/mcp/tools/get-profile.js.map +1 -0
  55. package/dist/src/mcp/tools/get-stats.d.ts +58 -0
  56. package/dist/src/mcp/tools/get-stats.js +135 -0
  57. package/dist/src/mcp/tools/get-stats.js.map +1 -0
  58. package/dist/src/mcp/tools/get-suggestions.d.ts +7 -0
  59. package/dist/src/mcp/tools/get-suggestions.js +176 -0
  60. package/dist/src/mcp/tools/get-suggestions.js.map +1 -0
  61. package/dist/src/mcp/tools/get-training.d.ts +48 -0
  62. package/dist/src/mcp/tools/get-training.js +102 -0
  63. package/dist/src/mcp/tools/get-training.js.map +1 -0
  64. package/dist/src/mcp/tools/log-highlight.d.ts +32 -0
  65. package/dist/src/mcp/tools/log-highlight.js +39 -0
  66. package/dist/src/mcp/tools/log-highlight.js.map +1 -0
  67. package/dist/src/mcp/tools/quest.d.ts +78 -0
  68. package/dist/src/mcp/tools/quest.js +72 -0
  69. package/dist/src/mcp/tools/quest.js.map +1 -0
  70. package/dist/src/mcp/tools/web-search.d.ts +15 -0
  71. package/dist/src/mcp/tools/web-search.js +17 -0
  72. package/dist/src/mcp/tools/web-search.js.map +1 -0
  73. package/dist/src/readers/history-reader.d.ts +28 -0
  74. package/dist/src/readers/history-reader.js +83 -0
  75. package/dist/src/readers/history-reader.js.map +1 -0
  76. package/dist/src/readers/session-reader.d.ts +89 -0
  77. package/dist/src/readers/session-reader.js +310 -0
  78. package/dist/src/readers/session-reader.js.map +1 -0
  79. package/dist/src/readers/stats-reader.d.ts +38 -0
  80. package/dist/src/readers/stats-reader.js +125 -0
  81. package/dist/src/readers/stats-reader.js.map +1 -0
  82. package/dist/src/store/local-store.d.ts +72 -0
  83. package/dist/src/store/local-store.js +145 -0
  84. package/dist/src/store/local-store.js.map +1 -0
  85. package/dist/src/store/quest-store.d.ts +77 -0
  86. package/dist/src/store/quest-store.js +309 -0
  87. package/dist/src/store/quest-store.js.map +1 -0
  88. package/dist/src/store/status-store.d.ts +73 -0
  89. package/dist/src/store/status-store.js +372 -0
  90. package/dist/src/store/status-store.js.map +1 -0
  91. package/dist/src/suggestions/rules.d.ts +1 -0
  92. package/dist/src/suggestions/rules.js +2 -0
  93. package/dist/src/suggestions/rules.js.map +1 -0
  94. package/dist/src/suggestions/video-links.d.ts +1 -0
  95. package/dist/src/suggestions/video-links.js +2 -0
  96. package/dist/src/suggestions/video-links.js.map +1 -0
  97. package/package.json +35 -0
  98. package/skills/he-coach/SKILL.md +56 -0
  99. package/skills/he-consult/SKILL.md +43 -0
  100. package/skills/he-enhance-claude-md/SKILL.md +58 -0
  101. package/skills/he-flex-socials/SKILL.md +50 -0
  102. package/skills/he-full-audit/SKILL.md +119 -0
  103. package/skills/he-improve-skill/SKILL.md +111 -0
  104. package/skills/he-interview/SKILL.md +54 -0
  105. package/skills/he-life-story/SKILL.md +64 -0
  106. package/skills/he-log-experience/SKILL.md +68 -0
  107. package/skills/he-open-dashboard/SKILL.md +27 -0
  108. package/skills/he-quest-status/SKILL.md +48 -0
  109. package/skills/he-recap-week/SKILL.md +49 -0
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env node
2
+ const command = process.argv[2];
3
+ async function main() {
4
+ switch (command) {
5
+ case "setup": {
6
+ const { setup } = await import("../src/commands/setup.js");
7
+ await setup();
8
+ break;
9
+ }
10
+ case "serve": {
11
+ const { serve } = await import("../src/commands/serve.js");
12
+ await serve();
13
+ break;
14
+ }
15
+ case "log-session": {
16
+ const { logSession } = await import("../src/commands/log-session.js");
17
+ await logSession();
18
+ break;
19
+ }
20
+ case "stats": {
21
+ const { setup } = await import("../src/commands/setup.js");
22
+ // Quick stats mode
23
+ console.log("Stats command coming soon.");
24
+ break;
25
+ }
26
+ default:
27
+ console.log(`
28
+ BuildPartner - Your AI Build Partner
29
+
30
+ Usage:
31
+ buildpartner setup Interactive setup + backfill
32
+ buildpartner setup --token X Pre-authenticated setup
33
+ buildpartner serve Start MCP server
34
+ buildpartner log-session Log current session (hook)
35
+ buildpartner stats Quick stats
36
+ `);
37
+ }
38
+ }
39
+ main().catch((err) => {
40
+ console.error(err);
41
+ process.exit(1);
42
+ });
43
+ export {};
44
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../bin/cli.ts"],"names":[],"mappings":";AAEA,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAEhC,KAAK,UAAU,IAAI;IACjB,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,0BAA0B,CAAC,CAAC;YAC3D,MAAM,KAAK,EAAE,CAAC;YACd,MAAM;QACR,CAAC;QACD,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,0BAA0B,CAAC,CAAC;YAC3D,MAAM,KAAK,EAAE,CAAC;YACd,MAAM;QACR,CAAC;QACD,KAAK,aAAa,CAAC,CAAC,CAAC;YACnB,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,gCAAgC,CAAC,CAAC;YACtE,MAAM,UAAU,EAAE,CAAC;YACnB,MAAM;QACR,CAAC;QACD,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,0BAA0B,CAAC,CAAC;YAC3D,mBAAmB;YACnB,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;YAC1C,MAAM;QACR,CAAC;QACD;YACE,OAAO,CAAC,GAAG,CAAC;;;;;;;;;CASjB,CAAC,CAAC;IACD,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,18 @@
1
+ export declare const API_BASE = "https://web-mu-six-27.vercel.app";
2
+ /**
3
+ * Fetch from the MyPlayer API with auth.
4
+ * Returns null if offline or auth missing (caller should fall back to local).
5
+ */
6
+ export declare function apiFetch(path: string, options?: RequestInit): Promise<Response | null>;
7
+ /**
8
+ * GET from API, parse JSON. Returns null on failure.
9
+ */
10
+ export declare function apiGet<T>(path: string): Promise<T | null>;
11
+ /**
12
+ * POST to API, parse JSON. Returns null on failure.
13
+ */
14
+ export declare function apiPost<T>(path: string, body: unknown): Promise<T | null>;
15
+ /**
16
+ * Track a usage event. Fire and forget, never blocks, never fails.
17
+ */
18
+ export declare function track(event: string, metadata?: Record<string, unknown>): void;
@@ -0,0 +1,74 @@
1
+ import { readAuth, logError } from "./store/local-store.js";
2
+ export const API_BASE = "https://web-mu-six-27.vercel.app";
3
+ /**
4
+ * Fetch from the MyPlayer API with auth.
5
+ * Returns null if offline or auth missing (caller should fall back to local).
6
+ */
7
+ export async function apiFetch(path, options) {
8
+ const auth = readAuth();
9
+ if (!auth?.token)
10
+ return null;
11
+ try {
12
+ const controller = new AbortController();
13
+ const timeout = setTimeout(() => controller.abort(), 5000);
14
+ const res = await fetch(`${API_BASE}${path}`, {
15
+ ...options,
16
+ headers: {
17
+ "Authorization": `Bearer ${auth.token}`,
18
+ "Content-Type": "application/json",
19
+ ...options?.headers,
20
+ },
21
+ signal: controller.signal,
22
+ });
23
+ clearTimeout(timeout);
24
+ return res;
25
+ }
26
+ catch (err) {
27
+ logError(err);
28
+ return null;
29
+ }
30
+ }
31
+ /**
32
+ * GET from API, parse JSON. Returns null on failure.
33
+ */
34
+ export async function apiGet(path) {
35
+ const res = await apiFetch(path);
36
+ if (!res || !res.ok)
37
+ return null;
38
+ return res.json();
39
+ }
40
+ /**
41
+ * POST to API, parse JSON. Returns null on failure.
42
+ */
43
+ export async function apiPost(path, body) {
44
+ const res = await apiFetch(path, {
45
+ method: "POST",
46
+ body: JSON.stringify(body),
47
+ });
48
+ if (!res || !res.ok)
49
+ return null;
50
+ return res.json();
51
+ }
52
+ /**
53
+ * Track a usage event. Fire and forget, never blocks, never fails.
54
+ */
55
+ export function track(event, metadata) {
56
+ const auth = readAuth();
57
+ const payload = {
58
+ event,
59
+ token: auth?.token || null,
60
+ metadata: {
61
+ ...metadata,
62
+ username: auth?.username || "anonymous",
63
+ timestamp: new Date().toISOString(),
64
+ },
65
+ };
66
+ // Fire and forget
67
+ fetch(`${API_BASE}/api/myplayer/track`, {
68
+ method: "POST",
69
+ headers: { "Content-Type": "application/json" },
70
+ body: JSON.stringify(payload),
71
+ signal: AbortSignal.timeout(3000),
72
+ }).catch(() => { });
73
+ }
74
+ //# sourceMappingURL=api-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../src/api-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAE5D,MAAM,CAAC,MAAM,QAAQ,GAAG,kCAAkC,CAAC;AAE3D;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAY,EAAE,OAAqB;IAChE,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;IACxB,IAAI,CAAC,IAAI,EAAE,KAAK;QAAE,OAAO,IAAI,CAAC;IAE9B,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,CAAC;QAE3D,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,QAAQ,GAAG,IAAI,EAAE,EAAE;YAC5C,GAAG,OAAO;YACV,OAAO,EAAE;gBACP,eAAe,EAAE,UAAU,IAAI,CAAC,KAAK,EAAE;gBACvC,cAAc,EAAE,kBAAkB;gBAClC,GAAG,OAAO,EAAE,OAAO;aACpB;YACD,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAC,CAAC;QAEH,YAAY,CAAC,OAAO,CAAC,CAAC;QACtB,OAAO,GAAG,CAAC;IACb,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,QAAQ,CAAC,GAAG,CAAC,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAAI,IAAY;IAC1C,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE;QAAE,OAAO,IAAI,CAAC;IACjC,OAAO,GAAG,CAAC,IAAI,EAAgB,CAAC;AAClC,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAI,IAAY,EAAE,IAAa;IAC1D,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE;QAC/B,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;KAC3B,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE;QAAE,OAAO,IAAI,CAAC;IACjC,OAAO,GAAG,CAAC,IAAI,EAAgB,CAAC;AAClC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,KAAK,CAAC,KAAa,EAAE,QAAkC;IACrE,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;IACxB,MAAM,OAAO,GAAG;QACd,KAAK;QACL,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,IAAI;QAC1B,QAAQ,EAAE;YACR,GAAG,QAAQ;YACX,QAAQ,EAAE,IAAI,EAAE,QAAQ,IAAI,WAAW;YACvC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC;KACF,CAAC;IAEF,kBAAkB;IAClB,KAAK,CAAC,GAAG,QAAQ,qBAAqB,EAAE;QACtC,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;QAC7B,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC;KAClC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;AACrB,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { ParsedSession } from "../readers/session-reader.js";
2
+ export type ActivityType = "code" | "content" | "research" | "automation" | "design" | "ops" | "data" | "debug";
3
+ export interface ClassificationResult {
4
+ activityType: ActivityType;
5
+ scores: Record<ActivityType, number>;
6
+ confidence: number;
7
+ signals: string[];
8
+ }
9
+ /**
10
+ * Classify a parsed session into an activity type.
11
+ */
12
+ export declare function classifySession(session: ParsedSession): ClassificationResult;
@@ -0,0 +1,300 @@
1
+ /** File extension sets for classification signals. */
2
+ const CODE_EXTENSIONS = new Set([
3
+ ".ts", ".tsx", ".js", ".jsx", ".py", ".go", ".rs", ".java", ".rb", ".swift",
4
+ ".kt", ".c", ".cpp", ".h", ".cs", ".php", ".vue", ".svelte",
5
+ ]);
6
+ const CONTENT_EXTENSIONS = new Set([".md", ".mdx", ".txt", ".rst"]);
7
+ const AUTOMATION_EXTENSIONS = new Set([".sh", ".bash", ".zsh"]);
8
+ const CONFIG_EXTENSIONS = new Set([".json", ".yaml", ".yml", ".toml", ".ini", ".env"]);
9
+ const DATA_EXTENSIONS = new Set([".csv", ".sql", ".parquet", ".jsonl"]);
10
+ const CI_CD_PATTERNS = [".github/workflows", ".gitlab-ci", "Jenkinsfile", "Dockerfile", ".circleci"];
11
+ /** Tool names grouped by what they signal. */
12
+ const WRITE_TOOLS = new Set(["Write", "Edit", "NotebookEdit"]);
13
+ const READ_TOOLS = new Set(["Read", "Grep", "Glob"]);
14
+ const WEB_TOOLS = new Set(["WebSearch", "WebFetch"]);
15
+ /**
16
+ * Classify a parsed session into an activity type.
17
+ */
18
+ export function classifySession(session) {
19
+ const scores = {
20
+ code: 0,
21
+ content: 0,
22
+ research: 0,
23
+ automation: 0,
24
+ design: 0,
25
+ ops: 0,
26
+ data: 0,
27
+ debug: 0,
28
+ };
29
+ const signals = [];
30
+ const toolCounts = countTools(session.toolCalls);
31
+ const totalToolCalls = session.toolCalls.length;
32
+ const files = session.filesTouched;
33
+ const fileExtensions = files.map(getExtension);
34
+ // --- CODE signals ---
35
+ const codeFileWrites = countFileWritesByExt(session.toolCalls, CODE_EXTENSIONS);
36
+ if (codeFileWrites > 0) {
37
+ scores.code += codeFileWrites * 3; // High weight
38
+ signals.push(`${codeFileWrites} code file writes`);
39
+ }
40
+ const codeFilesInList = fileExtensions.filter((e) => CODE_EXTENSIONS.has(e)).length;
41
+ if (codeFilesInList > 0) {
42
+ scores.code += codeFilesInList;
43
+ signals.push(`${codeFilesInList} code files touched`);
44
+ }
45
+ if (toolCounts["Bash"]) {
46
+ const bashCommands = getBashCommands(session.toolCalls);
47
+ const gitCommands = bashCommands.filter((c) => c.startsWith("git ")).length;
48
+ const npmCommands = bashCommands.filter((c) => c.startsWith("npm ") || c.startsWith("npx ") || c.startsWith("node ") ||
49
+ c.startsWith("pnpm ") || c.startsWith("yarn ") || c.startsWith("bun ")).length;
50
+ if (gitCommands > 0) {
51
+ scores.code += gitCommands * 2;
52
+ signals.push(`${gitCommands} git commands`);
53
+ }
54
+ if (npmCommands > 0) {
55
+ scores.code += npmCommands;
56
+ signals.push(`${npmCommands} npm/node commands`);
57
+ }
58
+ }
59
+ // package.json changes
60
+ if (files.some((f) => f.endsWith("package.json"))) {
61
+ scores.code += 2;
62
+ signals.push("package.json modified");
63
+ }
64
+ // --- CONTENT signals ---
65
+ const contentFileWrites = countFileWritesByExt(session.toolCalls, CONTENT_EXTENSIONS);
66
+ // Exclude CLAUDE.md and similar config markdown
67
+ const nonConfigMdWrites = countContentFileWrites(session.toolCalls);
68
+ if (nonConfigMdWrites > 0) {
69
+ scores.content += nonConfigMdWrites * 3;
70
+ signals.push(`${nonConfigMdWrites} content file writes`);
71
+ }
72
+ // Long text writes (prose)
73
+ const longTextWrites = countLongTextWrites(session.toolCalls);
74
+ if (longTextWrites > 0) {
75
+ scores.content += longTextWrites * 2;
76
+ signals.push(`${longTextWrites} long text writes`);
77
+ }
78
+ // Few code files = more likely content
79
+ if (codeFilesInList === 0 && nonConfigMdWrites > 0) {
80
+ scores.content += 3;
81
+ }
82
+ // --- RESEARCH signals ---
83
+ const webCalls = (toolCounts["WebSearch"] || 0) + (toolCounts["WebFetch"] || 0);
84
+ if (webCalls > 0) {
85
+ scores.research += webCalls * 3;
86
+ signals.push(`${webCalls} web search/fetch calls`);
87
+ }
88
+ const readCalls = (toolCounts["Read"] || 0) + (toolCounts["Grep"] || 0) + (toolCounts["Glob"] || 0);
89
+ const writeCalls = (toolCounts["Write"] || 0) + (toolCounts["Edit"] || 0);
90
+ if (readCalls > writeCalls * 3 && readCalls > 5) {
91
+ scores.research += 4;
92
+ signals.push("read-heavy session");
93
+ }
94
+ // Long conversation with few file changes
95
+ if (session.userPromptCount > 10 && files.length < 3) {
96
+ scores.research += 2;
97
+ signals.push("long conversation, few files");
98
+ }
99
+ // --- AUTOMATION signals ---
100
+ const shellFileWrites = countFileWritesByExt(session.toolCalls, AUTOMATION_EXTENSIONS);
101
+ if (shellFileWrites > 0) {
102
+ scores.automation += shellFileWrites * 3;
103
+ signals.push(`${shellFileWrites} shell script writes`);
104
+ }
105
+ const ciCdFiles = files.filter((f) => CI_CD_PATTERNS.some((p) => f.includes(p))).length;
106
+ if (ciCdFiles > 0) {
107
+ scores.automation += ciCdFiles * 3;
108
+ signals.push(`${ciCdFiles} CI/CD file changes`);
109
+ }
110
+ // Bash-dominant session
111
+ if (toolCounts["Bash"] && totalToolCalls > 0) {
112
+ const bashRatio = (toolCounts["Bash"] || 0) / totalToolCalls;
113
+ if (bashRatio > 0.6 && (toolCounts["Bash"] || 0) > 5) {
114
+ scores.automation += 3;
115
+ signals.push("bash-dominant session");
116
+ }
117
+ }
118
+ // Cron patterns
119
+ const bashCommands = getBashCommands(session.toolCalls);
120
+ if (bashCommands.some((c) => c.includes("cron") || c.includes("launchctl") || c.includes("systemctl"))) {
121
+ scores.automation += 3;
122
+ signals.push("cron/service management");
123
+ }
124
+ // --- DESIGN signals ---
125
+ if (session.permissionMode === "plan") {
126
+ scores.design += 4;
127
+ signals.push("plan mode active");
128
+ }
129
+ if (toolCounts["ExitPlanMode"]) {
130
+ scores.design += 3;
131
+ signals.push("used plan mode");
132
+ }
133
+ // Low file count but high prompt count
134
+ if (files.length < 3 && session.userPromptCount > 15) {
135
+ scores.design += 2;
136
+ signals.push("discussion-heavy, few files");
137
+ }
138
+ // --- OPS signals ---
139
+ const configFileWrites = countFileWritesByExt(session.toolCalls, CONFIG_EXTENSIONS);
140
+ // Exclude package.json (already counted for code)
141
+ const opsConfigWrites = countOpsConfigWrites(session.toolCalls);
142
+ if (opsConfigWrites > 0) {
143
+ scores.ops += opsConfigWrites * 2;
144
+ signals.push(`${opsConfigWrites} config file writes`);
145
+ }
146
+ // .env files
147
+ if (files.some((f) => f.includes(".env"))) {
148
+ scores.ops += 3;
149
+ signals.push(".env file modified");
150
+ }
151
+ // mcp_servers.json or settings changes
152
+ if (files.some((f) => f.includes("mcp_servers") || f.includes("settings.json"))) {
153
+ scores.ops += 3;
154
+ signals.push("tool/settings config changes");
155
+ }
156
+ // --- DATA signals ---
157
+ const dataFileOps = countFileWritesByExt(session.toolCalls, DATA_EXTENSIONS);
158
+ if (dataFileOps > 0) {
159
+ scores.data += dataFileOps * 3;
160
+ signals.push(`${dataFileOps} data file operations`);
161
+ }
162
+ // SQL tool usage (Supabase MCP, etc.)
163
+ const sqlTools = Object.keys(toolCounts).filter((t) => t.includes("sql") || t.includes("database") || t.includes("supabase"));
164
+ const sqlCallCount = sqlTools.reduce((sum, t) => sum + (toolCounts[t] || 0), 0);
165
+ if (sqlCallCount > 0) {
166
+ scores.data += sqlCallCount * 2;
167
+ signals.push(`${sqlCallCount} database/SQL calls`);
168
+ }
169
+ // pandas/numpy in bash commands
170
+ if (bashCommands.some((c) => c.includes("pandas") || c.includes("numpy") || c.includes("jupyter"))) {
171
+ scores.data += 3;
172
+ signals.push("data science tooling");
173
+ }
174
+ // --- DEBUG signals ---
175
+ // Short session with only edits (no new files)
176
+ const hasNewFiles = (toolCounts["Write"] || 0) > 0;
177
+ const hasOnlyEdits = (toolCounts["Edit"] || 0) > 0 && !hasNewFiles;
178
+ if (hasOnlyEdits && session.userPromptCount < 10) {
179
+ scores.debug += 3;
180
+ signals.push("short edit-only session");
181
+ }
182
+ // Error/fix/bug keywords in summary
183
+ if (session.summary) {
184
+ const lower = session.summary.toLowerCase();
185
+ if (lower.includes("fix") || lower.includes("bug") || lower.includes("error") || lower.includes("debug")) {
186
+ scores.debug += 4;
187
+ signals.push("fix/bug/error in summary");
188
+ }
189
+ }
190
+ // Short session duration (< 15 min)
191
+ if (session.startTime && session.endTime) {
192
+ const durationMs = new Date(session.endTime).getTime() - new Date(session.startTime).getTime();
193
+ const durationMin = durationMs / 60000;
194
+ if (durationMin < 15 && hasOnlyEdits) {
195
+ scores.debug += 2;
196
+ signals.push("quick fix session");
197
+ }
198
+ }
199
+ // Pick the highest-scoring type. Tiebreak order per spec.
200
+ const tiebreakOrder = [
201
+ "code", "content", "research", "automation", "design", "ops", "data", "debug",
202
+ ];
203
+ let bestType = "code";
204
+ let bestScore = 0;
205
+ for (const type of tiebreakOrder) {
206
+ if (scores[type] > bestScore) {
207
+ bestScore = scores[type];
208
+ bestType = type;
209
+ }
210
+ }
211
+ // Confidence: how dominant is the top score vs the rest
212
+ const totalScore = Object.values(scores).reduce((a, b) => a + b, 0);
213
+ const confidence = totalScore > 0 ? bestScore / totalScore : 0;
214
+ return {
215
+ activityType: bestType,
216
+ scores,
217
+ confidence,
218
+ signals,
219
+ };
220
+ }
221
+ // --- Helper functions ---
222
+ function getExtension(filePath) {
223
+ const dot = filePath.lastIndexOf(".");
224
+ if (dot === -1)
225
+ return "";
226
+ return filePath.slice(dot).toLowerCase();
227
+ }
228
+ function countTools(toolCalls) {
229
+ const counts = {};
230
+ for (const tc of toolCalls) {
231
+ counts[tc.name] = (counts[tc.name] || 0) + 1;
232
+ }
233
+ return counts;
234
+ }
235
+ function getBashCommands(toolCalls) {
236
+ return toolCalls
237
+ .filter((tc) => tc.name === "Bash")
238
+ .map((tc) => tc.input.command || "")
239
+ .filter(Boolean);
240
+ }
241
+ function countFileWritesByExt(toolCalls, extensions) {
242
+ let count = 0;
243
+ for (const tc of toolCalls) {
244
+ if (tc.name === "Write" || tc.name === "Edit") {
245
+ const fp = tc.input.file_path || "";
246
+ if (extensions.has(getExtension(fp)))
247
+ count++;
248
+ }
249
+ }
250
+ return count;
251
+ }
252
+ /** Count .md file writes that aren't CLAUDE.md, SKILL.md, plan files, etc. */
253
+ function countContentFileWrites(toolCalls) {
254
+ let count = 0;
255
+ for (const tc of toolCalls) {
256
+ if (tc.name === "Write" || tc.name === "Edit") {
257
+ const fp = tc.input.file_path || "";
258
+ const ext = getExtension(fp);
259
+ if (CONTENT_EXTENSIONS.has(ext)) {
260
+ const lower = fp.toLowerCase();
261
+ if (!lower.includes("claude.md") &&
262
+ !lower.includes("skill.md") &&
263
+ !lower.includes("/plans/") &&
264
+ !lower.includes("readme.md") &&
265
+ !lower.includes("changelog")) {
266
+ count++;
267
+ }
268
+ }
269
+ }
270
+ }
271
+ return count;
272
+ }
273
+ /** Count Write calls with content > 500 chars (long prose). */
274
+ function countLongTextWrites(toolCalls) {
275
+ let count = 0;
276
+ for (const tc of toolCalls) {
277
+ if (tc.name === "Write") {
278
+ const content = tc.input.content || "";
279
+ if (content.length > 500 && !content.includes("import ") && !content.includes("function ")) {
280
+ count++;
281
+ }
282
+ }
283
+ }
284
+ return count;
285
+ }
286
+ /** Count config file writes, excluding package.json (code signal). */
287
+ function countOpsConfigWrites(toolCalls) {
288
+ let count = 0;
289
+ for (const tc of toolCalls) {
290
+ if (tc.name === "Write" || tc.name === "Edit") {
291
+ const fp = tc.input.file_path || "";
292
+ const ext = getExtension(fp);
293
+ if (CONFIG_EXTENSIONS.has(ext) && !fp.endsWith("package.json") && !fp.endsWith("tsconfig.json")) {
294
+ count++;
295
+ }
296
+ }
297
+ }
298
+ return count;
299
+ }
300
+ //# sourceMappingURL=activity-classifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity-classifier.js","sourceRoot":"","sources":["../../../src/classifiers/activity-classifier.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import type { ActivityType } from "./activity-classifier.js";
2
+ export type PathType = "builder" | "storyteller" | "systems" | "builder+storyteller" | "builder+systems" | "storyteller+systems";
3
+ export interface PathResult {
4
+ path: PathType;
5
+ scores: {
6
+ builder: number;
7
+ storyteller: number;
8
+ systems: number;
9
+ };
10
+ distribution: Record<ActivityType, number>;
11
+ totalSessions: number;
12
+ }
13
+ /**
14
+ * Detect the user's path from their activity type distribution.
15
+ * Requires 10+ classified sessions for a meaningful result.
16
+ *
17
+ * Per the spec:
18
+ * builder_score = (code% + ops% + debug% + design%) with code weighted 2x
19
+ * storyteller_score = (content% + research% + design%) with content weighted 2x
20
+ * systems_score = (automation% + data% + ops% + research%) with automation weighted 2x
21
+ *
22
+ * Hybrid path when top two scores are within 15% of each other.
23
+ */
24
+ export declare function detectPath(activityTypes: ActivityType[]): PathResult | null;
25
+ /**
26
+ * Get a human-readable path label.
27
+ */
28
+ export declare function getPathLabel(path: PathType): string;
29
+ /**
30
+ * Format the fingerprint as a readable string.
31
+ * e.g. "Builder (58% Code, 22% Ops, 12% Content, 8% Research)"
32
+ */
33
+ export declare function formatFingerprint(result: PathResult): string;
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Detect the user's path from their activity type distribution.
3
+ * Requires 10+ classified sessions for a meaningful result.
4
+ *
5
+ * Per the spec:
6
+ * builder_score = (code% + ops% + debug% + design%) with code weighted 2x
7
+ * storyteller_score = (content% + research% + design%) with content weighted 2x
8
+ * systems_score = (automation% + data% + ops% + research%) with automation weighted 2x
9
+ *
10
+ * Hybrid path when top two scores are within 15% of each other.
11
+ */
12
+ export function detectPath(activityTypes) {
13
+ if (activityTypes.length < 10)
14
+ return null;
15
+ const total = activityTypes.length;
16
+ const counts = {
17
+ code: 0,
18
+ content: 0,
19
+ research: 0,
20
+ automation: 0,
21
+ design: 0,
22
+ ops: 0,
23
+ data: 0,
24
+ debug: 0,
25
+ };
26
+ for (const type of activityTypes) {
27
+ counts[type]++;
28
+ }
29
+ // Convert to percentages
30
+ const pct = {};
31
+ for (const [type, count] of Object.entries(counts)) {
32
+ pct[type] = count / total;
33
+ }
34
+ // Compute path scores per spec
35
+ const builderScore = pct.code * 2 + pct.ops + pct.debug + pct.design;
36
+ const storytellerScore = pct.content * 2 + pct.research + pct.design;
37
+ const systemsScore = pct.automation * 2 + pct.data + pct.ops + pct.research;
38
+ // Normalize to sum to 1
39
+ const scoreTotal = builderScore + storytellerScore + systemsScore;
40
+ const scores = {
41
+ builder: scoreTotal > 0 ? builderScore / scoreTotal : 0,
42
+ storyteller: scoreTotal > 0 ? storytellerScore / scoreTotal : 0,
43
+ systems: scoreTotal > 0 ? systemsScore / scoreTotal : 0,
44
+ };
45
+ // Determine path — hybrid if top two within 15%
46
+ const ranked = Object.entries(scores).sort((a, b) => b[1] - a[1]);
47
+ const [first, second] = ranked;
48
+ const gap = first[1] - second[1];
49
+ let path;
50
+ if (gap <= 0.15) {
51
+ // Hybrid path — combine top two alphabetically
52
+ const pair = [first[0], second[0]].sort();
53
+ path = `${pair[0]}+${pair[1]}`;
54
+ }
55
+ else {
56
+ path = first[0];
57
+ }
58
+ return {
59
+ path,
60
+ scores,
61
+ distribution: { ...counts },
62
+ totalSessions: total,
63
+ };
64
+ }
65
+ /**
66
+ * Get a human-readable path label.
67
+ */
68
+ export function getPathLabel(path) {
69
+ const labels = {
70
+ builder: "Builder",
71
+ storyteller: "Storyteller",
72
+ systems: "Systems Thinker",
73
+ "builder+storyteller": "Builder + Storyteller",
74
+ "builder+systems": "Builder + Systems Thinker",
75
+ "storyteller+systems": "Storyteller + Systems Thinker",
76
+ };
77
+ return labels[path] || path;
78
+ }
79
+ /**
80
+ * Format the fingerprint as a readable string.
81
+ * e.g. "Builder (58% Code, 22% Ops, 12% Content, 8% Research)"
82
+ */
83
+ export function formatFingerprint(result) {
84
+ const label = getPathLabel(result.path);
85
+ // Sort activity types by count descending
86
+ const sorted = Object.entries(result.distribution)
87
+ .filter(([, count]) => count > 0)
88
+ .sort((a, b) => b[1] - a[1]);
89
+ const parts = sorted.map(([type, count]) => {
90
+ const pct = Math.round((count / result.totalSessions) * 100);
91
+ return `${pct}% ${capitalize(type)}`;
92
+ });
93
+ return `${label} (${parts.join(", ")})`;
94
+ }
95
+ function capitalize(s) {
96
+ return s.charAt(0).toUpperCase() + s.slice(1);
97
+ }
98
+ //# sourceMappingURL=path-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-detector.js","sourceRoot":"","sources":["../../../src/classifiers/path-detector.ts"],"names":[],"mappings":"AAeA;;;;;;;;;;GAUG;AACH,MAAM,UAAU,UAAU,CAAC,aAA6B;IACtD,IAAI,aAAa,CAAC,MAAM,GAAG,EAAE;QAAE,OAAO,IAAI,CAAC;IAE3C,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,CAAC;IACnC,MAAM,MAAM,GAAiC;QAC3C,IAAI,EAAE,CAAC;QACP,OAAO,EAAE,CAAC;QACV,QAAQ,EAAE,CAAC;QACX,UAAU,EAAE,CAAC;QACb,MAAM,EAAE,CAAC;QACT,GAAG,EAAE,CAAC;QACN,IAAI,EAAE,CAAC;QACP,KAAK,EAAE,CAAC;KACT,CAAC;IAEF,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;QACjC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;IACjB,CAAC;IAED,yBAAyB;IACzB,MAAM,GAAG,GAAiC,EAAkC,CAAC;IAC7E,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACnD,GAAG,CAAC,IAAoB,CAAC,GAAG,KAAK,GAAG,KAAK,CAAC;IAC5C,CAAC;IAED,+BAA+B;IAC/B,MAAM,YAAY,GAChB,GAAG,CAAC,IAAI,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC;IAClD,MAAM,gBAAgB,GACpB,GAAG,CAAC,OAAO,GAAG,CAAC,GAAG,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC;IAC9C,MAAM,YAAY,GAChB,GAAG,CAAC,UAAU,GAAG,CAAC,GAAG,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,QAAQ,CAAC;IAEzD,wBAAwB;IACxB,MAAM,UAAU,GAAG,YAAY,GAAG,gBAAgB,GAAG,YAAY,CAAC;IAClE,MAAM,MAAM,GAAG;QACb,OAAO,EAAE,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;QACvD,WAAW,EAAE,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,gBAAgB,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;QAC/D,OAAO,EAAE,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;KACxD,CAAC;IAEF,gDAAgD;IAChD,MAAM,MAAM,GACV,MAAM,CAAC,OAAO,CAAC,MAAM,CACtB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAE9B,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC;IAC/B,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IAEjC,IAAI,IAAc,CAAC;IACnB,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;QAChB,+CAA+C;QAC/C,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAgD,CAAC;QACxF,IAAI,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,EAAc,CAAC;IAC7C,CAAC;SAAM,CAAC;QACN,IAAI,GAAG,KAAK,CAAC,CAAC,CAAa,CAAC;IAC9B,CAAC;IAED,OAAO;QACL,IAAI;QACJ,MAAM;QACN,YAAY,EAAE,EAAE,GAAG,MAAM,EAAE;QAC3B,aAAa,EAAE,KAAK;KACrB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,IAAc;IACzC,MAAM,MAAM,GAA2B;QACrC,OAAO,EAAE,SAAS;QAClB,WAAW,EAAE,aAAa;QAC1B,OAAO,EAAE,iBAAiB;QAC1B,qBAAqB,EAAE,uBAAuB;QAC9C,iBAAiB,EAAE,2BAA2B;QAC9C,qBAAqB,EAAE,+BAA+B;KACvD,CAAC;IACF,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;AAC9B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAkB;IAClD,MAAM,KAAK,GAAG,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAExC,0CAA0C;IAC1C,MAAM,MAAM,GAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,CAA8B;SAC7E,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC;SAChC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAE/B,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE;QACzC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,MAAM,CAAC,aAAa,CAAC,GAAG,GAAG,CAAC,CAAC;QAC7D,OAAO,GAAG,GAAG,KAAK,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,KAAK,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;AAC1C,CAAC;AAED,SAAS,UAAU,CAAC,CAAS;IAC3B,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAChD,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Hook handler: classify + log the most recent session.
3
+ * Called by the Claude Code "stop" hook after every session.
4
+ *
5
+ * Requirements:
6
+ * - Must complete in <1 second
7
+ * - Must not produce any stdout (silent)
8
+ * - Must not fail loudly; errors go to ~/.myplayer/errors.log
9
+ */
10
+ export declare function logSession(): Promise<void>;