vibebusiness 1.2.49 → 1.2.51

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 (70) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-build-manifest.json +17 -17
  3. package/.next/standalone/.next/app-path-routes-manifest.json +1 -1
  4. package/.next/standalone/.next/build-manifest.json +2 -2
  5. package/.next/standalone/.next/prerender-manifest.json +1 -1
  6. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  7. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  8. package/.next/standalone/.next/server/app/_not-found.rsc +1 -1
  9. package/.next/standalone/.next/server/app/api/analyze/route.js.nft.json +1 -1
  10. package/.next/standalone/.next/server/app/api/config/route.js.nft.json +1 -1
  11. package/.next/standalone/.next/server/app/api/epics/[id]/ideas/route.js.nft.json +1 -1
  12. package/.next/standalone/.next/server/app/api/epics/[id]/route.js.nft.json +1 -1
  13. package/.next/standalone/.next/server/app/api/epics/route.js.nft.json +1 -1
  14. package/.next/standalone/.next/server/app/api/goals/[id]/kpis/route.js.nft.json +1 -1
  15. package/.next/standalone/.next/server/app/api/goals/[id]/route.js.nft.json +1 -1
  16. package/.next/standalone/.next/server/app/api/goals/route.js.nft.json +1 -1
  17. package/.next/standalone/.next/server/app/api/hypotheses/[id]/route.js.nft.json +1 -1
  18. package/.next/standalone/.next/server/app/api/hypotheses/route.js.nft.json +1 -1
  19. package/.next/standalone/.next/server/app/api/ideas/[id]/comments/route.js.nft.json +1 -1
  20. package/.next/standalone/.next/server/app/api/ideas/[id]/implement/route.js.nft.json +1 -1
  21. package/.next/standalone/.next/server/app/api/ideas/[id]/route.js.nft.json +1 -1
  22. package/.next/standalone/.next/server/app/api/ideas/[id]/transition/route.js.nft.json +1 -1
  23. package/.next/standalone/.next/server/app/api/ideas/route.js.nft.json +1 -1
  24. package/.next/standalone/.next/server/app/api/implementations/route.js.nft.json +1 -1
  25. package/.next/standalone/.next/server/app/api/kpis/refresh/route.js +1 -1
  26. package/.next/standalone/.next/server/app/api/kpis/refresh/route.js.nft.json +1 -1
  27. package/.next/standalone/.next/server/app/api/social/[id]/publish/route.js.nft.json +1 -1
  28. package/.next/standalone/.next/server/app/api/social/[id]/route.js.nft.json +1 -1
  29. package/.next/standalone/.next/server/app/api/social/route.js.nft.json +1 -1
  30. package/.next/standalone/.next/server/app/goals/[id]/page_client-reference-manifest.js +1 -1
  31. package/.next/standalone/.next/server/app/goals/page.js.nft.json +1 -1
  32. package/.next/standalone/.next/server/app/goals/page_client-reference-manifest.js +1 -1
  33. package/.next/standalone/.next/server/app/hypotheses/[id]/page_client-reference-manifest.js +1 -1
  34. package/.next/standalone/.next/server/app/hypotheses/page.js +1 -1
  35. package/.next/standalone/.next/server/app/hypotheses/page.js.nft.json +1 -1
  36. package/.next/standalone/.next/server/app/hypotheses/page_client-reference-manifest.js +1 -1
  37. package/.next/standalone/.next/server/app/ideas/[id]/page.js.nft.json +1 -1
  38. package/.next/standalone/.next/server/app/ideas/[id]/page_client-reference-manifest.js +1 -1
  39. package/.next/standalone/.next/server/app/page.js +1 -1
  40. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  41. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  42. package/.next/standalone/.next/server/app/roadmap/[id]/page_client-reference-manifest.js +1 -1
  43. package/.next/standalone/.next/server/app/roadmap/page.js.nft.json +1 -1
  44. package/.next/standalone/.next/server/app/roadmap/page_client-reference-manifest.js +1 -1
  45. package/.next/standalone/.next/server/app/sessions/page.js.nft.json +1 -1
  46. package/.next/standalone/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  47. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  48. package/.next/standalone/.next/server/app/settings.html +1 -1
  49. package/.next/standalone/.next/server/app/settings.rsc +1 -1
  50. package/.next/standalone/.next/server/app/social/page_client-reference-manifest.js +1 -1
  51. package/.next/standalone/.next/server/app/social.html +1 -1
  52. package/.next/standalone/.next/server/app/social.rsc +1 -1
  53. package/.next/standalone/.next/server/app-paths-manifest.json +13 -13
  54. package/.next/standalone/.next/server/chunks/3794.js +64 -4
  55. package/.next/standalone/.next/server/pages/404.html +1 -1
  56. package/.next/standalone/.next/server/pages/500.html +1 -1
  57. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  58. package/.next/standalone/data/business-context.json +45 -6
  59. package/.next/standalone/data/goals.json +50 -10
  60. package/.next/standalone/data/ideas.json +1278 -597
  61. package/.next/standalone/data/implementations.json +101 -0
  62. package/.next/standalone/data/posthog.json +68 -0
  63. package/.next/standalone/data/sessions.json +5 -4
  64. package/.next/standalone/data/social.json +2 -2
  65. package/.next/standalone/package.json +1 -1
  66. package/.next/standalone/scripts/skills/social-media.ts +172 -2
  67. package/dist/scripts/heartbeat.js +286 -26
  68. package/package.json +1 -1
  69. /package/.next/static/{zIIaTqrawBK1MmHg37JOr → pCt9lOHHLoEA8SuY832zV}/_buildManifest.js +0 -0
  70. /package/.next/static/{zIIaTqrawBK1MmHg37JOr → pCt9lOHHLoEA8SuY832zV}/_ssgManifest.js +0 -0
