#!/usr/bin/env node /** * Bookworm Smart Assistant — 生产活动全量模拟器 * 路径: scripts/production-sim.js * 版本: v1.0 (2026-02-20) * * 用途: * 模拟一个完整工作日的 67 个对话事件,验证 activity-logger 日志链路完整性。 * 以「SaaS 支付网关重构」为主线,覆盖全部 50 Skills + 10 Agents + 7 MCPs。 * * 用法: * node scripts/production-sim.js # 执行模拟并写入活动日志 * node scripts/production-sim.js --dry-run # 仅打印场景,不写入日志 * node scripts/production-sim.js --verify # 执行后校验日志完整性 * * 日志输出: debug/activity-YYYY-MM-DD.jsonl * * 覆盖清单: * Skills (50): ai-ml-expert → zero-defect-guardian * Agents (10): orchestrator, self-auditor, self-healer, full-stack-builder, * research-analyst, quality-gate, canvas-ui-designer, * code-reviewer, pre-deploy-checker, test-writer * MCPs (7): deep-research, context7, sequential-thinking, playwright, * chrome-devtools, selenium, browserbase */ const { execSync } = require('child_process'); const fs = require('fs'); const path = require('path'); // ─── 配置 ─────────────────────────────────────────────── // 动态检测配置根目录 const detectClaudeRoot = () => require('./paths.config.js').PATHS.root; const CLAUDE_ROOT = detectClaudeRoot(); const HOOK = path.join(CLAUDE_ROOT, 'hooks', 'activity-logger.js'); const DEBUG_DIR = path.join(CLAUDE_ROOT, 'debug'); // ─── 参数解析 ─────────────────────────────────────────── const args = process.argv.slice(2); const DRY_RUN = args.includes('--dry-run'); const VERIFY = args.includes('--verify'); // ─── 计数器 ───────────────────────────────────────────── const stats = { skill: 0, agent: 0, mcp: 0, total: 0, failed: 0 }; // 记录注入前的日志行数,用于 --verify let logLinesBefore = 0; if (VERIFY || !DRY_RUN) { const dateStr = new Date().toISOString().slice(0, 10); const logFile = path.join(DEBUG_DIR, `activity-${dateStr}.jsonl`); try { logLinesBefore = fs.readFileSync(logFile, 'utf8').trim().split('\n').length; } catch { logLinesBefore = 0; } } // ─── 触发函数 ─────────────────────────────────────────── function trigger(payload, scenario) { const evLabel = ( payload.tool_name === 'Skill' ? 'SKILL' : payload.tool_name === 'TaskCreate' ? 'AGENT' : payload.tool_name.startsWith('mcp__') ? 'MCP ' : payload.tool_name === 'Bash' ? 'BASH ' : 'WRITE' ); const detail = payload.tool_input.skill || payload.tool_input.subject || payload.tool_name.replace('mcp__', '').split('__').join('/') || payload.tool_input.command?.slice(0, 60) || payload.tool_input.file_path || ''; if (DRY_RUN) { console.log(` [${evLabel}] ${detail}`); stats[payload.tool_name === 'Skill' ? 'skill' : payload.tool_name === 'TaskCreate' ? 'agent' : 'mcp']++; stats.total++; return; } try { const json = JSON.stringify(payload).replace(/'/g, "\\'"); execSync(`echo '${json}' | node "${HOOK}"`, { stdio: 'pipe', timeout: 5000 }); stats[payload.tool_name === 'Skill' ? 'skill' : payload.tool_name === 'TaskCreate' ? 'agent' : 'mcp']++; stats.total++; console.log(` [${evLabel}] ${detail}`); } catch (e) { stats.failed++; console.log(` [FAIL] ${detail} — ${e.message.slice(0, 80)}`); } } function skill(name, scenario) { console.log(`\n 用户: "${scenario}"`); trigger({ tool_name: 'Skill', tool_input: { skill: name } }, scenario); } function agent(name, subject, scenario) { console.log(`\n 系统: ${scenario}`); trigger({ tool_name: 'TaskCreate', tool_input: { subject: `[agent:${name}] ${subject}` } }, scenario); } function mcp(toolName, input, scenario) { console.log(`\n MCP: ${scenario}`); trigger({ tool_name: toolName, tool_input: input }, scenario); } // ═══════════════════════════════════════════════════════════ // 场景剧本: SaaS 支付网关重构 — 完整工作日 // ═══════════════════════════════════════════════════════════ // 场景仅在直接运行时执行 (被 require 时跳过) if (require.main !== module) { // 模块导出 (供测试使用) if (typeof module !== 'undefined') { module.exports = { detectClaudeRoot, trigger, skill, agent, mcp, stats, verifyStats, verifyLogIntegrity }; } return; // 被其他模块 require 时不执行场景 } console.log(''); console.log('================================================================'); console.log(' Bookworm 生产活动全量模拟器'); console.log(` 日期: ${new Date().toISOString().slice(0, 10)}`); console.log(` 模式: ${DRY_RUN ? '预览 (--dry-run)' : '写入活动日志'}`); console.log(` 钩子: ${HOOK}`); console.log('================================================================'); // ── Phase 1: 晨会与规划 (09:00-09:30) ────────────────── console.log('\n\n--- Phase 1: 晨会与项目规划 (09:00-09:30) ---'); skill('product-manager-expert', '帮我梳理 Q1 的产品路线图,重点是用户增长和留存功能'); skill('project-coordinator', '安排本周冲刺任务,包括支付模块重构和移动端适配'); skill('tech-lead-mentor', '新来的初级开发不太理解 SOLID 原则,帮我准备一份指导材料'); agent('orchestrator', '协调 Q1 支付模块重构项目', '编排多团队并行任务: 前端支付UI + 后端网关 + 数据库迁移'); // ── Phase 2: 架构与需求分析 (09:30-10:30) ────────────── console.log('\n\n--- Phase 2: 架构设计与需求分析 (09:30-10:30) ---'); skill('ai-ml-expert', '用户支付行为数据训练一个欺诈检测模型,要求 recall > 95% 且误报率 < 1%'); skill('architect-expert', '设计一个支持多租户的 SaaS 支付网关架构,要求 99.99% 可用性'); skill('cloud-native-expert', '我们要把支付服务迁移到 K8s,帮我设计 Helm Chart 和 HPA 策略'); skill('database-tuning-expert', 'PostgreSQL 的 orders 表已经 5000 万行了,查询越来越慢,怎么优化分区'); skill('edge-computing-expert', '海外用户延迟太高,考虑在边缘节点部署支付预校验服务'); skill('impact-analyst', '评估一下把支付从同步改成异步消息队列模式的影响范围'); skill('diagram-as-code-expert', '用 Mermaid 画一张支付系统的 C4 架构图'); mcp('mcp__sequential-thinking__sequentialthinking', { thought: '分析支付架构的关键决策点: 同步vs异步、单体vs微服务、SQL vs NoSQL', thoughtNumber: 1, totalThoughts: 5, nextThoughtNeeded: true }, '顺序推理分析支付架构决策树'); // ── Phase 3: 市场与商业分析 (10:30-11:00) ────────────── console.log('\n\n--- Phase 3: 市场与商业分析 (10:30-11:00) ---'); skill('business-plan-skill', '写一份 SaaS 支付平台的商业计划书,目标是种子轮融资'); skill('finance-advisor', '帮我做一个 3 年财务预测模型,包括 MRR 增长和获客成本'); skill('pricing-strategist', '我们的 API 调用计费模式合理吗?竞品都是怎么定价的'); skill('investor-review-guide', '投资人问我们的护城河是什么,帮我准备 pitch deck 的差异化部分'); skill('industry-research-cn', '调研一下 2025-2026 年中国第三方支付行业的监管趋势和市场规模'); skill('growth-hacker', '月活增长放缓了,帮我设计一套 PLG 增长飞轮策略'); skill('sales-consultant', '企业客户谈判卡在年费定价上了,给一些 B2B SaaS 的谈判技巧'); skill('legal-review-skill', '审查一下我们的用户服务条款,特别是支付退款和数据隐私部分'); agent('research-analyst', '竞品支付网关技术栈深度调研', '启动调研智能体,分析 Stripe/Adyen/PayPal 的技术架构差异'); mcp('mcp__deep-research__search', { query: '2026 payment gateway architecture trends microservices event-driven' }, '深度研究支付网关行业趋势'); // ── Phase 4: 前端开发 (11:00-12:00) ──────────────────── console.log('\n\n--- Phase 4: 前端开发 (11:00-12:00) ---'); skill('frontend-expert', '用 React 18 + TanStack Query 重写支付收银台组件,要求支持暗色模式'); skill('designer-expert', '设计支付成功页的 UI,要有品牌感和信任感'); skill('ux-researcher', '我们的支付转化率才 67%,分析一下结账流程哪一步流失最严重'); skill('miniprogram-expert', '微信小程序端的支付组件需要适配新版 JSAPI,帮我改一下'); skill('mobile-expert', 'React Native 端的支付页面在 Android 低端机上卡顿,怎么优化渲染'); agent('canvas-ui-designer', '设计支付收银台 UI 原型', '生成收银台组件的响应式设计方案和交互原型'); skill('copywriter-expert', '写支付页面的文案,包括按钮文字、错误提示、加载状态的 UX writing'); skill('social-media-manager', '新版支付体验上线了,帮我写一篇产品更新的推文和公众号文章'); mcp('mcp__playwright__browser_navigate', { url: 'http://localhost:3000/checkout' }, '自动化浏览器测试支付收银台页面渲染'); mcp('mcp__chrome-devtools__take_snapshot', {}, '用 DevTools 抓取收银台页面 DOM 快照排查布局问题'); // ── Phase 5: 后端与数据开发 (13:00-14:30) ────────────── console.log('\n\n--- Phase 5: 后端与数据开发 (13:00-14:30) ---'); skill('backend-builder', '用 NestJS + Prisma 实现支付回调的幂等处理逻辑'); skill('developer-expert', 'TypeScript 里怎么优雅地处理支付状态机的类型推导'); skill('api-integration-specialist', '集成支付宝和微信支付的统一回调接口,需要签名验证'); skill('data-engineer-expert', '设计支付数据的 ETL 管道,从 PostgreSQL 实时同步到 ClickHouse'); skill('data-analyst-expert', '分析上个月的支付数据,哪些渠道的失败率最高,原因是什么'); skill('regex-shell-wizard', '写一个正则提取支付日志里的交易 ID 和金额: "TXN-2026-[A-Z0-9]+ amount=\\d+.\\d+"'); skill('ultimate-code-expert', '这段支付回调处理代码有竞态条件,帮我重构成无锁设计'); skill('email-communicator', '帮我写一封邮件给支付渠道的技术对接人,催促沙箱环境的开通'); agent('full-stack-builder', '实现支付回调幂等处理模块', '全栈构建: 后端幂等键 + Redis 分布式锁 + 前端重试机制'); mcp('mcp__context7__resolve-library-id', { libraryName: '@nestjs/core' }, '查询 NestJS 最新文档以实现支付模块'); // ── Phase 6: 安全与合规 (14:30-15:00) ────────────────── console.log('\n\n--- Phase 6: 安全审计与合规 (14:30-15:00) ---'); skill('security-expert', '对支付 API 做一次安全审计,检查 OWASP Top 10 和 PCI-DSS 合规'); skill('devsecops-expert', '在 CI/CD 管道里集成 SAST/DAST 扫描,特别是密钥泄露检测'); skill('customer-success-expert', '用户投诉支付扣款成功但订单未更新,帮我排查并写一个安抚话术'); // ── Phase 7: 测试与质量 (15:00-16:00) ────────────────── console.log('\n\n--- Phase 7: 测试与质量保障 (15:00-16:00) ---'); skill('tester-expert', '帮我设计支付模块的测试方案,包括单元测试、集成测试和 E2E 测试'); skill('browser-automation-expert', '用 Playwright 写一个支付流程的 E2E 测试,覆盖成功/失败/超时三种场景'); skill('performance-expert', '支付接口的 P99 延迟从 200ms 涨到 800ms 了,帮我定位瓶颈'); skill('debugger-expert', '支付回调偶发 500 错误,日志里有 "deadlock detected",帮我排查'); agent('test-writer', '生成支付模块测试套件', '自动生成: 支付创建/回调/退款/对账 4 个模块的 Vitest 测试用例'); agent('quality-gate', '支付模块质量门控检查', '执行: 覆盖率 > 80% + 无 Critical 漏洞 + 性能基线达标'); agent('code-reviewer', '审查支付回调 PR #347', 'Review: 幂等处理逻辑 + Redis 锁超时 + 错误重试策略'); mcp('mcp__selenium__navigate', { url: 'http://localhost:3000/checkout?test=e2e' }, 'Selenium 跨浏览器兼容性测试支付页面'); mcp('mcp__browserbase__browserbase_session_create', {}, '创建云端浏览器会话进行多地域支付页面测试'); // ── Phase 8: 部署与运维 (16:00-17:00) ────────────────── console.log('\n\n--- Phase 8: 部署与运维 (16:00-17:00) ---'); skill('devops-expert', '帮我写 GitHub Actions 的 CI/CD 配置,支付模块要蓝绿部署'); skill('sre-expert', '设计支付系统的 SLO: 可用性 99.99%,P99 延迟 < 300ms,错误率 < 0.1%'); skill('git-operation-master', '支付分支 feature/payment-v2 需要 rebase 到 main,有 3 个冲突文件'); skill('technical-seo-expert', '支付成功页需要正确的 canonical URL 和结构化数据标记'); skill('prompt-optimizer', '优化支付客服机器人的 system prompt,让它更准确地处理退款咨询'); agent('pre-deploy-checker', '支付模块 v2.0 上线前检查', '预发布检查: 数据库迁移脚本 + 环境变量 + 回滚方案 + 监控告警'); // ── Phase 9: 系统自进化 (17:00-17:30) ────────────────── console.log('\n\n--- Phase 9: 系统自进化闭环 (17:00-17:30) ---'); skill('project-audit-expert', '对今天的支付模块重构做一个项目复盘,识别技术债和改进点'); skill('reviewer-expert', '帮我 review 今天提交的所有 PR,检查代码风格和架构一致性'); skill('genesis-engine', '根据今天的开发经验,生成一个"支付系统开发"的技能模板'); skill('zero-defect-guardian', '全面扫描支付模块的代码质量: 类型安全、错误处理、边界情况'); skill('tech-writer-expert', '帮支付模块写 API 文档,用 OpenAPI 3.0 格式'); agent('self-auditor', '每日系统一致性审计', '8 维度扫描: 配置 → 技能 → 智能体 → 钩子 → MCP → 路由 → 安全 → 磁盘'); agent('self-healer', '自动修复审计发现的元数据偏差', '修复: 版本号同步 + 技能计数校正 + 注册表更新'); // ═══════════════════════════════════════════════════════════ // 结果汇总 // ═══════════════════════════════════════════════════════════ console.log('\n'); console.log('================================================================'); console.log(' 模拟完成'); console.log('----------------------------------------------------------------'); console.log(` Skills: ${stats.skill}/50`); console.log(` Agents: ${stats.agent}/10`); console.log(` MCPs: ${stats.mcp}/7`); console.log(` ----------------`); console.log(` Total: ${stats.total}/67${stats.failed ? ` (${stats.failed} failed)` : ''}`); console.log('================================================================'); // 完整性校验函数 (供测试使用) function verifyStats(s) { return s.skill === 50 && s.agent === 10 && s.mcp === 7; } // 日志完整性校验函数 function verifyLogIntegrity(logFile, linesBefore) { const allLines = fs.readFileSync(logFile, 'utf8').trim().split('\n'); const newLines = allLines.slice(linesBefore); const skills = new Set(), agents = new Set(), mcps = new Set(); for (const line of newLines) { const o = JSON.parse(line); if (o.event === 'skill') skills.add(o.detail); else if (o.event === 'agent') { const m = o.detail.match(/\[agent:(\S+)\]/); agents.add(m ? m[1] : o.detail); } else if (o.event === 'mcp') mcps.add(o.detail.split('/')[0]); } return { newLines: newLines.length, skills: skills.size, agents: agents.size, mcps: mcps.size }; } if (require.main === module) { const passed = verifyStats(stats); if (!passed) { console.log('\n [WARN] 覆盖不完整,请检查失败项'); process.exit(1); } console.log(`\n [PASS] 全量覆盖验证通过 — 67/67 事件已${DRY_RUN ? '预览' : '写入活动日志'}`); // ─── --verify: 日志完整性校验 ─────────────────────────── if (VERIFY && !DRY_RUN) { console.log('\n--- 日志完整性校验 ---'); const dateStr = new Date().toISOString().slice(0, 10); const logFile = path.join(DEBUG_DIR, `activity-${dateStr}.jsonl`); try { const result = verifyLogIntegrity(logFile, logLinesBefore); console.log(` 新增日志行: ${result.newLines}`); console.log(` Unique Skills: ${result.skills}/50`); console.log(` Unique Agents: ${result.agents}/10`); console.log(` Unique MCPs: ${result.mcps}/7`); if (result.skills === 50 && result.agents === 10 && result.mcps === 7) { console.log('\n [PASS] 日志完整性校验通过'); } else { console.log('\n [WARN] 日志记录数与预期不符'); process.exit(1); } } catch (e) { console.log(` [ERROR] 无法读取日志: ${e.message}`); process.exit(1); } } }