popilot 0.6.0 → 0.8.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.
- package/bin/cli.mjs +204 -2
- package/lib/doctor.mjs +38 -1
- package/lib/hydrate.mjs +15 -0
- package/lib/scaffold.mjs +5 -0
- package/lib/setup-wizard.mjs +35 -2
- package/package.json +1 -1
- package/scaffold/.context/project.yaml.example +19 -0
- package/scaffold/mcp-notification-server/package.json +18 -0
- package/scaffold/mcp-notification-server/src/index.ts +275 -0
- package/scaffold/mcp-notification-server/src/turso-client.ts +142 -0
- package/scaffold/mcp-notification-server/tsconfig.json +14 -0
- package/scaffold/mcp-pm/package.json +19 -0
- package/scaffold/mcp-pm/src/api-client.ts +69 -0
- package/scaffold/mcp-pm/src/index.ts +660 -0
- package/scaffold/mcp-pm/tsconfig.json +14 -0
- package/scaffold/pm-api/package.json +21 -0
- package/scaffold/pm-api/sql/001-memo-v2.sql +49 -0
- package/scaffold/pm-api/sql/002-notifications.sql +18 -0
- package/scaffold/pm-api/sql/003-content.sql +66 -0
- package/scaffold/pm-api/sql/004-agent-events.sql +21 -0
- package/scaffold/pm-api/sql/005-epic-sprint-decoupling.sql +6 -0
- package/scaffold/pm-api/sql/schema-core.sql +331 -0
- package/scaffold/pm-api/sql/schema-docs.sql +25 -0
- package/scaffold/pm-api/sql/schema-meetings.sql +17 -0
- package/scaffold/pm-api/sql/schema-rewards.sql +16 -0
- package/scaffold/pm-api/src/auth.ts +28 -0
- package/scaffold/pm-api/src/blockchain/adapter.ts +20 -0
- package/scaffold/pm-api/src/blockchain/tron.ts +62 -0
- package/scaffold/pm-api/src/db/adapter.ts +36 -0
- package/scaffold/pm-api/src/db/turso.ts +147 -0
- package/scaffold/pm-api/src/index.ts +114 -0
- package/scaffold/pm-api/src/mcp-tools/dashboard.ts +40 -0
- package/scaffold/pm-api/src/mcp-tools/epic.ts +67 -0
- package/scaffold/pm-api/src/mcp-tools/event.ts +89 -0
- package/scaffold/pm-api/src/mcp-tools/index.ts +11 -0
- package/scaffold/pm-api/src/mcp-tools/initiative.ts +51 -0
- package/scaffold/pm-api/src/mcp-tools/memo.ts +164 -0
- package/scaffold/pm-api/src/mcp-tools/notification.ts +37 -0
- package/scaffold/pm-api/src/mcp-tools/retro.ts +183 -0
- package/scaffold/pm-api/src/mcp-tools/sprint.ts +204 -0
- package/scaffold/pm-api/src/mcp-tools/standup.ts +136 -0
- package/scaffold/pm-api/src/mcp-tools/story.ts +230 -0
- package/scaffold/pm-api/src/mcp-tools/task.ts +187 -0
- package/scaffold/pm-api/src/mcp-tools/utils.ts +83 -0
- package/scaffold/pm-api/src/mcp.ts +871 -0
- package/scaffold/pm-api/src/nudge.ts +283 -0
- package/scaffold/pm-api/src/routes/auth.ts +32 -0
- package/scaffold/pm-api/src/routes/v2-activity.ts +27 -0
- package/scaffold/pm-api/src/routes/v2-admin.ts +165 -0
- package/scaffold/pm-api/src/routes/v2-dashboard.ts +189 -0
- package/scaffold/pm-api/src/routes/v2-docs.ts +34 -0
- package/scaffold/pm-api/src/routes/v2-initiatives.ts +118 -0
- package/scaffold/pm-api/src/routes/v2-kickoff.ts +265 -0
- package/scaffold/pm-api/src/routes/v2-meetings.ts +324 -0
- package/scaffold/pm-api/src/routes/v2-memos.ts +257 -0
- package/scaffold/pm-api/src/routes/v2-nav.ts +260 -0
- package/scaffold/pm-api/src/routes/v2-notifications.ts +79 -0
- package/scaffold/pm-api/src/routes/v2-page-content.ts +35 -0
- package/scaffold/pm-api/src/routes/v2-pm.ts +380 -0
- package/scaffold/pm-api/src/routes/v2-policy.ts +58 -0
- package/scaffold/pm-api/src/routes/v2-retro.ts +221 -0
- package/scaffold/pm-api/src/routes/v2-rewards.ts +132 -0
- package/scaffold/pm-api/src/routes/v2-scenarios.ts +48 -0
- package/scaffold/pm-api/src/routes/v2-search.ts +32 -0
- package/scaffold/pm-api/src/routes/v2-standup.ts +127 -0
- package/scaffold/pm-api/src/routes/v2-user.ts +38 -0
- package/scaffold/pm-api/src/types.ts +11 -0
- package/scaffold/pm-api/src/utils/activity.ts +22 -0
- package/scaffold/pm-api/src/utils/admin.ts +9 -0
- package/scaffold/pm-api/src/utils/agent-notify.ts +62 -0
- package/scaffold/pm-api/src/utils/assignee.ts +69 -0
- package/scaffold/pm-api/src/utils/db.ts +45 -0
- package/scaffold/pm-api/src/utils/initiative.ts +23 -0
- package/scaffold/pm-api/src/utils/retro-link.ts +32 -0
- package/scaffold/pm-api/src/utils/sprint-lifecycle.ts +96 -0
- package/scaffold/pm-api/tsconfig.json +15 -0
- package/scaffold/pm-api/wrangler.toml.hbs +11 -0
- package/scaffold/spec-site/package-lock.json +892 -0
- package/scaffold/spec-site/package.json +15 -1
- package/scaffold/spec-site/src/api/types.ts +6 -0
- package/scaffold/spec-site/src/components/AppHeader.vue +429 -55
- package/scaffold/spec-site/src/components/AuthGate.vue +117 -0
- package/scaffold/spec-site/src/components/BurndownChart.vue +78 -0
- package/scaffold/spec-site/src/components/DocComments.vue +137 -0
- package/scaffold/spec-site/src/components/DocEditor.vue +118 -0
- package/scaffold/spec-site/src/components/DocExportBar.vue +110 -0
- package/scaffold/spec-site/src/components/DocsSidebar.vue +309 -0
- package/scaffold/spec-site/src/components/EmptyState.vue +30 -0
- package/scaffold/spec-site/src/components/ErrorBanner.vue +38 -0
- package/scaffold/spec-site/src/components/Icon.vue +58 -0
- package/scaffold/spec-site/src/components/MemberSelect.vue +48 -0
- package/scaffold/spec-site/src/components/MemoChecklist.vue +88 -0
- package/scaffold/spec-site/src/components/MemoGraph.vue +75 -0
- package/scaffold/spec-site/src/components/MemoItem.vue +353 -0
- package/scaffold/spec-site/src/components/MemoRelations.vue +101 -0
- package/scaffold/spec-site/src/components/MemoTimeline.vue +53 -0
- package/scaffold/spec-site/src/components/MentionInput.vue +174 -0
- package/scaffold/spec-site/src/components/NotificationDropdown.vue +116 -0
- package/scaffold/spec-site/src/components/PriorityBadge.vue +23 -0
- package/scaffold/spec-site/src/components/SearchModal.vue +102 -0
- package/scaffold/spec-site/src/components/SlashCommand.ts +123 -0
- package/scaffold/spec-site/src/components/StateDisplay.vue +54 -0
- package/scaffold/spec-site/src/components/TreeNode.vue +82 -0
- package/scaffold/spec-site/src/components/UserAvatar.vue +24 -0
- package/scaffold/spec-site/src/components/VelocityChart.vue +77 -0
- package/scaffold/spec-site/src/composables/navTypes.ts +3 -0
- package/scaffold/spec-site/src/composables/pmTypes.ts +15 -2
- package/scaffold/spec-site/src/composables/useBottomSheet.ts +103 -0
- package/scaffold/spec-site/src/composables/useDashboard.ts +221 -0
- package/scaffold/spec-site/src/composables/useMediaQuery.ts +28 -0
- package/scaffold/spec-site/src/composables/useMemo.ts +39 -0
- package/scaffold/spec-site/src/composables/useNotification.ts +200 -0
- package/scaffold/spec-site/src/composables/usePmStore.ts +48 -1
- package/scaffold/spec-site/src/composables/useRetro.ts +6 -0
- package/scaffold/spec-site/src/composables/useStandup.ts +201 -0
- package/scaffold/spec-site/src/composables/useTheme.ts +37 -0
- package/scaffold/spec-site/src/composables/useTurso.ts +17 -0
- package/scaffold/spec-site/src/composables/useUser.ts +19 -1
- package/scaffold/spec-site/src/composables/useViewport.ts +26 -0
- package/scaffold/spec-site/src/features.ts +108 -0
- package/scaffold/spec-site/src/mockup/ComponentPalette.vue +61 -0
- package/scaffold/spec-site/src/mockup/MockupCanvas.vue +459 -0
- package/scaffold/spec-site/src/mockup/PropertyPanel.vue +217 -0
- package/scaffold/spec-site/src/mockup/componentCatalog.ts +68 -0
- package/scaffold/spec-site/src/mockup/useScenarios.ts +67 -0
- package/scaffold/spec-site/src/pages/AdminPage.vue +299 -0
- package/scaffold/spec-site/src/pages/DashboardPage.vue +650 -0
- package/scaffold/spec-site/src/pages/DocsEditor.vue +119 -0
- package/scaffold/spec-site/src/pages/DocsHub.vue +157 -0
- package/scaffold/spec-site/src/pages/DocsPage.vue +444 -0
- package/scaffold/spec-site/src/pages/InboxPage.vue +156 -0
- package/scaffold/spec-site/src/pages/MeetingsPage.vue +294 -0
- package/scaffold/spec-site/src/pages/MemosPage.vue +857 -0
- package/scaffold/spec-site/src/pages/MockupEditorPage.vue +611 -0
- package/scaffold/spec-site/src/pages/MockupListPage.vue +121 -0
- package/scaffold/spec-site/src/pages/MockupViewerPage.vue +199 -0
- package/scaffold/spec-site/src/pages/MyPage.vue +343 -0
- package/scaffold/spec-site/src/pages/NotificationSettingsPage.vue +59 -0
- package/scaffold/spec-site/src/pages/RewardsPage.vue +266 -0
- package/scaffold/spec-site/src/pages/SprintAdmin.vue +521 -0
- package/scaffold/spec-site/src/pages/SprintTimeline.vue +159 -0
- package/scaffold/spec-site/src/pages/board/BoardAdmin.vue +422 -0
- package/scaffold/spec-site/src/pages/board/BoardEpicSection.vue +54 -0
- package/scaffold/spec-site/src/pages/board/BoardPage.vue +884 -0
- package/scaffold/spec-site/src/pages/board/BoardStoryCard.vue +67 -0
- package/scaffold/spec-site/src/pages/board/BoardTaskItem.vue +52 -0
- package/scaffold/spec-site/src/pages/board/KanbanBoard.vue +93 -0
- package/scaffold/spec-site/src/pages/board/MyTasksPage.vue +202 -0
- package/scaffold/spec-site/src/pages/board/SprintClose.vue +167 -0
- package/scaffold/spec-site/src/pages/board/SprintColumn.vue +49 -0
- package/scaffold/spec-site/src/pages/board/SprintKickoff.vue +389 -0
- package/scaffold/spec-site/src/pages/board/StatusBadge.vue +52 -0
- package/scaffold/spec-site/src/pages/board/StoryDetailPanel.vue +495 -0
- package/scaffold/spec-site/src/pages/board/TaskCard.vue +42 -0
- package/scaffold/spec-site/src/pages/retro/RetroCard.vue +36 -2
- package/scaffold/spec-site/src/pages/retro/RetroHeader.vue +82 -66
- package/scaffold/spec-site/src/pages/retro/RetroPage.vue +47 -18
- package/scaffold/spec-site/src/pages/standup/StandupEntryCard.vue +551 -0
- package/scaffold/spec-site/src/pages/standup/StandupForm.vue +68 -0
- package/scaffold/spec-site/src/pages/standup/StandupList.vue +71 -0
- package/scaffold/spec-site/src/pages/standup/StandupPage.vue +225 -0
- package/scaffold/spec-site/src/router.ts +141 -0
- package/scaffold/spec-site/src/styles/buttons.css +124 -0
- package/scaffold/spec-site/src/utils/parseMentions.ts +56 -0
- package/scaffold/spec-site/src/utils/timezone.ts +18 -0
package/bin/cli.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { resolve, basename } from 'node:path';
|
|
4
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
4
5
|
import { execSync } from 'node:child_process';
|
|
5
6
|
import { copyScaffold, appendToFile, detectExisting } from '../lib/scaffold.mjs';
|
|
6
7
|
import { runSetupWizard } from '../lib/setup-wizard.mjs';
|
|
@@ -15,6 +16,8 @@ const USAGE = `
|
|
|
15
16
|
init [dir] Scaffold + interactive setup + hydration (default)
|
|
16
17
|
hydrate [dir] Sync latest scaffold templates + re-hydrate from project.yaml
|
|
17
18
|
doctor [dir] Check installation health
|
|
19
|
+
deploy [dir] Deploy pm-api to Cloudflare Workers (Tier 2)
|
|
20
|
+
migrate [dir] Run SQL schema migrations on pm-api database (Tier 2)
|
|
18
21
|
help Show this help
|
|
19
22
|
|
|
20
23
|
Options:
|
|
@@ -28,10 +31,12 @@ const USAGE = `
|
|
|
28
31
|
npx popilot hydrate
|
|
29
32
|
npx popilot hydrate --force
|
|
30
33
|
npx popilot doctor
|
|
34
|
+
npx popilot deploy
|
|
35
|
+
npx popilot migrate
|
|
31
36
|
npx popilot my-project # same as: popilot init my-project
|
|
32
37
|
`;
|
|
33
38
|
|
|
34
|
-
const SUBCOMMANDS = new Set(['init', 'hydrate', 'doctor', 'help']);
|
|
39
|
+
const SUBCOMMANDS = new Set(['init', 'hydrate', 'doctor', 'deploy', 'migrate', 'help']);
|
|
35
40
|
|
|
36
41
|
async function main() {
|
|
37
42
|
const args = process.argv.slice(2);
|
|
@@ -71,6 +76,12 @@ async function main() {
|
|
|
71
76
|
case 'doctor':
|
|
72
77
|
await cmdDoctor(targetDir, { skipSpecSite, platform });
|
|
73
78
|
break;
|
|
79
|
+
case 'deploy':
|
|
80
|
+
await cmdDeploy(targetDir);
|
|
81
|
+
break;
|
|
82
|
+
case 'migrate':
|
|
83
|
+
await cmdMigrate(targetDir);
|
|
84
|
+
break;
|
|
74
85
|
}
|
|
75
86
|
}
|
|
76
87
|
|
|
@@ -133,7 +144,34 @@ async function cmdInit(targetDir, { skipSpecSite, force, platform }) {
|
|
|
133
144
|
console.log(` ${f} ✅ (domain)`);
|
|
134
145
|
}
|
|
135
146
|
|
|
136
|
-
//
|
|
147
|
+
// 4a. Install pm-api dependencies (Tier 2)
|
|
148
|
+
const pmApiDir = resolve(targetDir, 'pm-api');
|
|
149
|
+
try {
|
|
150
|
+
const { access: fsAccess } = await import('node:fs/promises');
|
|
151
|
+
await fsAccess(resolve(pmApiDir, 'package.json'));
|
|
152
|
+
console.log();
|
|
153
|
+
console.log(' 📦 Installing pm-api dependencies...');
|
|
154
|
+
try {
|
|
155
|
+
execSync('npm install', { cwd: pmApiDir, stdio: 'pipe' });
|
|
156
|
+
console.log(' ✅ Done');
|
|
157
|
+
} catch {
|
|
158
|
+
console.log(' ⚠️ npm install failed. Run manually: cd pm-api && npm install');
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Also install mcp-pm
|
|
162
|
+
const mcpPmDir = resolve(targetDir, 'mcp-pm');
|
|
163
|
+
console.log(' 📦 Installing mcp-pm dependencies...');
|
|
164
|
+
try {
|
|
165
|
+
execSync('npm install', { cwd: mcpPmDir, stdio: 'pipe' });
|
|
166
|
+
console.log(' ✅ Done');
|
|
167
|
+
} catch {
|
|
168
|
+
console.log(' ⚠️ npm install failed. Run manually: cd mcp-pm && npm install');
|
|
169
|
+
}
|
|
170
|
+
} catch {
|
|
171
|
+
// pm-api not present (Tier 0/1) — skip
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// 4b. Install spec-site dependencies
|
|
137
175
|
if (!skipSpecSite) {
|
|
138
176
|
const specSiteDir = resolve(targetDir, 'spec-site');
|
|
139
177
|
console.log();
|
|
@@ -241,6 +279,170 @@ async function cmdDoctor(targetDir, { skipSpecSite, platform }) {
|
|
|
241
279
|
process.exit(failed.length > 0 ? 1 : 0);
|
|
242
280
|
}
|
|
243
281
|
|
|
282
|
+
// ── deploy ───────────────────────────────────────────────
|
|
283
|
+
|
|
284
|
+
async function cmdDeploy(targetDir) {
|
|
285
|
+
console.log();
|
|
286
|
+
console.log(' 🚀 Popilot — Deploy pm-api');
|
|
287
|
+
console.log(' ══════════════════════════════════════');
|
|
288
|
+
console.log();
|
|
289
|
+
|
|
290
|
+
const pmApiDir = resolve(targetDir, 'pm-api');
|
|
291
|
+
|
|
292
|
+
if (!existsSync(pmApiDir)) {
|
|
293
|
+
console.log(' ❌ pm-api directory not found.');
|
|
294
|
+
console.log(` Expected at: ${pmApiDir}`);
|
|
295
|
+
console.log(' Deploy is only available for Tier 2 (interactive spec-site with backend).');
|
|
296
|
+
console.log();
|
|
297
|
+
process.exit(1);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const wranglerToml = resolve(pmApiDir, 'wrangler.toml');
|
|
301
|
+
if (!existsSync(wranglerToml)) {
|
|
302
|
+
console.log(' ❌ wrangler.toml not found in pm-api.');
|
|
303
|
+
console.log(' Found wrangler.toml.hbs — run `popilot hydrate` first to generate wrangler.toml.');
|
|
304
|
+
console.log();
|
|
305
|
+
process.exit(1);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
console.log(` 📂 Deploying from: ${pmApiDir}`);
|
|
309
|
+
console.log();
|
|
310
|
+
|
|
311
|
+
try {
|
|
312
|
+
execSync('npx wrangler deploy', { cwd: pmApiDir, stdio: 'inherit' });
|
|
313
|
+
console.log();
|
|
314
|
+
console.log(' ✅ pm-api deployed successfully.');
|
|
315
|
+
console.log();
|
|
316
|
+
} catch {
|
|
317
|
+
console.log();
|
|
318
|
+
console.log(' ❌ Deploy failed. Check the wrangler output above for details.');
|
|
319
|
+
console.log();
|
|
320
|
+
process.exit(1);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// ── migrate ──────────────────────────────────────────────
|
|
325
|
+
|
|
326
|
+
async function cmdMigrate(targetDir) {
|
|
327
|
+
console.log();
|
|
328
|
+
console.log(' 🗄️ Popilot — Run SQL Migrations');
|
|
329
|
+
console.log(' ══════════════════════════════════════');
|
|
330
|
+
console.log();
|
|
331
|
+
|
|
332
|
+
const pmApiDir = resolve(targetDir, 'pm-api');
|
|
333
|
+
|
|
334
|
+
if (!existsSync(pmApiDir)) {
|
|
335
|
+
console.log(' ❌ pm-api directory not found.');
|
|
336
|
+
console.log(` Expected at: ${pmApiDir}`);
|
|
337
|
+
console.log(' Migrate is only available for Tier 2 (interactive spec-site with backend).');
|
|
338
|
+
console.log();
|
|
339
|
+
process.exit(1);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
const sqlDir = resolve(pmApiDir, 'sql');
|
|
343
|
+
if (!existsSync(sqlDir)) {
|
|
344
|
+
console.log(' ❌ pm-api/sql/ directory not found.');
|
|
345
|
+
console.log(' No migration files available.');
|
|
346
|
+
console.log();
|
|
347
|
+
process.exit(1);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// Read D1 database name from wrangler.toml
|
|
351
|
+
const wranglerToml = resolve(pmApiDir, 'wrangler.toml');
|
|
352
|
+
if (!existsSync(wranglerToml)) {
|
|
353
|
+
console.log(' ❌ wrangler.toml not found in pm-api.');
|
|
354
|
+
console.log(' Run `popilot hydrate` first to generate wrangler.toml.');
|
|
355
|
+
console.log();
|
|
356
|
+
process.exit(1);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
const wranglerContent = readFileSync(wranglerToml, 'utf-8');
|
|
360
|
+
const dbNameMatch = wranglerContent.match(/database_name\s*=\s*"([^"]+)"/);
|
|
361
|
+
const dbName = dbNameMatch ? dbNameMatch[1] : null;
|
|
362
|
+
|
|
363
|
+
if (!dbName) {
|
|
364
|
+
console.log(' ❌ Could not find D1 database_name in wrangler.toml.');
|
|
365
|
+
console.log(' Ensure [[d1_databases]] is configured with a database_name.');
|
|
366
|
+
console.log();
|
|
367
|
+
process.exit(1);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
console.log(` 📂 SQL directory: ${sqlDir}`);
|
|
371
|
+
console.log(` 🗃️ D1 database: ${dbName}`);
|
|
372
|
+
console.log();
|
|
373
|
+
|
|
374
|
+
// Read project.yaml to determine enabled features
|
|
375
|
+
const projectYaml = resolve(targetDir, '.context', 'project.yaml');
|
|
376
|
+
let features = { rewards: false, meetings: true, docs: true };
|
|
377
|
+
|
|
378
|
+
if (existsSync(projectYaml)) {
|
|
379
|
+
try {
|
|
380
|
+
const yamlContent = readFileSync(projectYaml, 'utf-8');
|
|
381
|
+
// Parse feature flags from YAML (simple regex — avoids adding a YAML dep)
|
|
382
|
+
const rewardsMatch = yamlContent.match(/features:[\s\S]*?rewards:\s*(true|false)/);
|
|
383
|
+
const meetingsMatch = yamlContent.match(/features:[\s\S]*?meetings:\s*(true|false)/);
|
|
384
|
+
const docsMatch = yamlContent.match(/features:[\s\S]*?docs:\s*(true|false)/);
|
|
385
|
+
|
|
386
|
+
if (rewardsMatch) features.rewards = rewardsMatch[1] === 'true';
|
|
387
|
+
if (meetingsMatch) features.meetings = meetingsMatch[1] === 'true';
|
|
388
|
+
if (docsMatch) features.docs = docsMatch[1] === 'true';
|
|
389
|
+
} catch {
|
|
390
|
+
console.log(' ⚠️ Could not read project.yaml — using default feature flags.');
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// Build list of schemas to apply
|
|
395
|
+
const schemas = [{ file: 'schema-core.sql', label: 'core (always)' }];
|
|
396
|
+
|
|
397
|
+
if (features.rewards) {
|
|
398
|
+
schemas.push({ file: 'schema-rewards.sql', label: 'rewards' });
|
|
399
|
+
}
|
|
400
|
+
if (features.meetings) {
|
|
401
|
+
schemas.push({ file: 'schema-meetings.sql', label: 'meetings' });
|
|
402
|
+
}
|
|
403
|
+
if (features.docs) {
|
|
404
|
+
schemas.push({ file: 'schema-docs.sql', label: 'docs' });
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
console.log(' 📋 Schemas to apply:');
|
|
408
|
+
for (const s of schemas) {
|
|
409
|
+
console.log(` - ${s.file} (${s.label})`);
|
|
410
|
+
}
|
|
411
|
+
console.log();
|
|
412
|
+
|
|
413
|
+
// Execute each schema
|
|
414
|
+
let applied = 0;
|
|
415
|
+
let failed = 0;
|
|
416
|
+
|
|
417
|
+
for (const s of schemas) {
|
|
418
|
+
const sqlFile = resolve(sqlDir, s.file);
|
|
419
|
+
if (!existsSync(sqlFile)) {
|
|
420
|
+
console.log(` ⚠️ ${s.file} not found — skipped`);
|
|
421
|
+
continue;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
try {
|
|
425
|
+
execSync(
|
|
426
|
+
`npx wrangler d1 execute ${dbName} --file=sql/${s.file} --remote`,
|
|
427
|
+
{ cwd: pmApiDir, stdio: 'pipe' }
|
|
428
|
+
);
|
|
429
|
+
console.log(` ✅ ${s.file} applied`);
|
|
430
|
+
applied++;
|
|
431
|
+
} catch (err) {
|
|
432
|
+
console.log(` ❌ ${s.file} failed: ${err.message}`);
|
|
433
|
+
failed++;
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
console.log();
|
|
438
|
+
if (failed === 0) {
|
|
439
|
+
console.log(` ✅ Migration complete — ${applied} schema(s) applied.`);
|
|
440
|
+
} else {
|
|
441
|
+
console.log(` ⚠️ Migration finished with errors — ${applied} applied, ${failed} failed.`);
|
|
442
|
+
}
|
|
443
|
+
console.log();
|
|
444
|
+
}
|
|
445
|
+
|
|
244
446
|
// ── Run ─────────────────────────────────────────────────
|
|
245
447
|
|
|
246
448
|
main().catch(err => {
|
package/lib/doctor.mjs
CHANGED
|
@@ -97,7 +97,44 @@ export async function runDoctor(targetDir, opts = {}) {
|
|
|
97
97
|
}, passed, failed, warnings);
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
// 7.
|
|
100
|
+
// 7. Tier 2 checks (pm-api + mcp-pm)
|
|
101
|
+
const pmApiDir = join(targetDir, 'pm-api');
|
|
102
|
+
let hasPmApi = false;
|
|
103
|
+
try { await access(pmApiDir); hasPmApi = true; } catch {}
|
|
104
|
+
|
|
105
|
+
if (hasPmApi) {
|
|
106
|
+
await check('pm-api/package.json exists', async () => {
|
|
107
|
+
await access(join(pmApiDir, 'package.json'));
|
|
108
|
+
}, passed, failed);
|
|
109
|
+
|
|
110
|
+
await check('pm-api/wrangler.toml exists (hydrated)', async () => {
|
|
111
|
+
await access(join(pmApiDir, 'wrangler.toml'));
|
|
112
|
+
try {
|
|
113
|
+
await access(join(pmApiDir, 'wrangler.toml.hbs'));
|
|
114
|
+
throw new Error('wrangler.toml.hbs still exists — hydration incomplete');
|
|
115
|
+
} catch (e) {
|
|
116
|
+
if (e.message.includes('hydration')) throw e;
|
|
117
|
+
}
|
|
118
|
+
}, passed, failed);
|
|
119
|
+
|
|
120
|
+
await check('pm-api/sql/schema-core.sql exists', async () => {
|
|
121
|
+
await access(join(pmApiDir, 'sql', 'schema-core.sql'));
|
|
122
|
+
}, passed, failed);
|
|
123
|
+
|
|
124
|
+
await check('mcp-pm/package.json exists', async () => {
|
|
125
|
+
await access(join(targetDir, 'mcp-pm', 'package.json'));
|
|
126
|
+
}, passed, failed);
|
|
127
|
+
|
|
128
|
+
await check('pm-api/node_modules exists', async () => {
|
|
129
|
+
await access(join(pmApiDir, 'node_modules'));
|
|
130
|
+
}, passed, failed, warnings);
|
|
131
|
+
|
|
132
|
+
await check('mcp-pm/node_modules exists', async () => {
|
|
133
|
+
await access(join(targetDir, 'mcp-pm', 'node_modules'));
|
|
134
|
+
}, passed, failed, warnings);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// 8. .gitignore entries
|
|
101
138
|
await check('.gitignore includes user-context.yaml', async () => {
|
|
102
139
|
const content = await readFile(join(targetDir, '.gitignore'), 'utf-8');
|
|
103
140
|
if (!content.includes('user-context.yaml')) {
|
package/lib/hydrate.mjs
CHANGED
|
@@ -145,6 +145,21 @@ export async function hydrate(targetDir, opts = {}) {
|
|
|
145
145
|
if (result) hydrated.push(relative(targetDir, result));
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
+
// pm-api wrangler.toml.hbs hydration (Tier 2)
|
|
149
|
+
const pmApiWranglerPath = join(targetDir, 'pm-api', 'wrangler.toml.hbs');
|
|
150
|
+
try {
|
|
151
|
+
const wranglerResult = await hydrateFile(pmApiWranglerPath, {
|
|
152
|
+
ctx,
|
|
153
|
+
registry,
|
|
154
|
+
enabledProviders,
|
|
155
|
+
targetType: 'system',
|
|
156
|
+
targetName: 'wrangler.toml',
|
|
157
|
+
});
|
|
158
|
+
if (wranglerResult) hydrated.push(relative(targetDir, wranglerResult));
|
|
159
|
+
} catch {
|
|
160
|
+
// pm-api not present (Tier 0/1) — skip
|
|
161
|
+
}
|
|
162
|
+
|
|
148
163
|
// Domain command generation
|
|
149
164
|
const domains = projectYaml.operations?.domains || [];
|
|
150
165
|
const domainResults = [];
|
package/lib/scaffold.mjs
CHANGED
|
@@ -57,6 +57,11 @@ async function walk(srcDir, destDir, targetDir, options, copied, overwritten, sk
|
|
|
57
57
|
continue;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
// Skip pm-api and mcp-pm if not Tier 2
|
|
61
|
+
if (options.skipPmApi && (relPath.startsWith('pm-api') || relPath.startsWith('mcp-pm'))) {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
|
|
60
65
|
// Skip manifest.yaml (adapter metadata, not a project file)
|
|
61
66
|
if (entry.name === 'manifest.yaml') {
|
|
62
67
|
continue;
|
package/lib/setup-wizard.mjs
CHANGED
|
@@ -130,6 +130,38 @@ export async function runSetupWizard(targetDir, opts = {}) {
|
|
|
130
130
|
specSiteConfig.mode = specSiteTier;
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
+
// ── Phase 6: Backend Setup (Tier 2) ──────────────
|
|
134
|
+
let pmApiConfig = { enabled: false, url: '', features: { rewards: false, meetings: true, docs: true, initiatives: true }, blockchain: { enabled: false, provider: '', token_name: '', contract_address: '', token_decimals: 8 } };
|
|
135
|
+
|
|
136
|
+
if (specSiteTier === 'interactive') {
|
|
137
|
+
console.log();
|
|
138
|
+
console.log(' ──────────────────────────────────────');
|
|
139
|
+
console.log(' 🖥️ Backend Setup (Tier 2)');
|
|
140
|
+
console.log(' ──────────────────────────────────────');
|
|
141
|
+
console.log();
|
|
142
|
+
|
|
143
|
+
pmApiConfig.enabled = true;
|
|
144
|
+
pmApiConfig.url = await ask(rl, 'PM API URL (leave empty to configure later)');
|
|
145
|
+
|
|
146
|
+
console.log();
|
|
147
|
+
console.log(' Feature modules:');
|
|
148
|
+
pmApiConfig.features.rewards = await confirm(rl, 'Enable rewards/penalties module?', false);
|
|
149
|
+
pmApiConfig.features.meetings = await confirm(rl, 'Enable meetings module?', true);
|
|
150
|
+
pmApiConfig.features.docs = await confirm(rl, 'Enable docs module?', true);
|
|
151
|
+
pmApiConfig.features.initiatives = await confirm(rl, 'Enable initiatives module?', true);
|
|
152
|
+
|
|
153
|
+
console.log();
|
|
154
|
+
const enableBlockchain = await confirm(rl, 'Enable blockchain integration?', false);
|
|
155
|
+
if (enableBlockchain) {
|
|
156
|
+
pmApiConfig.blockchain.enabled = true;
|
|
157
|
+
pmApiConfig.blockchain.provider = await select(rl, 'Blockchain provider:', [
|
|
158
|
+
{ label: 'TRON', value: 'tron' },
|
|
159
|
+
], 0);
|
|
160
|
+
pmApiConfig.blockchain.token_name = await ask(rl, 'Token name');
|
|
161
|
+
pmApiConfig.blockchain.contract_address = await ask(rl, 'Contract address');
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
133
165
|
console.log();
|
|
134
166
|
|
|
135
167
|
// ── Phase 5: Integrations ────────────────────────
|
|
@@ -141,7 +173,7 @@ export async function runSetupWizard(targetDir, opts = {}) {
|
|
|
141
173
|
// project.yaml
|
|
142
174
|
const projectYaml = buildProjectYaml({
|
|
143
175
|
projectName, tagline, projectType,
|
|
144
|
-
domains, devScope, integrations, specSiteConfig,
|
|
176
|
+
domains, devScope, integrations, specSiteConfig, pmApiConfig,
|
|
145
177
|
platform: opts.platform || null,
|
|
146
178
|
industryPreset,
|
|
147
179
|
});
|
|
@@ -356,7 +388,7 @@ export const ALL_INTEGRATION_PROVIDERS = [
|
|
|
356
388
|
'sqlite_lambda',
|
|
357
389
|
];
|
|
358
390
|
|
|
359
|
-
function buildProjectYaml({ projectName, tagline, projectType, domains, devScope, integrations, specSiteConfig, platform, industryPreset }) {
|
|
391
|
+
function buildProjectYaml({ projectName, tagline, projectType, domains, devScope, integrations, specSiteConfig, pmApiConfig, platform, industryPreset }) {
|
|
360
392
|
// Build the full integrations block with all known providers
|
|
361
393
|
const integrationsBlock = {};
|
|
362
394
|
|
|
@@ -418,6 +450,7 @@ function buildProjectYaml({ projectName, tagline, projectType, domains, devScope
|
|
|
418
450
|
deploy_url: '',
|
|
419
451
|
backend: specSiteConfig.backend,
|
|
420
452
|
},
|
|
453
|
+
pm_api: pmApiConfig || { enabled: false },
|
|
421
454
|
},
|
|
422
455
|
_meta: {
|
|
423
456
|
created_at: new Date().toISOString(),
|
package/package.json
CHANGED
|
@@ -103,8 +103,27 @@ operations:
|
|
|
103
103
|
service_repo: "" # {{dev_scope.service_repo}}
|
|
104
104
|
|
|
105
105
|
spec_site:
|
|
106
|
+
enabled: false
|
|
107
|
+
mode: "static" # static | interactive
|
|
106
108
|
title: "" # {{spec_site.title}}
|
|
107
109
|
deploy_url: "" # {{spec_site.deploy_url}}
|
|
110
|
+
backend: ""
|
|
111
|
+
|
|
112
|
+
# PM API Backend (Tier 2 — Full interactive mode)
|
|
113
|
+
pm_api:
|
|
114
|
+
enabled: false
|
|
115
|
+
url: "" # PM API URL (e.g. https://pm-api.your-domain.workers.dev)
|
|
116
|
+
features:
|
|
117
|
+
rewards: false
|
|
118
|
+
meetings: true
|
|
119
|
+
docs: true
|
|
120
|
+
initiatives: true
|
|
121
|
+
blockchain:
|
|
122
|
+
enabled: false
|
|
123
|
+
provider: "" # tron | (future: eth, solana)
|
|
124
|
+
token_name: ""
|
|
125
|
+
contract_address: ""
|
|
126
|
+
token_decimals: 8
|
|
108
127
|
|
|
109
128
|
# ============================================================
|
|
110
129
|
# Metadata
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mcp-notification-server",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"dev": "tsc --watch"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@modelcontextprotocol/sdk": "^1.12.1"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"typescript": "^5.7.0",
|
|
16
|
+
"@types/node": "^22.0.0"
|
|
17
|
+
}
|
|
18
|
+
}
|