@@ -1369,6 +1369,107 @@
1369
1369
  "[2026-02-21T03:14:02.477Z] Create PR only mode — skipping implementation",
1370
1370
  "[2026-02-21T03:14:02.490Z] No commits to push, skipping PR creation"
1371
1371
  ]
1372
+ },
1373
+ {
1374
+ "id": "impl-mly92zre",
1375
+ "idea_id": "idea-073e5d92",
1376
+ "status": "completed",
1377
+ "repo_name": "vibebusiness",
1378
+ "branch_name": "ai/idea-073e5d92-fix-critical-shell-injection-in-implemen",
1379
+ "workspace_path": "/Users/luismey/Code/vibebusiness/workspaces/vibebusiness-worktrees/ai/idea-073e5d92-impl-g0",
1380
+ "logs": [
1381
+ "[2026-02-22T21:19:05.353Z] Implementation started",
1382
+ "[2026-02-22T21:19:05.357Z] Using pre-configured worktree: /Users/luismey/Code/vibebusiness/workspaces/vibebusiness-worktrees/ai/idea-073e5d92-impl-g0",
1383
+ "[2026-02-22T21:19:05.361Z] Running Claude Code to implement changes (timeout: 600s (model: sonnet))...",
1384
+ "[2026-02-22T21:19:05.372Z] Using pre-configured worktree: /Users/luismey/Code/vibebusiness/workspaces/vibebusiness-worktrees/ai/idea-073e5d92-impl-g1",
1385
+ "[2026-02-22T21:19:05.377Z] Running Claude Code to implement changes (timeout: 600s (model: sonnet))...",
1386
+ "[2026-02-22T21:19:05.386Z] Using pre-configured worktree: /Users/luismey/Code/vibebusiness/workspaces/vibebusiness-worktrees/ai/idea-073e5d92-impl-g2",
1387
+ "[2026-02-22T21:19:05.396Z] Using pre-configured worktree: /Users/luismey/Code/vibebusiness/workspaces/vibebusiness-worktrees/ai/idea-073e5d92-impl-g3",
1388
+ "[2026-02-22T21:19:05.403Z] Running Claude Code to implement changes (timeout: 600s (model: sonnet))...",
1389
+ "[2026-02-22T21:19:05.423Z] Using pre-configured worktree: /Users/luismey/Code/vibebusiness/workspaces/vibebusiness-worktrees/ai/idea-073e5d92-impl-g4",
1390
+ "[2026-02-22T21:19:05.455Z] Running Claude Code to implement changes (timeout: 600s (model: sonnet))...",
1391
+ "[2026-02-22T21:19:05.466Z] Using pre-configured worktree: /Users/luismey/Code/vibebusiness/workspaces/vibebusiness-worktrees/ai/idea-073e5d92-impl-g5",
1392
+ "[2026-02-22T21:19:05.477Z] Running Claude Code to implement changes (timeout: 600s (model: sonnet))...",
1393
+ "[2026-02-22T21:19:35.372Z] ...Claude Code working (30s elapsed, 0 chars output, 30s since last output)",
1394
+ "[2026-02-22T21:19:35.380Z] ...Claude Code working (30s elapsed, 0 chars output, 30s since last output)",
1395
+ "[2026-02-22T21:19:35.401Z] ...Claude Code working (30s elapsed, 0 chars output, 30s since last output)",
1396
+ "[2026-02-22T21:19:35.412Z] ...Claude Code working (30s elapsed, 0 chars output, 30s since last output)",
1397
+ "[2026-02-22T21:19:35.466Z] ...Claude Code working (30s elapsed, 0 chars output, 30s since last output)",
1398
+ "[2026-02-22T21:19:35.481Z] ...Claude Code working (30s elapsed, 0 chars output, 30s since last output)",
1399
+ "[2026-02-22T21:19:43.621Z] Claude Code completed successfully in 38s (1000 chars)",
1400
+ "[2026-02-22T21:19:43.657Z] Changes detected, staging and committing...",
1401
+ "[2026-02-22T21:19:43.739Z] Skipping PR creation (--skip-pr)",
1402
+ "[2026-02-22T21:20:04.844Z] Claude Code completed successfully in 59s (1005 chars)",
1403
+ "[2026-02-22T21:20:04.899Z] Changes detected, staging and committing...",
1404
+ "[2026-02-22T21:20:04.975Z] Skipping PR creation (--skip-pr)",
1405
+ "[2026-02-22T21:20:05.021Z] Claude Code completed successfully in 60s (1202 chars)",
1406
+ "[2026-02-22T21:20:05.065Z] Changes detected, staging and committing...",
1407
+ "[2026-02-22T21:20:05.127Z] Skipping PR creation (--skip-pr)",
1408
+ "[2026-02-22T21:20:05.412Z] ...Claude Code working (60s elapsed, 0 chars output, 60s since last output)",
1409
+ "[2026-02-22T21:20:05.467Z] ...Claude Code working (60s elapsed, 0 chars output, 60s since last output)",
1410
+ "[2026-02-22T21:20:05.480Z] ...Claude Code working (60s elapsed, 0 chars output, 60s since last output)",
1411
+ "[2026-02-22T21:20:35.414Z] ...Claude Code working (90s elapsed, 0 chars output, 90s since last output)",
1412
+ "[2026-02-22T21:20:35.468Z] ...Claude Code working (90s elapsed, 0 chars output, 90s since last output)",
1413
+ "[2026-02-22T21:20:35.483Z] ...Claude Code working (90s elapsed, 0 chars output, 90s since last output)",
1414
+ "[2026-02-22T21:20:42.632Z] Claude Code completed successfully in 97s (1206 chars)",
1415
+ "[2026-02-22T21:20:42.685Z] Changes detected, staging and committing...",
1416
+ "[2026-02-22T21:20:42.735Z] Skipping PR creation (--skip-pr)",
1417
+ "[2026-02-22T21:21:05.414Z] ...Claude Code working (120s elapsed, 0 chars output, 120s since last output)",
1418
+ "[2026-02-22T21:21:05.481Z] ...Claude Code working (120s elapsed, 0 chars output, 120s since last output)",
1419
+ "[2026-02-22T21:21:35.414Z] ...Claude Code working (150s elapsed, 0 chars output, 150s since last output)",
1420
+ "[2026-02-22T21:21:35.483Z] ...Claude Code working (150s elapsed, 0 chars output, 150s since last output)",
1421
+ "[2026-02-22T21:22:05.416Z] ...Claude Code working (180s elapsed, 0 chars output, 180s since last output)",
1422
+ "[2026-02-22T21:22:05.483Z] ...Claude Code working (180s elapsed, 0 chars output, 180s since last output)",
1423
+ "[2026-02-22T21:22:35.417Z] ...Claude Code working (210s elapsed, 0 chars output, 210s since last output)",
1424
+ "[2026-02-22T21:22:35.484Z] ...Claude Code working (210s elapsed, 0 chars output, 210s since last output)",
1425
+ "[2026-02-22T21:23:05.416Z] ...Claude Code working (240s elapsed, 0 chars output, 240s since last output)",
1426
+ "[2026-02-22T21:23:05.483Z] ...Claude Code working (240s elapsed, 0 chars output, 240s since last output)",
1427
+ "[2026-02-22T21:23:17.057Z] Claude Code completed successfully in 252s (2194 chars)",
1428
+ "[2026-02-22T21:23:17.098Z] Changes detected, staging and committing...",
1429
+ "[2026-02-22T21:23:17.156Z] Skipping PR creation (--skip-pr)",
1430
+ "[2026-02-22T21:23:35.417Z] ...Claude Code working (270s elapsed, 0 chars output, 270s since last output)",
1431
+ "[2026-02-22T21:24:04.053Z] Claude Code completed successfully in 299s (2310 chars)",
1432
+ "[2026-02-22T21:24:04.121Z] Changes detected, staging and committing...",
1433
+ "[2026-02-22T21:24:04.199Z] Skipping PR creation (--skip-pr)"
1434
+ ]
1435
+ },
1436
+ {
1437
+ "id": "impl-mly949xm",
1438
+ "idea_id": "idea-073e5d92",
1439
+ "status": "completed",
1440
+ "repo_name": "vibebusiness",
1441
+ "branch_name": "ai/idea-073e5d92-fix-critical-shell-injection-in-implemen",
1442
+ "workspace_path": "/Users/luismey/Code/vibebusiness/workspaces/vibebusiness-worktrees/ai/idea-073e5d92-impl-g0",
1443
+ "logs": [
1444
+ "[2026-02-22T21:20:05.193Z] Implementation started",
1445
+ "[2026-02-22T21:20:05.195Z] Using pre-configured worktree: /Users/luismey/Code/vibebusiness/workspaces/vibebusiness-worktrees/ai/idea-073e5d92-impl-g0",
1446
+ "[2026-02-22T21:20:05.196Z] Running Claude Code to implement changes (timeout: 600s (model: sonnet))...",
1447
+ "[2026-02-22T21:20:35.199Z] ...Claude Code working (30s elapsed, 0 chars output, 30s since last output)",
1448
+ "[2026-02-22T21:21:05.200Z] ...Claude Code working (60s elapsed, 0 chars output, 60s since last output)",
1449
+ "[2026-02-22T21:21:30.701Z] Claude Code completed successfully in 86s (1241 chars)",
1450
+ "[2026-02-22T21:21:30.721Z] Changes detected, staging and committing...",
1451
+ "[2026-02-22T21:21:30.799Z] Skipping PR creation (--skip-pr)"
1452
+ ]
1453
+ },
1454
+ {
1455
+ "id": "impl-mly9641i",
1456
+ "idea_id": "idea-073e5d92",
1457
+ "status": "completed",
1458
+ "repo_name": "vibebusiness",
1459
+ "branch_name": "ai/idea-073e5d92-fix-critical-shell-injection-in-implemen",
1460
+ "workspace_path": "/Users/luismey/Code/vibebusiness/workspaces/vibebusiness-worktrees/ai/idea-073e5d92-impl-g0",
1461
+ "logs": [
1462
+ "[2026-02-22T21:21:30.870Z] Implementation started",
1463
+ "[2026-02-22T21:21:30.871Z] Using pre-configured worktree: /Users/luismey/Code/vibebusiness/workspaces/vibebusiness-worktrees/ai/idea-073e5d92-impl-g0",
1464
+ "[2026-02-22T21:21:30.872Z] Running Claude Code to implement changes (timeout: 600s (model: sonnet))...",
1465
+ "[2026-02-22T21:22:00.877Z] ...Claude Code working (30s elapsed, 0 chars output, 30s since last output)",
1466
+ "[2026-02-22T21:22:30.876Z] ...Claude Code working (60s elapsed, 0 chars output, 60s since last output)",
1467
+ "[2026-02-22T21:23:00.877Z] ...Claude Code working (90s elapsed, 0 chars output, 90s since last output)",
1468
+ "[2026-02-22T21:23:30.878Z] ...Claude Code working (120s elapsed, 0 chars output, 120s since last output)",
1469
+ "[2026-02-22T21:23:36.366Z] Claude Code completed successfully in 125s (1664 chars)",
1470
+ "[2026-02-22T21:23:36.408Z] Changes detected, staging and committing...",
1471
+ "[2026-02-22T21:23:36.507Z] Skipping PR creation (--skip-pr)"
1472
+ ]
1372
1473
  }
