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,73 @@
1
+ export interface SkillStatus {
2
+ total_uses: number;
3
+ last_used: string | null;
4
+ last_improved: string | null;
5
+ uses_since_improved: number;
6
+ }
7
+ export interface StatusData {
8
+ installed_at: string;
9
+ improve_skill: {
10
+ last_ran: string | null;
11
+ skills_used_since: string[];
12
+ total_skill_uses_since: number;
13
+ };
14
+ log_experience: {
15
+ last_ran: string | null;
16
+ sessions_since: number;
17
+ days_since: number;
18
+ };
19
+ skills: Record<string, SkillStatus>;
20
+ last_reminded: Record<string, string>;
21
+ }
22
+ export interface ConsumptionEvent {
23
+ skill: string;
24
+ timestamp: string;
25
+ environment?: string;
26
+ session_context?: string;
27
+ reset?: string;
28
+ skill_improved?: string;
29
+ training_topic?: string;
30
+ training_version?: string;
31
+ tier?: string;
32
+ }
33
+ export interface Reminder {
34
+ type: "improve_skill" | "log_experience" | "skill_stale" | "update_available";
35
+ message: string;
36
+ priority: "high" | "medium" | "low";
37
+ }
38
+ export interface VersionInfo {
39
+ current: string;
40
+ latest: string | null;
41
+ update_available: boolean;
42
+ }
43
+ export declare function readStatus(): StatusData;
44
+ export declare function writeStatus(status: StatusData): void;
45
+ export declare function initializeStatus(): void;
46
+ export declare function logConsumption(event: ConsumptionEvent): void;
47
+ export declare function readConsumption(): ConsumptionEvent[];
48
+ export declare function checkStatus(skillName: string, sessionContext?: string): Promise<{
49
+ reminders: Reminder[];
50
+ version: VersionInfo;
51
+ quest_completed?: {
52
+ completed_quest: string;
53
+ next_quest: {
54
+ id: string;
55
+ title: string;
56
+ description: string;
57
+ prompt: string;
58
+ } | null;
59
+ message: string;
60
+ };
61
+ }>;
62
+ export declare function resetStatus(type: "improve_skill" | "log_experience", skillImproved?: string): {
63
+ success: boolean;
64
+ };
65
+ export declare function incrementSessionCounter(): void;
66
+ export declare function getConsumptionMetrics(): {
67
+ total_skill_runs: number;
68
+ runs_by_skill: Record<string, number>;
69
+ runs_by_day: Record<string, number>;
70
+ runs_by_environment: Record<string, number>;
71
+ environment_percentage: Record<string, number>;
72
+ recent_events: ConsumptionEvent[];
73
+ };
@@ -0,0 +1,372 @@
1
+ import { readFileSync, writeFileSync, appendFileSync, existsSync } from "fs";
2
+ import { join, dirname } from "path";
3
+ import { homedir } from "os";
4
+ import { fileURLToPath } from "url";
5
+ import { ensureDir } from "./local-store.js";
6
+ import { tryAutoCompleteQuest } from "./quest-store.js";
7
+ import { apiPost } from "../api-client.js";
8
+ import { skillCommand } from "../constants.js";
9
+ const __filename = fileURLToPath(import.meta.url);
10
+ const __dirname = dirname(__filename);
11
+ const MYPLAYER_DIR = join(homedir(), ".myplayer");
12
+ const STATUS_PATH = join(MYPLAYER_DIR, "status.json");
13
+ const CONSUMPTION_PATH = join(MYPLAYER_DIR, "consumption.jsonl");
14
+ const VERSION_CACHE_PATH = join(MYPLAYER_DIR, "version-check.json");
15
+ const VERSION_CHECK_TTL_MS = 24 * 60 * 60 * 1000; // 24 hours
16
+ // --- Thresholds ---
17
+ const THRESHOLDS = {
18
+ improve_skill: {
19
+ uses_since_threshold: 10,
20
+ days_since_threshold: 14,
21
+ },
22
+ log_experience: {
23
+ days_since_threshold: 7,
24
+ sessions_since_threshold: 15,
25
+ },
26
+ skill_staleness: {
27
+ uses_since_improved: 15,
28
+ days_since_improved: 30,
29
+ },
30
+ grace_period_days: 7,
31
+ reminder_cooldown_hours: 24,
32
+ };
33
+ // --- Status File ---
34
+ export function readStatus() {
35
+ try {
36
+ return JSON.parse(readFileSync(STATUS_PATH, "utf-8"));
37
+ }
38
+ catch {
39
+ return createDefaultStatus();
40
+ }
41
+ }
42
+ export function writeStatus(status) {
43
+ ensureDir();
44
+ writeFileSync(STATUS_PATH, JSON.stringify(status, null, 2) + "\n");
45
+ }
46
+ export function initializeStatus() {
47
+ if (existsSync(STATUS_PATH))
48
+ return;
49
+ const status = createDefaultStatus();
50
+ writeStatus(status);
51
+ }
52
+ function createDefaultStatus() {
53
+ const now = new Date().toISOString();
54
+ return {
55
+ installed_at: now,
56
+ improve_skill: {
57
+ last_ran: null,
58
+ skills_used_since: [],
59
+ total_skill_uses_since: 0,
60
+ },
61
+ log_experience: {
62
+ last_ran: null,
63
+ sessions_since: 0,
64
+ days_since: 0,
65
+ },
66
+ skills: {},
67
+ last_reminded: {},
68
+ };
69
+ }
70
+ // --- Consumption Log ---
71
+ export function logConsumption(event) {
72
+ ensureDir();
73
+ appendFileSync(CONSUMPTION_PATH, JSON.stringify(event) + "\n");
74
+ }
75
+ export function readConsumption() {
76
+ try {
77
+ const raw = readFileSync(CONSUMPTION_PATH, "utf-8");
78
+ const events = [];
79
+ for (const line of raw.split("\n")) {
80
+ const trimmed = line.trim();
81
+ if (!trimmed)
82
+ continue;
83
+ try {
84
+ events.push(JSON.parse(trimmed));
85
+ }
86
+ catch {
87
+ // skip malformed
88
+ }
89
+ }
90
+ return events;
91
+ }
92
+ catch {
93
+ return [];
94
+ }
95
+ }
96
+ // --- Check Status ---
97
+ export async function checkStatus(skillName, sessionContext) {
98
+ const status = readStatus();
99
+ const now = new Date();
100
+ // Detect environment for analytics
101
+ const env = detectRunEnvironment();
102
+ // Log the consumption event
103
+ logConsumption({
104
+ skill: skillName,
105
+ timestamp: now.toISOString(),
106
+ environment: env,
107
+ session_context: sessionContext,
108
+ });
109
+ // Update skill tracking
110
+ if (!status.skills[skillName]) {
111
+ status.skills[skillName] = {
112
+ total_uses: 0,
113
+ last_used: null,
114
+ last_improved: null,
115
+ uses_since_improved: 0,
116
+ };
117
+ }
118
+ status.skills[skillName].total_uses++;
119
+ status.skills[skillName].last_used = now.toISOString();
120
+ status.skills[skillName].uses_since_improved++;
121
+ // Update global tracking
122
+ status.improve_skill.skills_used_since.push(skillName);
123
+ status.improve_skill.total_skill_uses_since++;
124
+ writeStatus(status);
125
+ // Auto-complete quest if this skill matches an active quest
126
+ const questResult = tryAutoCompleteQuest(skillName);
127
+ // Sync quest completion to server so the dashboard updates
128
+ if (questResult) {
129
+ // Find the quest ID from the completed quest title
130
+ const { QUEST_DEFINITIONS } = await import("./quest-store.js");
131
+ const completedDef = QUEST_DEFINITIONS.find((q) => q.title === questResult.completed_quest);
132
+ if (completedDef) {
133
+ apiPost("/api/myplayer/quests", { completed_quest_id: completedDef.id }).catch(() => { });
134
+ }
135
+ }
136
+ // Version check (non-blocking, cached 24h)
137
+ const version = await getVersionInfo();
138
+ // Check grace period (no reminders for first 7 days)
139
+ const installedAt = new Date(status.installed_at);
140
+ const daysSinceInstall = daysBetween(installedAt, now);
141
+ if (daysSinceInstall < THRESHOLDS.grace_period_days) {
142
+ return { reminders: [], version, ...(questResult && { quest_completed: questResult }) };
143
+ }
144
+ // Generate reminders
145
+ const reminders = [];
146
+ // Priority 1: Skill improvement overdue
147
+ if (status.improve_skill.total_skill_uses_since >= THRESHOLDS.improve_skill.uses_since_threshold &&
148
+ !isOnCooldown(status, "improve_skill", now)) {
149
+ reminders.push({
150
+ type: "improve_skill",
151
+ message: `You've used skills ${status.improve_skill.total_skill_uses_since} times since your last ${skillCommand("improve-skill")} run. If anything felt off or you gave feedback that should be permanent, run ${skillCommand("improve-skill")} to bake it in.`,
152
+ priority: "high",
153
+ });
154
+ status.last_reminded.improve_skill = now.toISOString();
155
+ }
156
+ // Priority 2: Experience logging overdue
157
+ if (status.log_experience.last_ran) {
158
+ const daysSinceLog = daysBetween(new Date(status.log_experience.last_ran), now);
159
+ if (daysSinceLog >= THRESHOLDS.log_experience.days_since_threshold &&
160
+ !isOnCooldown(status, "log_experience", now)) {
161
+ reminders.push({
162
+ type: "log_experience",
163
+ message: `It's been ${daysSinceLog} days since you last ran ${skillCommand("log-experience")}. Your recent sessions won't make it into future scripts or content unless you capture them.`,
164
+ priority: "medium",
165
+ });
166
+ status.last_reminded.log_experience = now.toISOString();
167
+ }
168
+ }
169
+ else if (status.log_experience.sessions_since >= THRESHOLDS.log_experience.sessions_since_threshold &&
170
+ !isOnCooldown(status, "log_experience", now)) {
171
+ reminders.push({
172
+ type: "log_experience",
173
+ message: `You've had ${status.log_experience.sessions_since} sessions but haven't run ${skillCommand("log-experience")} yet. Capture what you've learned so your system keeps growing.`,
174
+ priority: "medium",
175
+ });
176
+ status.last_reminded.log_experience = now.toISOString();
177
+ }
178
+ // Priority 3: Specific skill is stale
179
+ const thisSkill = status.skills[skillName];
180
+ if (thisSkill?.uses_since_improved >= THRESHOLDS.skill_staleness.uses_since_improved &&
181
+ !isOnCooldown(status, `skill_stale_${skillName}`, now)) {
182
+ reminders.push({
183
+ type: "skill_stale",
184
+ message: `You've used /${skillName} ${thisSkill.uses_since_improved} times since it was last improved. If the output could be better, run: ${skillCommand("improve-skill")} ${skillName}`,
185
+ priority: "low",
186
+ });
187
+ status.last_reminded[`skill_stale_${skillName}`] = now.toISOString();
188
+ }
189
+ // Priority 4: Version update available
190
+ if (version.update_available &&
191
+ !isOnCooldown(status, "update_available", now)) {
192
+ reminders.push({
193
+ type: "update_available",
194
+ message: `BuildPartner ${version.latest} is available (you have ${version.current}). Run: npx buildpartner@latest setup`,
195
+ priority: "low",
196
+ });
197
+ status.last_reminded.update_available = now.toISOString();
198
+ }
199
+ if (reminders.length > 0) {
200
+ writeStatus(status);
201
+ }
202
+ return { reminders: reminders.slice(0, 2), version, ...(questResult && { quest_completed: questResult }) };
203
+ }
204
+ // --- Reset Status ---
205
+ export function resetStatus(type, skillImproved) {
206
+ const status = readStatus();
207
+ const now = new Date().toISOString();
208
+ if (type === "improve_skill") {
209
+ status.improve_skill.last_ran = now;
210
+ status.improve_skill.total_skill_uses_since = 0;
211
+ status.improve_skill.skills_used_since = [];
212
+ if (skillImproved && status.skills[skillImproved]) {
213
+ status.skills[skillImproved].uses_since_improved = 0;
214
+ status.skills[skillImproved].last_improved = now;
215
+ }
216
+ logConsumption({ skill: "improve-skill", timestamp: now, reset: "improve_skill", skill_improved: skillImproved });
217
+ }
218
+ else if (type === "log_experience") {
219
+ status.log_experience.last_ran = now;
220
+ status.log_experience.sessions_since = 0;
221
+ logConsumption({ skill: "log-experience", timestamp: now, reset: "log_experience" });
222
+ }
223
+ writeStatus(status);
224
+ return { success: true };
225
+ }
226
+ // --- Increment Session Counter (called by stop hook) ---
227
+ export function incrementSessionCounter() {
228
+ const status = readStatus();
229
+ status.log_experience.sessions_since++;
230
+ writeStatus(status);
231
+ }
232
+ // --- Admin / Metrics ---
233
+ export function getConsumptionMetrics() {
234
+ const events = readConsumption();
235
+ const runsBySkill = {};
236
+ const runsByDay = {};
237
+ const runsByEnv = {};
238
+ for (const e of events) {
239
+ runsBySkill[e.skill] = (runsBySkill[e.skill] || 0) + 1;
240
+ const day = e.timestamp.slice(0, 10);
241
+ runsByDay[day] = (runsByDay[day] || 0) + 1;
242
+ const env = e.environment || "unknown";
243
+ runsByEnv[env] = (runsByEnv[env] || 0) + 1;
244
+ }
245
+ // Calculate percentages
246
+ const total = events.length || 1;
247
+ const envPct = {};
248
+ for (const [env, count] of Object.entries(runsByEnv)) {
249
+ envPct[env] = Math.round((count / total) * 100);
250
+ }
251
+ return {
252
+ total_skill_runs: events.length,
253
+ runs_by_skill: runsBySkill,
254
+ runs_by_day: runsByDay,
255
+ runs_by_environment: runsByEnv,
256
+ environment_percentage: envPct,
257
+ recent_events: events.slice(-50),
258
+ };
259
+ }
260
+ // --- Environment Detection (per-call, more accurate than stored) ---
261
+ function detectRunEnvironment() {
262
+ if (process.env.TERM_PROGRAM === "vscode" || process.env.VSCODE_PID)
263
+ return "vscode";
264
+ if (process.env.CLAUDE_DESKTOP)
265
+ return "claude-desktop";
266
+ if (process.env.CLAUDE_CODE)
267
+ return "claude-cowork";
268
+ if (!process.stdin.isTTY)
269
+ return "non-interactive";
270
+ return "terminal";
271
+ }
272
+ // --- Version Check ---
273
+ function getCurrentVersion() {
274
+ try {
275
+ // Walk up from dist/src/store/ to find package.json
276
+ const paths = [
277
+ join(__dirname, "..", "..", "..", "package.json"), // from dist/src/store/
278
+ join(__dirname, "..", "..", "package.json"),
279
+ ];
280
+ for (const p of paths) {
281
+ if (existsSync(p)) {
282
+ const pkg = JSON.parse(readFileSync(p, "utf-8"));
283
+ if (pkg.version)
284
+ return pkg.version;
285
+ }
286
+ }
287
+ }
288
+ catch {
289
+ // ignore
290
+ }
291
+ return "0.0.0";
292
+ }
293
+ async function fetchLatestVersion() {
294
+ try {
295
+ const controller = new AbortController();
296
+ const timeout = setTimeout(() => controller.abort(), 3000);
297
+ const res = await fetch("https://registry.npmjs.org/buildpartner/latest", {
298
+ signal: controller.signal,
299
+ });
300
+ clearTimeout(timeout);
301
+ if (!res.ok)
302
+ return null;
303
+ const data = (await res.json());
304
+ return data.version || null;
305
+ }
306
+ catch {
307
+ return null;
308
+ }
309
+ }
310
+ function compareVersions(current, latest) {
311
+ const c = current.split(".").map(Number);
312
+ const l = latest.split(".").map(Number);
313
+ for (let i = 0; i < 3; i++) {
314
+ if ((l[i] || 0) > (c[i] || 0))
315
+ return true;
316
+ if ((l[i] || 0) < (c[i] || 0))
317
+ return false;
318
+ }
319
+ return false;
320
+ }
321
+ async function getVersionInfo() {
322
+ const current = getCurrentVersion();
323
+ // Check cache first
324
+ try {
325
+ if (existsSync(VERSION_CACHE_PATH)) {
326
+ const cache = JSON.parse(readFileSync(VERSION_CACHE_PATH, "utf-8"));
327
+ const age = Date.now() - new Date(cache.checked_at).getTime();
328
+ if (age < VERSION_CHECK_TTL_MS && cache.latest) {
329
+ return {
330
+ current,
331
+ latest: cache.latest,
332
+ update_available: compareVersions(current, cache.latest),
333
+ };
334
+ }
335
+ }
336
+ }
337
+ catch {
338
+ // ignore cache errors
339
+ }
340
+ // Fetch from npm (non-blocking, 3s timeout)
341
+ const latest = await fetchLatestVersion();
342
+ // Update cache
343
+ if (latest) {
344
+ try {
345
+ ensureDir();
346
+ writeFileSync(VERSION_CACHE_PATH, JSON.stringify({
347
+ latest,
348
+ checked_at: new Date().toISOString(),
349
+ }));
350
+ }
351
+ catch {
352
+ // ignore
353
+ }
354
+ }
355
+ return {
356
+ current,
357
+ latest,
358
+ update_available: latest ? compareVersions(current, latest) : false,
359
+ };
360
+ }
361
+ // --- Helpers ---
362
+ function daysBetween(a, b) {
363
+ return Math.floor((b.getTime() - a.getTime()) / (1000 * 60 * 60 * 24));
364
+ }
365
+ function isOnCooldown(status, reminderType, now) {
366
+ const lastReminded = status.last_reminded[reminderType];
367
+ if (!lastReminded)
368
+ return false;
369
+ const hoursSince = (now.getTime() - new Date(lastReminded).getTime()) / (1000 * 60 * 60);
370
+ return hoursSince < THRESHOLDS.reminder_cooldown_hours;
371
+ }
372
+ //# sourceMappingURL=status-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status-store.js","sourceRoot":"","sources":["../../../src/store/status-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=rules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules.js","sourceRoot":"","sources":["../../../src/suggestions/rules.ts"],"names":[],"mappings":""}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=video-links.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video-links.js","sourceRoot":"","sources":["../../../src/suggestions/video-links.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "buildpartner",
3
+ "version": "0.3.0",
4
+ "type": "module",
5
+ "description": "Your AI build partner. Expert guidance inside Claude Code.",
6
+ "bin": {
7
+ "buildpartner": "./dist/bin/cli.js"
8
+ },
9
+ "exports": {
10
+ ".": "./dist/bin/cli.js",
11
+ "./constants": "./dist/src/constants.js"
12
+ },
13
+ "files": [
14
+ "dist",
15
+ "skills"
16
+ ],
17
+ "scripts": {
18
+ "build": "tsc",
19
+ "dev": "tsx bin/cli.ts"
20
+ },
21
+ "dependencies": {
22
+ "@inquirer/prompts": "^7",
23
+ "@modelcontextprotocol/sdk": "latest",
24
+ "chalk": "^5",
25
+ "inquirer": "^12",
26
+ "ora": "^8",
27
+ "uuid": "^11"
28
+ },
29
+ "devDependencies": {
30
+ "@types/node": "^22",
31
+ "@types/uuid": "^10",
32
+ "tsx": "^4",
33
+ "typescript": "^5"
34
+ }
35
+ }
@@ -0,0 +1,56 @@
1
+ # /he-coach
2
+
3
+ Review my setup and tell me what to improve. Looks at how you use Claude Code, what tools you're missing, what patterns to fix. Gives you 3 action items.
4
+
5
+ ## MCP Tools
6
+
7
+ Only call tools that are registered on the `myplayer` MCP server. If a tool call fails or a tool name isn't recognized, do not retry with a different name. The available tools are: `get_personal_context`, `get_expert_knowledge`, `save_profile`, `get_quest_progress`, `check_status`.
8
+
9
+ ## Instructions
10
+
11
+ 1. Call `get_personal_context` with `{ "include_sessions": true }`.
12
+
13
+ 2. From the returned data, analyze:
14
+
15
+ ### Setup Review
16
+ - What MCP servers are they using? What are they missing?
17
+ - What skills have they tried? What haven't they touched?
18
+ - What tools do they lean on vs. underuse? (e.g., heavy Read but no Grep)
19
+ - Are they using hooks? Plans? Agents?
20
+
21
+ ### Usage Patterns
22
+ - Are they stuck in one activity type? (all code, no automation)
23
+ - Are sessions getting shorter or longer? (efficiency signal)
24
+ - What projects are they spending the most time on?
25
+
26
+ ### What to Do Next
27
+ - Give exactly 3 actionable items, ranked by impact
28
+ - Each should be specific and doable THIS WEEK
29
+ - Reference their actual projects and patterns, not generic advice
30
+
31
+ 3. Format the review:
32
+
33
+ ```
34
+ ## Your Setup Review
35
+
36
+ **Activity**: {X sessions, Y tokens, main focus: Z}
37
+ **Streak**: {current streak}
38
+ **Subscription**: {trial/active/expired}
39
+
40
+ ### What's working
41
+ - {1-2 things they're doing well}
42
+
43
+ ### What to improve
44
+ 1. {Most impactful action item with specific steps}
45
+ 2. {Second action item}
46
+ 3. {Third action item}
47
+
48
+ ### Quick win
49
+ {One thing they can do in the next 5 minutes}
50
+ ```
51
+
52
+ 4. Keep the tone direct and encouraging. No fluff, just "here's what to do."
53
+
54
+ 5. If they have < 5 sessions, say: "Keep going. After a few more sessions I'll have real recommendations. For now, try /he-interview to build your profile."
55
+
56
+ 6. Call `check_status` with `{ "skill_name": "coach" }`.
@@ -0,0 +1,43 @@
1
+ # /he-consult
2
+
3
+ I need expert help with something. Ask any question and get matched to the right framework: pricing, content, launch, AI automation, marketing, sales, product strategy, and more.
4
+
5
+ ## MCP Tools
6
+
7
+ Only call tools that are registered on the `myplayer` MCP server. If a tool call fails or a tool name isn't recognized, do not retry with a different name. The available tools are: `get_personal_context`, `get_expert_knowledge`, `save_profile`, `get_quest_progress`, `check_status`.
8
+
9
+ ## Instructions
10
+
11
+ 1. Take the user's question or problem description.
12
+
13
+ 2. Call `get_expert_knowledge` with a `query` based on their question. This returns:
14
+ - Matching expert frameworks
15
+ - The user's personal context (stats, AI profile, what they build)
16
+
17
+ 3. If the search returns multiple matching topics, pick the 1-2 most relevant and call `get_expert_knowledge` again with the specific `topic` key to get the full framework content.
18
+
19
+ 4. Apply the framework to the user's specific situation. Be a consultant, not a parrot:
20
+ - Use their personal context to make advice specific (their projects, their stack, their patterns)
21
+ - Ask 1-2 clarifying questions if needed
22
+ - Challenge their assumptions
23
+ - Give them a concrete next step they can do RIGHT NOW
24
+
25
+ 5. Format your response as a consultation:
26
+
27
+ ```
28
+ ## Your Situation
29
+ [Restate their problem using what you know about them from personal context]
30
+
31
+ ## Framework
32
+ [Which expert framework applies and why]
33
+
34
+ ## Recommendation
35
+ [Specific, actionable advice tailored to their situation]
36
+
37
+ ## Next Step
38
+ [One concrete thing to do right now]
39
+ ```
40
+
41
+ 6. If their question spans multiple domains, acknowledge it and pull from multiple frameworks. You have access to everything: don't silo yourself.
42
+
43
+ 7. Call `check_status` with `{ "skill_name": "consult" }`.