popilot 0.6.0 → 0.7.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 (112) hide show
  1. package/bin/cli.mjs +204 -2
  2. package/lib/doctor.mjs +38 -1
  3. package/lib/hydrate.mjs +15 -0
  4. package/lib/scaffold.mjs +5 -0
  5. package/lib/setup-wizard.mjs +35 -2
  6. package/package.json +1 -1
  7. package/scaffold/.context/project.yaml.example +19 -0
  8. package/scaffold/mcp-pm/package.json +19 -0
  9. package/scaffold/mcp-pm/src/api-client.ts +69 -0
  10. package/scaffold/mcp-pm/src/index.ts +660 -0
  11. package/scaffold/mcp-pm/tsconfig.json +14 -0
  12. package/scaffold/pm-api/package.json +21 -0
  13. package/scaffold/pm-api/sql/schema-core.sql +331 -0
  14. package/scaffold/pm-api/sql/schema-docs.sql +25 -0
  15. package/scaffold/pm-api/sql/schema-meetings.sql +17 -0
  16. package/scaffold/pm-api/sql/schema-rewards.sql +16 -0
  17. package/scaffold/pm-api/src/auth.ts +28 -0
  18. package/scaffold/pm-api/src/blockchain/adapter.ts +20 -0
  19. package/scaffold/pm-api/src/blockchain/tron.ts +62 -0
  20. package/scaffold/pm-api/src/db/adapter.ts +36 -0
  21. package/scaffold/pm-api/src/db/turso.ts +147 -0
  22. package/scaffold/pm-api/src/index.ts +114 -0
  23. package/scaffold/pm-api/src/mcp-tools/dashboard.ts +40 -0
  24. package/scaffold/pm-api/src/mcp-tools/epic.ts +67 -0
  25. package/scaffold/pm-api/src/mcp-tools/event.ts +89 -0
  26. package/scaffold/pm-api/src/mcp-tools/index.ts +11 -0
  27. package/scaffold/pm-api/src/mcp-tools/initiative.ts +51 -0
  28. package/scaffold/pm-api/src/mcp-tools/memo.ts +164 -0
  29. package/scaffold/pm-api/src/mcp-tools/notification.ts +37 -0
  30. package/scaffold/pm-api/src/mcp-tools/retro.ts +183 -0
  31. package/scaffold/pm-api/src/mcp-tools/sprint.ts +204 -0
  32. package/scaffold/pm-api/src/mcp-tools/standup.ts +136 -0
  33. package/scaffold/pm-api/src/mcp-tools/story.ts +230 -0
  34. package/scaffold/pm-api/src/mcp-tools/task.ts +187 -0
  35. package/scaffold/pm-api/src/mcp-tools/utils.ts +83 -0
  36. package/scaffold/pm-api/src/mcp.ts +871 -0
  37. package/scaffold/pm-api/src/nudge.ts +283 -0
  38. package/scaffold/pm-api/src/routes/auth.ts +32 -0
  39. package/scaffold/pm-api/src/routes/v2-activity.ts +27 -0
  40. package/scaffold/pm-api/src/routes/v2-admin.ts +165 -0
  41. package/scaffold/pm-api/src/routes/v2-dashboard.ts +189 -0
  42. package/scaffold/pm-api/src/routes/v2-docs.ts +34 -0
  43. package/scaffold/pm-api/src/routes/v2-initiatives.ts +118 -0
  44. package/scaffold/pm-api/src/routes/v2-kickoff.ts +265 -0
  45. package/scaffold/pm-api/src/routes/v2-meetings.ts +324 -0
  46. package/scaffold/pm-api/src/routes/v2-memos.ts +257 -0
  47. package/scaffold/pm-api/src/routes/v2-nav.ts +260 -0
  48. package/scaffold/pm-api/src/routes/v2-notifications.ts +79 -0
  49. package/scaffold/pm-api/src/routes/v2-page-content.ts +35 -0
  50. package/scaffold/pm-api/src/routes/v2-pm.ts +380 -0
  51. package/scaffold/pm-api/src/routes/v2-policy.ts +58 -0
  52. package/scaffold/pm-api/src/routes/v2-retro.ts +221 -0
  53. package/scaffold/pm-api/src/routes/v2-rewards.ts +132 -0
  54. package/scaffold/pm-api/src/routes/v2-scenarios.ts +48 -0
  55. package/scaffold/pm-api/src/routes/v2-search.ts +32 -0
  56. package/scaffold/pm-api/src/routes/v2-standup.ts +127 -0
  57. package/scaffold/pm-api/src/routes/v2-user.ts +38 -0
  58. package/scaffold/pm-api/src/types.ts +11 -0
  59. package/scaffold/pm-api/src/utils/activity.ts +22 -0
  60. package/scaffold/pm-api/src/utils/admin.ts +9 -0
  61. package/scaffold/pm-api/src/utils/agent-notify.ts +62 -0
  62. package/scaffold/pm-api/src/utils/assignee.ts +69 -0
  63. package/scaffold/pm-api/src/utils/db.ts +45 -0
  64. package/scaffold/pm-api/src/utils/initiative.ts +23 -0
  65. package/scaffold/pm-api/src/utils/sprint-lifecycle.ts +96 -0
  66. package/scaffold/pm-api/tsconfig.json +15 -0
  67. package/scaffold/pm-api/wrangler.toml.hbs +11 -0
  68. package/scaffold/spec-site/package-lock.json +40 -0
  69. package/scaffold/spec-site/package.json +4 -1
  70. package/scaffold/spec-site/src/api/types.ts +6 -0
  71. package/scaffold/spec-site/src/components/AppHeader.vue +429 -55
  72. package/scaffold/spec-site/src/components/MemberSelect.vue +48 -0
  73. package/scaffold/spec-site/src/components/NotificationDropdown.vue +116 -0
  74. package/scaffold/spec-site/src/components/SearchModal.vue +102 -0
  75. package/scaffold/spec-site/src/components/VelocityChart.vue +77 -0
  76. package/scaffold/spec-site/src/composables/pmTypes.ts +15 -2
  77. package/scaffold/spec-site/src/composables/useDashboard.ts +221 -0
  78. package/scaffold/spec-site/src/composables/useMediaQuery.ts +28 -0
  79. package/scaffold/spec-site/src/composables/useNotification.ts +200 -0
  80. package/scaffold/spec-site/src/composables/usePmStore.ts +48 -1
  81. package/scaffold/spec-site/src/composables/useRetro.ts +6 -0
  82. package/scaffold/spec-site/src/composables/useStandup.ts +201 -0
  83. package/scaffold/spec-site/src/composables/useTheme.ts +37 -0
  84. package/scaffold/spec-site/src/composables/useUser.ts +19 -1
  85. package/scaffold/spec-site/src/features.ts +108 -0
  86. package/scaffold/spec-site/src/pages/AdminPage.vue +299 -0
  87. package/scaffold/spec-site/src/pages/DashboardPage.vue +650 -0
  88. package/scaffold/spec-site/src/pages/DocsHub.vue +157 -0
  89. package/scaffold/spec-site/src/pages/InboxPage.vue +156 -0
  90. package/scaffold/spec-site/src/pages/MeetingsPage.vue +294 -0
  91. package/scaffold/spec-site/src/pages/MyPage.vue +343 -0
  92. package/scaffold/spec-site/src/pages/RewardsPage.vue +266 -0
  93. package/scaffold/spec-site/src/pages/board/BoardAdmin.vue +422 -0
  94. package/scaffold/spec-site/src/pages/board/BoardEpicSection.vue +54 -0
  95. package/scaffold/spec-site/src/pages/board/BoardPage.vue +884 -0
  96. package/scaffold/spec-site/src/pages/board/BoardStoryCard.vue +67 -0
  97. package/scaffold/spec-site/src/pages/board/BoardTaskItem.vue +52 -0
  98. package/scaffold/spec-site/src/pages/board/MyTasksPage.vue +202 -0
  99. package/scaffold/spec-site/src/pages/board/SprintClose.vue +167 -0
  100. package/scaffold/spec-site/src/pages/board/SprintColumn.vue +49 -0
  101. package/scaffold/spec-site/src/pages/board/SprintKickoff.vue +389 -0
  102. package/scaffold/spec-site/src/pages/board/StatusBadge.vue +52 -0
  103. package/scaffold/spec-site/src/pages/board/StoryDetailPanel.vue +495 -0
  104. package/scaffold/spec-site/src/pages/board/TaskCard.vue +42 -0
  105. package/scaffold/spec-site/src/pages/retro/RetroCard.vue +36 -2
  106. package/scaffold/spec-site/src/pages/retro/RetroHeader.vue +82 -66
  107. package/scaffold/spec-site/src/pages/retro/RetroPage.vue +47 -18
  108. package/scaffold/spec-site/src/pages/standup/StandupEntryCard.vue +551 -0
  109. package/scaffold/spec-site/src/pages/standup/StandupForm.vue +68 -0
  110. package/scaffold/spec-site/src/pages/standup/StandupList.vue +71 -0
  111. package/scaffold/spec-site/src/pages/standup/StandupPage.vue +225 -0
  112. package/scaffold/spec-site/src/router.ts +141 -0
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Sprint Lifecycle — pure domain logic
3
+ * No DB dependency. Fully testable.
4
+ */
5
+
6
+ export interface StoryRow {
7
+ id: number
8
+ title: string
9
+ sprint: string | null
10
+ status: string
11
+ story_points: number | null
12
+ assignee: string | null
13
+ }
14
+
15
+ export interface SprintStatus {
16
+ id: string
17
+ status: 'planning' | 'active' | 'closed'
18
+ }
19
+
20
+ export interface VelocityRecord {
21
+ sprintId: string
22
+ assignee: string
23
+ doneSP: number
24
+ totalSP: number
25
+ }
26
+
27
+ export interface CloseSummary {
28
+ sprintId: string
29
+ completedCount: number
30
+ incompleteCount: number
31
+ totalStories: number
32
+ doneSP: number
33
+ totalSP: number
34
+ completionRate: number
35
+ }
36
+
37
+ /** Check whether the sprint can be closed */
38
+ export function canClose(sprint: SprintStatus): { ok: boolean; error?: string } {
39
+ if (sprint.status !== 'active') {
40
+ return { ok: false, error: `Can only close sprints in active state (current: ${sprint.status})` }
41
+ }
42
+ return { ok: true }
43
+ }
44
+
45
+ /** Filter incomplete stories */
46
+ export function getIncompleteStories(stories: StoryRow[]): StoryRow[] {
47
+ return stories.filter(s => s.status !== 'done')
48
+ }
49
+
50
+ /** Filter completed stories */
51
+ export function getCompletedStories(stories: StoryRow[]): StoryRow[] {
52
+ return stories.filter(s => s.status === 'done')
53
+ }
54
+
55
+ /** Move incomplete stories to backlog (pure function — returns new array) */
56
+ export function moveToBacklog(stories: StoryRow[]): StoryRow[] {
57
+ return stories.map(s => ({ ...s, sprint: null }))
58
+ }
59
+
60
+ /** Aggregate completed SP per team member */
61
+ export function aggregateVelocity(sprintId: string, stories: StoryRow[]): VelocityRecord[] {
62
+ const map = new Map<string, { done: number; total: number }>()
63
+
64
+ for (const s of stories) {
65
+ const assignee = s.assignee ?? 'Unassigned'
66
+ if (!map.has(assignee)) map.set(assignee, { done: 0, total: 0 })
67
+ const entry = map.get(assignee)!
68
+ entry.total += s.story_points ?? 0
69
+ if (s.status === 'done') entry.done += s.story_points ?? 0
70
+ }
71
+
72
+ return [...map.entries()].map(([assignee, { done, total }]) => ({
73
+ sprintId,
74
+ assignee,
75
+ doneSP: done,
76
+ totalSP: total,
77
+ }))
78
+ }
79
+
80
+ /** Generate close summary */
81
+ export function generateCloseSummary(sprintId: string, stories: StoryRow[]): CloseSummary {
82
+ const completed = getCompletedStories(stories)
83
+ const incomplete = getIncompleteStories(stories)
84
+ const totalDoneSP = completed.reduce((sum, s) => sum + (s.story_points ?? 0), 0)
85
+ const totalSP = stories.reduce((sum, s) => sum + (s.story_points ?? 0), 0)
86
+
87
+ return {
88
+ sprintId,
89
+ completedCount: completed.length,
90
+ incompleteCount: incomplete.length,
91
+ totalStories: stories.length,
92
+ doneSP: totalDoneSP,
93
+ totalSP,
94
+ completionRate: totalSP > 0 ? Math.round((totalDoneSP / totalSP) * 100) : 0,
95
+ }
96
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ES2022",
5
+ "moduleResolution": "bundler",
6
+ "lib": ["ES2022"],
7
+ "types": ["@cloudflare/workers-types"],
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "noEmit": true
12
+ },
13
+ "include": ["src"],
14
+ "exclude": ["src/**/*.test.ts"]
15
+ }
@@ -0,0 +1,11 @@
1
+ name = "{{project.name}}-pm-api"
2
+ main = "src/index.ts"
3
+ compatibility_date = "2025-03-10"
4
+
5
+ # Database credentials: npx wrangler secret put TURSO_URL && npx wrangler secret put TURSO_AUTH_TOKEN
6
+
7
+ # Proactive Nudge schedule (UTC)
8
+ # 01:00 UTC: Morning check — review_overdue, sprint_deadline, task_stagnant, blocker_open
9
+ # 08:00 UTC: Afternoon check — all rules + standup_missing, sprint_daily_report
10
+ [triggers]
11
+ crons = ["0 1 * * *", "0 8 * * *"]
@@ -8,6 +8,9 @@
8
8
  "name": "spec-site",