1373
1474
  ]
1374
1475
  }
@@ -0,0 +1,68 @@
1
+ {
2
+ "last_updated": "2026-02-22T21:45:00.000Z",
3
+ "integration_status": {
4
+ "sdk_installed": true,
5
+ "api_key_valid": true,
6
+ "provider_generated": true,
7
+ "pageview_tracker": true,
8
+ "event_helper": true,
9
+ "kpi_adapter": true
10
+ },
11
+ "framework": {
12
+ "framework": "nextjs",
13
+ "typescript": true,
14
+ "appRouter": true,
15
+ "srcDir": true
16
+ },
17
+ "generated_files": [
18
+ "website/src/components/PostHogProvider.tsx",
19
+ "website/src/components/PostHogPageview.tsx",
20
+ "website/src/lib/posthog.ts"
21
+ ],
22
+ "detected_events": [
23
+ {
24
+ "event": "waitlist_signup_success",
25
+ "location": "website/src/app/page.tsx",
26
+ "type": "website"
27
+ },
28
+ {
29
+ "event": "waitlist_signup_error",
30
+ "location": "website/src/app/page.tsx",
31
+ "type": "website"
32
+ },
33
+ {
34
+ "event": "checkout_completed",
35
+ "location": "website/src/components/TrackCheckoutComplete.tsx",
36
+ "type": "website"
37
+ },
38
+ {
39
+ "event": "command_run",
40
+ "location": "bin/ai-analyst.ts",
41
+ "type": "cli",
42
+ "properties": ["command", "dryRun", "session", "task", "type", "deep", "minimal"]
43
+ },
44
+ {
45
+ "event": "heartbeat_task",
46
+ "location": "scripts/heartbeat.ts",
47
+ "type": "backend",
48
+ "properties": ["taskType", "success", "errorType"]
49
+ }
50
+ ],
51
+ "kpi_mappings": {
52
+ "kpi-beta-signups": "waitlist_signup_success",
53
+ "kpi-paying-users": "checkout_completed",
54
+ "kpi-cli-init-count": "command_run[command=init]",
55
+ "kpi-cli-vibe-count": "command_run[command=vibe]",
56
+ "kpi-cli-scan-count": "command_run[command=scan]"
57
+ },
58
+ "unmapped_events": [
59
+ {
60
+ "event": "waitlist_signup_error",
61
+ "reason": "No matching KPI — useful for error monitoring in PostHog dashboards"
62
+ },
63
+ {
64
+ "event": "heartbeat_task",
65
+ "reason": "Operational metric — useful in PostHog dashboards but no business KPI match"
66
+ }
67
+ ]
68
+ }
@@ -341,18 +341,19 @@
341
341
  {
342
342
  "id": "session-4a6293fb",
343
343
  "created_at": "2026-02-19T20:11:45.297Z",
344
- "completed_at": null,
344
+ "completed_at": "2026-02-22T00:00:00.000Z",
345
345
  "type": "quick",
346
- "status": "running",
346
+ "status": "failed",
347
347
  "repos_analyzed": [
348
348
  "vibebusiness"
349
349
  ],
350
350
  "ideas_generated": [],
351
- "error_message": null,
351
+ "error_message": "Session timed out — marked failed by dedup-triage-and-approve-inbox meta-task on 2026-02-22. Was stuck in 'running' with 0 ideas generated since 2026-02-19T20:11:45.",
352
352
  "logs": [
353
353
  "[2026-02-19T20:11:45.297Z] Session started",
354
354
  "[2026-02-19T20:11:45.301Z] Generated quick analysis prompt",
355
- "[2026-02-19T20:11:45.301Z] Running Claude Code analysis..."
355
+ "[2026-02-19T20:11:45.301Z] Running Claude Code analysis...",
356
+ "[2026-02-22T00:00:00.000Z] Session marked failed by meta-task cleanup (zombie session — no ideas generated, stuck in running state)"
356
357
  ]
357
358
  }
358
359
  ]
@@ -1,11 +1,11 @@
1
1
  {
2
- "last_updated": "2026-02-20T22:50:48.200Z",
2
+ "last_updated": "2026-02-22T20:39:11.478Z",
3
3
  "platform": "x",
4
4
  "username": "@luisgmey",
5
5
  "credentials_valid": true,
6
6
  "drafts": [],
7
7
  "metrics": {
8
- "followers_count": 334,
8
+ "followers_count": 335,
9
9
  "post_streak_days": 0,
10
10
  "total_posts": 0,
11
11
  "last_post_date": null
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibebusiness",
3
- "version": "1.2.49",
3
+ "version": "1.2.51",
4
4
  "description": "AI-powered autonomous product manager. Research. Build. Ship. Grow.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "private": false,
@@ -8,6 +8,7 @@
8
8
  *
9
9
  * Task prefixes handled:
10
10
  * social-setup-x → Validate X credentials, save username
11
+ * social-plan-week → Generate a 7-day content calendar with AI-optimized drafts
11
12
  * social-draft-ship → Draft a "just shipped" tweet from latest shipped idea
12
13
  * social-draft-ship-visual → Draft ship tweet with card/video media
13
14
  * social-draft-update → Draft a product update from positioning data
@@ -24,7 +25,7 @@
24
25
  import * as fs from 'fs';
25
26
  import * as path from 'path';
26
27
  import { v4 as uuidv4 } from 'uuid';
27
- import { SOCIAL_FILE, GOALS_FILE, DATA_DIR } from '../lib/paths';
28
+ import { SOCIAL_FILE, GOALS_FILE, IDEAS_FILE, POSITIONING_FILE, DATA_DIR } from '../lib/paths';
28
29
  import {
29
30
  loadCredentials,
30
31
  createXClient,
@@ -45,10 +46,11 @@ import {
45
46
  import {
46
47
  generateViralTweet,
47
48
  generateViralThread,
49
+ generateWeekPlan,
48
50
  scoreDraft,
49
51
  type TweetTopic,
50
52
  } from '../lib/social/ai-content-generator';
51
- import type { SocialConfig, SocialDraft, SocialDraftSource, TweetEngagement, BusinessGoal } from '../../src/lib/types';
53
+ import type { SocialConfig, SocialDraft, SocialDraftSource, TweetEngagement, BusinessGoal, PositioningData } from '../../src/lib/types';
52
54
 
53
55
  // ─── State ───────────────────────────────────────────────────────────────────
54
56
 
@@ -159,6 +161,7 @@ function createDraft(
159
161
 
160
162
  const SOCIAL_PREFIXES = [
161
163
  'social-setup-x',
164
+ 'social-plan-week',
162
165
  'social-draft-ship-visual',
163
166
  'social-draft-ship',
164
167
  'social-draft-update',
@@ -191,6 +194,9 @@ export async function executeSocialTask(
191
194
  if (taskId === 'social-setup-x') {
192
195
  return await executeSetupX();
193
196
  }
197
+ if (taskId === 'social-plan-week') {
198
+ return await executePlanWeek();
199
+ }
194
200
  if (taskId === 'social-draft-ship-visual') {
195
201
  return executeDraftShipVisual();
196
202
  }
@@ -251,6 +257,7 @@ export function readSocialFreshness(): {
251
257
  best_tweet_id: string | null;
252
258
  best_engagement_rate: number | null;
253
259
  thread_count: number;
260
+ scheduled_draft_count: number;
254
261
  } {
255
262
  const state = loadState();
256
263
  const pendingDrafts = state.drafts.filter((d) => d.status === 'draft').length;
@@ -278,6 +285,12 @@ export function readSocialFreshness(): {
278
285
 
279
286
  const threadCount = state.drafts.filter((d) => d.is_thread && d.status === 'published').length;
280
287
 
288
+ // Count drafts with future scheduled dates
289
+ const today = new Date().toISOString().split('T')[0];
290
+ const scheduledDraftCount = state.drafts.filter(
291
+ (d) => d.status === 'draft' && d.scheduled_date && d.scheduled_date >= today
292
+ ).length;
293
+
281
294
  return {
282
295
  configured: state.credentials_valid,
283
296
  credentials_valid: state.credentials_valid,
@@ -290,6 +303,7 @@ export function readSocialFreshness(): {
290
303
  best_tweet_id: bestTweetId,
291
304
  best_engagement_rate: bestEngagementRate,
292
305
  thread_count: threadCount,
306
+ scheduled_draft_count: scheduledDraftCount,
293
307
  };
294
308
  }
295
309
 
@@ -616,6 +630,161 @@ async function executeDraftThread(
616
630
  };
617
631
  }
618
632
 
633
+ // ─── Weekly Content Plan ─────────────────────────────────────────────────
634
+
635
+ async function executePlanWeek(): Promise<{ success: boolean; output: string }> {
636
+ const state = loadState();
637
+
638
+ // Gather context for the AI planner
639
+ const pastPerformance = collectEngagementHistory(state);
640
+
641
+ // Read positioning data
642
+ let positioning: PositioningData | null = null;
643
+ try {
644
+ if (fs.existsSync(POSITIONING_FILE)) {
645
+ positioning = JSON.parse(fs.readFileSync(POSITIONING_FILE, 'utf-8'));
646
+ }
647
+ } catch { /* ignore */ }
648
+
649
+ // Read goals for behind-schedule context
650
+ let goalsContext = '';
651
+ try {
652
+ if (fs.existsSync(GOALS_FILE)) {
653
+ const { goals } = JSON.parse(fs.readFileSync(GOALS_FILE, 'utf-8')) as { goals: BusinessGoal[] };
654
+ const relevant = goals
655
+ .filter((g) => g.status === 'on_track' || g.status === 'at_risk' || g.status === 'behind')
656
+ .map((g) => {
657
+ const progress = g.current_value != null && g.target_value
658
+ ? `${Math.round((g.current_value / g.target_value) * 100)}%`
659
+ : 'unknown';
660
+ return `- ${g.title} (${g.status}, ${progress} complete, deadline: ${g.deadline})`;
661
+ });
662
+ goalsContext = relevant.length > 0 ? relevant.join('\n') : 'No active goals.';
663
+ }
664
+ } catch { /* ignore */ }
665
+
666
+ // Read recently shipped ideas (last 14 days)
667
+ let recentShips = '';
668
+ try {
669
+ if (fs.existsSync(IDEAS_FILE)) {
670
+ const { ideas } = JSON.parse(fs.readFileSync(IDEAS_FILE, 'utf-8')) as {
671
+ ideas: Array<{ id: string; title: string; stage: string; updated_at: string }>;
672
+ };
673
+ const twoWeeksAgo = new Date(Date.now() - 14 * 24 * 60 * 60 * 1000).toISOString();
674
+ const shipped = ideas
675
+ .filter((i) => i.stage === 'shipped' && i.updated_at > twoWeeksAgo)
676
+ .map((i) => `- ${i.title} (shipped ${i.updated_at.split('T')[0]})`);
677
+ recentShips = shipped.length > 0 ? shipped.join('\n') : 'No recent ships.';
678
+ }
679
+ } catch { /* ignore */ }
680
+
681
+ // KPI highlights
682
+ let kpiHighlights = '';
683
+ try {
684
+ if (fs.existsSync(GOALS_FILE)) {
685
+ const { goals } = JSON.parse(fs.readFileSync(GOALS_FILE, 'utf-8')) as { goals: BusinessGoal[] };
686
+ const highlights: string[] = [];
687
+ for (const goal of goals) {
688
+ for (const kpi of goal.kpis) {
689
+ if (kpi.current_value != null && kpi.target_value != null) {
690
+ const pct = Math.round((kpi.current_value / kpi.target_value) * 100);
691
+ highlights.push(`- ${kpi.name}: ${kpi.current_value}/${kpi.target_value} ${kpi.unit} (${pct}%)`);
692
+ }
693
+ }
694
+ }
695
+ kpiHighlights = highlights.length > 0 ? highlights.join('\n') : 'No KPI data.';
696
+ }
697
+ } catch { /* ignore */ }
698
+
699
+ const plan = await generateWeekPlan({
700
+ positioning,
701
+ pastPerformance,
702
+ goalsContext,
703
+ recentShips,
704
+ kpiHighlights,
705
+ });
706
+
707
+ if (plan.days.length === 0) {
708
+ return { success: false, output: 'AI failed to generate a weekly content plan.' };
709
+ }
710
+
711
+ // Create drafts for each non-rest day
712
+ const createdDrafts: Array<{ day: string; date: string; type: string; id: string }> = [];
713
+
714
+ for (const day of plan.days) {
715
+ if (day.type === 'rest' || !day.content) continue;
716
+
717
+ if (day.type === 'thread' && day.thread_tweets && day.thread_tweets.length > 0) {
718
+ // Thread draft
719
+ const draft: SocialDraft = {
720
+ id: `draft-${uuidv4().slice(0, 8)}`,
721
+ text: day.thread_tweets[0],
722
+ source: 'thread',
723
+ source_ref: null,
724
+ status: 'draft',
725
+ created_at: new Date().toISOString(),
726
+ published_at: null,
727
+ tweet_id: null,
728
+ tweet_url: null,
729
+ is_thread: true,
730
+ thread_tweets: day.thread_tweets,
731
+ scheduled_date: day.date,
732
+ };
733
+ state.drafts.push(draft);
734
+ createdDrafts.push({ day: day.day, date: day.date, type: 'thread', id: draft.id });
735
+ } else {
736
+ // Single tweet draft
737
+ const source: SocialDraftSource = (['ship', 'milestone', 'update', 'digest', 'insight'].includes(day.topic as string)
738
+ ? day.topic
739
+ : 'insight') as SocialDraftSource;
740
+ const draft = createDraft(state, day.content, source, null);
741
+ draft.scheduled_date = day.date;
742
+ createdDrafts.push({ day: day.day, date: day.date, type: day.type, id: draft.id });
743
+ }
744
+ }
745
+
746
+ saveState(state);
747
+
748
+ // Format calendar output
749
+ const monday = plan.days.find((d) => d.day === 'monday')?.date ?? '';
750
+ const sunday = plan.days.find((d) => d.day === 'sunday')?.date ?? '';
751
+ const dateRange = monday && sunday
752
+ ? `${formatDateShort(monday)} - ${formatDateShort(sunday)}`
753
+ : 'This Week';
754
+
755
+ const lines: string[] = [`Weekly Content Plan (${dateRange})`, ''];
756
+
757
+ for (const day of plan.days) {
758
+ const dayLabel = day.day.charAt(0).toUpperCase() + day.day.slice(1, 3);
759
+ if (day.type === 'rest') {
760
+ lines.push(`${dayLabel} -- Rest`);
761
+ } else {
762
+ const threadInfo = day.type === 'thread' && day.thread_tweets
763
+ ? ` (${day.thread_tweets.length} tweets)`
764
+ : '';
765
+ const preview = day.content.length > 60
766
+ ? `"${day.content.slice(0, 57)}..."`
767
+ : `"${day.content}"`;
768
+ lines.push(`${dayLabel} [${day.type}] ${preview}${threadInfo}`);
769
+ lines.push(` Hook: ${day.hook_type} | ${day.rationale}`);
770
+ }
771
+ }
772
+
773
+ lines.push('');
774
+ lines.push(`${createdDrafts.length} drafts created. Review and edit at: vibebusiness start -> /social`);
775
+
776
+ return { success: true, output: lines.join('\n') };
777
+ }
778
+
779
+ /**
780
+ * Format YYYY-MM-DD to "Mon DD" short form.
781
+ */
782
+ function formatDateShort(isoDate: string): string {
783
+ const d = new Date(isoDate + 'T00:00:00');
784
+ const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
785
+ return `${months[d.getMonth()]} ${d.getDate()}`;
786
+ }
787
+
619
788
  // ─── Engagement Tracking ──────────────────────────────────────────────────
620
789
 
621
790
  async function executeTrackMetrics(): Promise<{ success: boolean; output: string }> {
@@ -777,6 +946,7 @@ async function executeCheckStatus(): Promise<{ success: boolean; output: string
777
946
  }
778
947
 
779
948
  lines.push(` Pending drafts: ${freshness.draft_count}`);
949
+ lines.push(` Scheduled drafts: ${freshness.scheduled_draft_count}`);
780
950
  lines.push(` Post streak: ${freshness.post_streak_days} day(s)`);
781
951
  lines.push(` Total posts: ${freshness.total_posts}`);
782
952
  lines.push(` Threads published: ${freshness.thread_count}`);