9
9
  "version": "1.0.0",
10
10
  "dependencies": {
11
+ "dompurify": "^3.2.0",
12
+ "lucide-vue-next": "^0.470.0",
13
+ "marked": "^15.0.0",
11
14
  "vue": "^3.5.27",
12
15
  "vue-router": "^4.5.0"
13
16
  },
@@ -869,6 +872,13 @@
869
872
  "dev": true,
870
873
  "license": "MIT"
871
874
  },
875
+ "node_modules/@types/trusted-types": {
876
+ "version": "2.0.7",
877
+ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
878
+ "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
879
+ "license": "MIT",
880
+ "optional": true
881
+ },
872
882
  "node_modules/@vitejs/plugin-vue": {
873
883
  "version": "5.2.4",
874
884
  "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz",
@@ -1091,6 +1101,15 @@
1091
1101
  "dev": true,
1092
1102
  "license": "MIT"
1093
1103
  },
1104
+ "node_modules/dompurify": {
1105
+ "version": "3.3.3",
1106
+ "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.3.tgz",
1107
+ "integrity": "sha512-Oj6pzI2+RqBfFG+qOaOLbFXLQ90ARpcGG6UePL82bJLtdsa6CYJD7nmiU8MW9nQNOtCHV3lZ/Bzq1X0QYbBZCA==",
1108
+ "license": "(MPL-2.0 OR Apache-2.0)",
1109
+ "optionalDependencies": {
1110
+ "@types/trusted-types": "^2.0.7"
1111
+ }
1112
+ },
1094
1113
  "node_modules/entities": {
1095
1114
  "version": "7.0.1",
1096
1115
  "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz",
@@ -1194,6 +1213,15 @@
1194
1213
  "he": "bin/he"
1195
1214
  }
1196
1215
  },
1216
+ "node_modules/lucide-vue-next": {
1217
+ "version": "0.470.0",
1218
+ "resolved": "https://registry.npmjs.org/lucide-vue-next/-/lucide-vue-next-0.470.0.tgz",
1219
+ "integrity": "sha512-hqcVn93ghGJIEFo1MiQuy0PrZbp5nHZZcSxumZ+0qIRYy+f7e0ngVTsFOiQYL2Gl1YZ+PQR0WJkIDH5MCp3gGw==",
1220
+ "license": "ISC",
1221
+ "peerDependencies": {
1222
+ "vue": ">=3.0.1"
1223
+ }
1224
+ },
1197
1225
  "node_modules/magic-string": {
1198
1226
  "version": "0.30.21",
1199
1227
  "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
@@ -1203,6 +1231,18 @@
1203
1231
  "@jridgewell/sourcemap-codec": "^1.5.5"
1204
1232
  }
1205
1233
  },
1234
+ "node_modules/marked": {
1235
+ "version": "15.0.12",
1236
+ "resolved": "https://registry.npmjs.org/marked/-/marked-15.0.12.tgz",
1237
+ "integrity": "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA==",
1238
+ "license": "MIT",
1239
+ "bin": {
1240
+ "marked": "bin/marked.js"
1241
+ },
1242
+ "engines": {
1243
+ "node": ">= 18"
1244
+ }
1245
+ },
1206
1246
  "node_modules/minimatch": {
1207
1247
  "version": "9.0.9",
1208
1248
  "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz",
@@ -9,7 +9,10 @@
9
9
  },
10
10
  "dependencies": {
11
11
  "vue": "^3.5.27",
12
- "vue-router": "^4.5.0"
12
+ "vue-router": "^4.5.0",
13
+ "dompurify": "^3.2.0",
14
+ "marked": "^15.0.0",
15
+ "lucide-vue-next": "^0.470.0"
13
16
  },
14
17
  "devDependencies": {
15
18
  "@vitejs/plugin-vue": "^5.2.3",
@@ -122,6 +122,10 @@ export interface PmStoryRow {
122
122
  priority: string
123
123
  area: string
124
124
  story_points: number | null
125
+ start_date: string | null
126
+ due_date: string | null
127
+ figma_url: string | null
128
+ related_prs: string | null
125
129
  sort_order: number
126
130
  created_at: string
127
131
  updated_at: string
@@ -134,6 +138,8 @@ export interface PmTaskRow {
134
138
  assignee: string | null
135
139
  status: string
136
140
  description: string | null
141
+ story_points: number | null
142
+ due_date: string | null
137
143
  sort_order: number
138
144
  created_at: string
139
145
  updated_at: string