[{"data":1,"prerenderedAt":3032},["ShallowReactive",2],{"navigation":3,"\u002Fpractice\u002Fdeployment":189,"\u002Fpractice\u002Fdeployment-surround":3027},[4,35,57,75,101,123,149,171],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":34},"第 1 章：认识 Claude Code","i-lucide-rocket","\u002Fintro","1.intro",[10,14,18,22,26,30],{"title":11,"path":12,"stem":13},"什么是 Claude Code","\u002Fintro\u002Fwhat-is-claude-code","1.intro\u002F1.what-is-claude-code",{"title":15,"path":16,"stem":17},"Claude Code 与 Copilot、Cursor、Windsurf 的本质区别","\u002Fintro\u002Fvs-competitors","1.intro\u002F2.vs-competitors",{"title":19,"path":20,"stem":21},"AI 编程助手生态全景与选型指南","\u002Fintro\u002Fecosystem-guide","1.intro\u002F3.ecosystem-guide",{"title":23,"path":24,"stem":25},"LLM 的概率本质","\u002Fintro\u002Fllm-probability","1.intro\u002F4.llm-probability",{"title":27,"path":28,"stem":29},"从聊天机器人到 Agent","\u002Fintro\u002Ffrom-chatbot-to-agent","1.intro\u002F5.from-chatbot-to-agent",{"title":31,"path":32,"stem":33},"Claude Code 的 Agentic Loop 全拆解","\u002Fintro\u002Fagentic-loop","1.intro\u002F6.agentic-loop",false,{"title":36,"icon":37,"path":38,"stem":39,"children":40,"page":34},"第 2 章：安装与配置","i-lucide-settings","\u002Fsetup","2.setup",[41,45,49,53],{"title":42,"path":43,"stem":44},"系统要求与安装方式","\u002Fsetup\u002Fsystem-requirements","2.setup\u002F1.system-requirements",{"title":46,"path":47,"stem":48},"认证、登录与多账户管理","\u002Fsetup\u002Fauthentication","2.setup\u002F2.authentication",{"title":50,"path":51,"stem":52},"选择你的界面","\u002Fsetup\u002Fchoose-interface","2.setup\u002F3.choose-interface",{"title":54,"path":55,"stem":56},"Coding Plan","\u002Fsetup\u002Fcoding-plan","2.setup\u002F4.coding-plan",{"title":58,"icon":59,"path":60,"stem":61,"children":62,"page":34},"第 3 章：快速上手","i-lucide-hand","\u002Fquickstart","3.quickstart",[63,67,71],{"title":64,"path":65,"stem":66},"启动、交互模式与基本命令","\u002Fquickstart\u002Fstartup","3.quickstart\u002F1.startup",{"title":68,"path":69,"stem":70},"让 Claude 理解你的项目","\u002Fquickstart\u002Fcodebase-understanding","3.quickstart\u002F2.codebase-understanding",{"title":72,"path":73,"stem":74},"第一次代码变更","\u002Fquickstart\u002Ffirst-change","3.quickstart\u002F3.first-change",{"title":76,"icon":77,"path":78,"stem":79,"children":80,"page":34},"第 4 章：核心功能","i-lucide-laptop","\u002Fcore-features","4.core-features",[81,85,89,93,97],{"title":82,"path":83,"stem":84},"代码库全景扫描与模块关系分析","\u002Fcore-features\u002Fcodebase-scan","4.core-features\u002F1.codebase-scan",{"title":86,"path":87,"stem":88},"代码编辑与生成","\u002Fcore-features\u002Fedit-generate","4.core-features\u002F2.edit-generate",{"title":90,"path":91,"stem":92},"测试与调试","\u002Fcore-features\u002Ftest-debug","4.core-features\u002F3.test-debug",{"title":94,"path":95,"stem":96},"Git 工作流","\u002Fcore-features\u002Fgit-workflow","4.core-features\u002F4.git-workflow",{"title":98,"path":99,"stem":100},"工具链执行","\u002Fcore-features\u002Ftoolchain","4.core-features\u002F5.toolchain",{"title":102,"icon":103,"path":104,"stem":105,"children":106,"page":34},"第 5 章：进阶配置","i-lucide-wrench","\u002Fadvanced","5.advanced",[107,111,115,119],{"title":108,"path":109,"stem":110},"CLAUDE.md","\u002Fadvanced\u002Fclaude-md","5.advanced\u002F1.claude-md",{"title":112,"path":113,"stem":114},"Skills","\u002Fadvanced\u002Fskills","5.advanced\u002F2.skills",{"title":116,"path":117,"stem":118},"MCP","\u002Fadvanced\u002Fmcp","5.advanced\u002F3.mcp",{"title":120,"path":121,"stem":122},"Hooks 与 Plan 模式","\u002Fadvanced\u002Fhooks-plan","5.advanced\u002F4.hooks-plan",{"title":124,"icon":125,"path":126,"stem":127,"children":128,"page":34},"第 6 章：实战开发","i-lucide-hammer","\u002Fpractice","6.practice",[129,133,137,141,145],{"title":130,"path":131,"stem":132},"需求分析与架构设计","\u002Fpractice\u002Frequirements-architecture","6.practice\u002F1.requirements-architecture",{"title":134,"path":135,"stem":136},"项目脚手架搭建与技术选型","\u002Fpractice\u002Fscaffolding","6.practice\u002F2.scaffolding",{"title":138,"path":139,"stem":140},"核心功能实现","\u002Fpractice\u002Fcore-features","6.practice\u002F3.core-features",{"title":142,"path":143,"stem":144},"测试覆盖、代码审查与质量调优","\u002Fpractice\u002Ftesting-quality","6.practice\u002F4.testing-quality",{"title":146,"path":147,"stem":148},"部署上线与成果分享","\u002Fpractice\u002Fdeployment","6.practice\u002F5.deployment",{"title":150,"icon":151,"path":152,"stem":153,"children":154,"page":34},"第 7 章：心法层","i-lucide-brain","\u002Fmindset","7.mindset",[155,159,163,167],{"title":156,"path":157,"stem":158},"提示词设计原则","\u002Fmindset\u002Fprompt-design","7.mindset\u002F1.prompt-design",{"title":160,"path":161,"stem":162},"上下文管理策略","\u002Fmindset\u002Fcontext-management","7.mindset\u002F2.context-management",{"title":164,"path":165,"stem":166},"安全与权限控制","\u002Fmindset\u002Fsecurity","7.mindset\u002F3.security",{"title":168,"path":169,"stem":170},"Boris Cherny 的 9 条实战心法与团队推广经验","\u002Fmindset\u002Fboris-cherny-tips","7.mindset\u002F4.boris-cherny-tips",{"title":172,"icon":173,"path":174,"stem":175,"children":176,"page":34},"附录","i-lucide-paperclip","\u002Fappendix","8.appendix",[177,181,185],{"title":178,"path":179,"stem":180},"常用命令速查表","\u002Fappendix\u002Fa.command-cheatsheet","8.appendix\u002Fa.command-cheatsheet",{"title":182,"path":183,"stem":184},"AI 核心术语汇编","\u002Fappendix\u002Fb.ai-terminology","8.appendix\u002Fb.ai-terminology",{"title":186,"path":187,"stem":188},"资源链接与延伸阅读","\u002Fappendix\u002Fc.resources","8.appendix\u002Fc.resources",{"id":190,"title":146,"body":191,"description":3020,"extension":3021,"links":3022,"meta":3023,"navigation":569,"path":147,"seo":3025,"stem":148,"__hash__":3026},"docs\u002F6.practice\u002F5.deployment.md",{"type":192,"value":193,"toc":2976},"minimark",[194,203,214,225,228,231,236,241,248,264,267,278,285,291,312,319,323,326,404,407,413,417,420,455,462,468,474,515,521,525,528,531,537,541,544,669,676,678,682,686,689,802,809,815,819,839,846,850,870,876,882,886,889,895,902,904,908,912,915,1297,1300,1304,1307,1333,1336,1341,1361,1368,1372,1375,1381,1385,1391,1479,1483,1489,1516,1519,1569,1571,1575,1579,1582,1602,1609,1615,1817,1828,1834,1838,1937,1940,1944,1950,1957,1962,1968,1971,1975,1978,1998,2001,2010,2024,2031,2037,2048,2055,2059,2062,2068,2071,2073,2077,2081,2084,2110,2117,2122,2157,2164,2168,2182,2185,2191,2217,2222,2228,2231,2235,2238,2244,2250,2256,2276,2279,2283,2286,2306,2309,2342,2345,2351,2377,2384,2386,2390,2394,2397,2421,2427,2453,2456,2462,2466,2469,2475,2481,2487,2507,2510,2531,2534,2544,2548,2551,2557,2560,2564,2567,2633,2636,2641,2667,2674,2679,2685,2689,2695,2701,2718,2724,2738,2745,2751,2765,2772,2777,2801,2804,2806,2809,2812,2822,2825,2828,2840,2843,2853,2856,2972],[195,196,197,198,202],"p",{},"6.4 的尾声留下一句承诺：带着\"质量已达标\"的代码进入部署上线环节。这一节兑现承诺。",[199,200,201],"strong",{},"部署不是开发的下游，而是产品价值真正开始流动的起点","——代码静静躺在仓库里时它的价值是零，只有当真实用户在真实场景中调用它，价值才被点亮。",[195,204,205,206,209,210,213],{},"但部署也是软件工程中\"事故密度\"最高的阶段。Google SRE 团队的一项统计指出：",[199,207,208],{},"生产环境的 70% 故障源于变更","——上线、配置、依赖升级。这意味着 Claude Code 协作的部署链路必须比开发链路更谨慎。本节会把\"上线前 → 上线中 → 上线后 → 成果沉淀\"四个阶段全部铺开，每个阶段给出一份可以立即套用的对话脚本与守护机制。读完之后，团队应该具备",[199,211,212],{},"用 Claude Code 把\"代码合并到 main\"到\"灰度推全量\"全流程托管的能力","。",[195,215,216,217,220,221,224],{},"需要先澄清一个常见误解：",[199,218,219],{},"Claude Code 在部署阶段的角色与开发阶段不同","。开发阶段它可以是\"主驱动者\"——主动写代码、主动修复 bug、主动重构。但部署阶段它只能是\"协作助手\"——生成清单、解读日志、起草 plan、协助复盘。",[199,222,223],{},"所有\"按下按钮\"的动作必须由人类工程师执行","。这条边界不是 AI 能力问题，而是责任分配问题——线上事故的法律责任、商业责任、用户信任责任，永远必须有一个人类承担者。把\"按按钮\"这条最简单但最关键的动作让给 AI，等同于让责任链断裂。",[195,226,227],{},"本节的所有方法论都建立在这条边界之上。读者在套用任何对话脚本时，都应当本能地问自己一句：\"这个动作的最终执行权在我手里，还是不知不觉间被让渡了？\"",[229,230],"hr",{},[232,233,235],"h2",{"id":234},"一上线前的飞行检查清单","一、上线前的\"飞行检查清单\"",[237,238,240],"h3",{"id":239},"_11-功能检查与回归测试","1.1 功能检查与回归测试",[195,242,243,244,247],{},"任何功能在合并到 main 之前都已经跑过本地测试与 CI 测试，但",[199,245,246],{},"上线前的检查不只是\"测试通过\"那么简单","。它需要回答四个问题：",[249,250,251,255,258,261],"ol",{},[252,253,254],"li",{},"本次发布包含哪些功能与变更？（changelog）",[252,256,257],{},"每项变更对现有功能有无回归风险？（regression scope）",[252,259,260],{},"哪些用户路径必须在上线后立即手动验证？（smoke test list）",[252,262,263],{},"万一出问题，回滚的最小操作单元是什么？（rollback unit）",[195,265,266],{},"让 Claude 协助生成\"变更影响分析报告\"：",[268,269,274],"pre",{"className":270,"code":272,"language":273},[271],"language-text","请分析自上次发布（tag v1.4.2）以来 main 分支的所有 commit，输出：\n1. 按业务模块分组的功能清单\n2. 每项变更的回归风险等级（低\u002F中\u002F高）\n3. 高风险变更建议的人工验证步骤\n4. 推荐的回滚单元（单 commit \u002F 多 commit \u002F 整版本）\n\n输出格式：Markdown 表格，可直接贴入发布说明。\n","text",[275,276,272],"code",{"__ignoreMap":277},"",[195,279,280,281,284],{},"Claude 输出的报告需要工程师审阅一遍。",[199,282,283],{},"不要直接把 AI 生成的回归风险评估当作最终判断","——它是起点，不是终点。",[195,286,287,290],{},[199,288,289],{},"回归测试的\"三圈层模型\"","：本人在多年实战中总结出一个简单分层，能让回归测试既高效又有覆盖度——",[292,293,294,300,306],"ul",{},[252,295,296,299],{},[199,297,298],{},"核心圈","（关键路径，必须 100% 自动化）：登录\u002F注册、付款、关键业务流程的端到端测试。任何一个失败立即阻断上线。",[252,301,302,305],{},[199,303,304],{},"外圈","（次要路径，自动化 + 抽样手测）：搜索、过滤、列表分页、设置页等。CI 跑完整自动化套件，灰度阶段额外抽样 5-10 个真实用户路径手动复核。",[252,307,308,311],{},[199,309,310],{},"边缘圈","（低频路径，主要靠监控）：管理后台、数据导出、批处理任务。不强求每次回归全测，靠生产环境监控告警兜底。",[195,313,314,315,318],{},"这种分层能避免\"全量回归测试\"的成本黑洞，又能保证最关键路径的零容忍。判断一条路径属于哪一圈的简单标准——",[199,316,317],{},"这条路径出问题，影响多少 DAU、影响多少营收、是否阻塞用户继续使用核心服务","？三个问题里有任何一个答\"很多\u002F很大\u002F是\"，它就是核心圈。",[237,320,322],{"id":321},"_12-性能与容量评估","1.2 性能与容量评估",[195,324,325],{},"新功能上线后，QPS、内存、数据库连接数都可能与开发环境不同。上线前必须做一次容量预估：",[327,328,329,345],"table",{},[330,331,332],"thead",{},[333,334,335,339,342],"tr",{},[336,337,338],"th",{},"维度",[336,340,341],{},"评估方法",[336,343,344],{},"工具",[346,347,348,360,371,382,393],"tbody",{},[333,349,350,354,357],{},[351,352,353],"td",{},"QPS 预估",[351,355,356],{},"基于历史相似功能 + 日活预估",[351,358,359],{},"团队历史数据、Prometheus",[333,361,362,365,368],{},[351,363,364],{},"数据库压力",[351,366,367],{},"慢查询计划、索引覆盖",[351,369,370],{},"EXPLAIN、pgbench",[333,372,373,376,379],{},[351,374,375],{},"内存占用",[351,377,378],{},"压测峰值 + 安全余量",[351,380,381],{},"k6、wrk、locust",[333,383,384,387,390],{},[351,385,386],{},"第三方依赖",[351,388,389],{},"API 限速、配额、熔断阈值",[351,391,392],{},"服务商控制台",[333,394,395,398,401],{},[351,396,397],{},"冷启动",[351,399,400],{},"Serverless 平台首次调用延迟",[351,402,403],{},"平台 metrics",[195,405,406],{},"让 Claude 生成压测脚本是高效的起点：",[268,408,411],{"className":409,"code":410,"language":273},[271],"基于 src\u002Fapi\u002Fuser\u002Flist.ts 的接口签名，写一个 k6 脚本，模拟：\n- 持续 5 分钟、100 并发用户\n- 70% 读 \u002F 30% 写\n- 错误率告警阈值 1%、p95 响应时间阈值 500ms\n- 输出 JSON 格式的报告供后续分析\n\n文件路径：tests\u002Fload\u002Fuser-list.k6.js\n不要修改其他文件。\n",[275,412,410],{"__ignoreMap":277},[237,414,416],{"id":415},"_13-安全合规与隐私自查","1.3 安全合规与隐私自查",[195,418,419],{},"每次上线都要做最少三项自查：",[292,421,422,436,449],{},[252,423,424,427,428,431,432,435],{},[199,425,426],{},"密钥扫描","：用 ",[275,429,430],{},"gitleaks"," 或 ",[275,433,434],{},"trufflehog"," 扫一遍 main 分支，确认没有把 API Key 误推到仓库。",[252,437,438,441,442,431,445,448],{},[199,439,440],{},"依赖漏洞","：跑 ",[275,443,444],{},"pnpm audit",[275,446,447],{},"npm audit","，把高危漏洞列入\"必须修复\"清单。",[252,450,451,454],{},[199,452,453],{},"数据合规","：如果改动涉及用户数据，对照公司隐私政策（GDPR、个保法、CCPA 等）逐项核对。",[195,456,457,458,461],{},"让 Claude 协助但",[199,459,460],{},"永远不让 Claude 拍板安全决策","：",[268,463,466],{"className":464,"code":465,"language":273},[271],"请运行 pnpm audit --json，把结果按 severity 分组。\n对于 high 与 critical 级别的漏洞：\n1. 列出受影响包与版本范围\n2. 说明可升级的修复版本\n3. 评估升级是否会引入 breaking change\n\n不要执行升级。我审阅后再决定。\n",[275,467,465],{"__ignoreMap":277},[195,469,470,473],{},[199,471,472],{},"\"安全合规自查\"的进阶清单","：除了密钥、漏洞、合规三大基础，成熟团队还需要覆盖以下细项——",[292,475,476,482,491,497,503,509],{},[252,477,478,481],{},[199,479,480],{},"CSP（Content Security Policy）","：前端是否设置了严格的内容安全策略，避免 XSS 利用。",[252,483,484,487,488,213],{},[199,485,486],{},"CORS 策略","：API 是否有过宽的 ",[275,489,490],{},"Access-Control-Allow-Origin: *",[252,492,493,496],{},[199,494,495],{},"认证 Token 时效","：JWT 过期时间是否合理（普通业务 1-24 小时、敏感操作更短）。",[252,498,499,502],{},[199,500,501],{},"日志脱敏","：日志中是否会无意打印用户密码、Token、身份证号等敏感数据。",[252,504,505,508],{},[199,506,507],{},"依赖来源","：是否引入了来路不明的小众包（注意\"包名错字\"型供应链攻击）。",[252,510,511,514],{},[199,512,513],{},"第三方 SDK 隐私","：埋点 SDK、广告 SDK 是否符合 App Store \u002F Google Play 隐私要求。",[195,516,517,518,213],{},"每一项都让 Claude 协助生成检查报告，再由工程师审阅决策。",[199,519,520],{},"安全决策永远是人类的责任",[237,522,524],{"id":523},"_14-文档与知识资产同步","1.4 文档与知识资产同步",[195,526,527],{},"上线意味着对外承诺。承诺包括：API 文档、changelog、用户指引、运维手册。任何一项滞后都会带来用户与运维的额外成本。",[195,529,530],{},"让 Claude 协助同步：",[268,532,535],{"className":533,"code":534,"language":273},[271],"基于 src\u002Fapi\u002Fv2\u002F* 这一轮新增的 5 个接口，生成：\n1. OpenAPI 3.0 spec（输出到 docs\u002Fapi\u002Fv2.yaml）\n2. 中文版接口说明（输出到 docs\u002Fapi\u002Fv2.md）\n3. 错误码索引（追加到 docs\u002Ferrors.md）\n4. CHANGELOG.md 中本次发布的新增条目\n\n请保持现有文档的风格与命名约定。\n",[275,536,534],{"__ignoreMap":277},[237,538,540],{"id":539},"_15-让-claude-生成上线前一日清单并交叉核对","1.5 让 Claude 生成\"上线前一日清单\"并交叉核对",[195,542,543],{},"把上面的所有动作汇总为一份\"上线前清单（Pre-Flight Checklist）\"，让 Claude 每次上线时自动生成并要求工程师逐项打钩：",[268,545,549],{"className":546,"code":547,"language":548,"meta":277,"style":277},"language-markdown shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","## v1.5.0 上线前清单 — 2026-04-27\n\n- [ ] CI 全绿（main 最新 commit）\n- [ ] 变更影响报告已审阅\n- [ ] 回归测试 100% 通过\n- [ ] 压测报告 p95 \u003C 500ms、错误率 \u003C 0.1%\n- [ ] gitleaks 扫描无密钥泄漏\n- [ ] pnpm audit 无 critical 漏洞\n- [ ] API 文档已同步\n- [ ] CHANGELOG.md 已更新\n- [ ] 回滚脚本已演练（staging 环境）\n- [ ] On-call 值班同学已通知\n- [ ] 灰度策略已确认（10% → 50% → 100%）\n- [ ] 监控告警已配置\n","markdown",[275,550,551,564,571,581,589,597,605,613,621,629,637,645,653,661],{"__ignoreMap":277},[552,553,556,560],"span",{"class":554,"line":555},"line",1,[552,557,559],{"class":558},"sMK4o","## ",[552,561,563],{"class":562},"sBMFI","v1.5.0 上线前清单 — 2026-04-27\n",[552,565,567],{"class":554,"line":566},2,[552,568,570],{"emptyLinePlaceholder":569},true,"\n",[552,572,574,577],{"class":554,"line":573},3,[552,575,576],{"class":558},"-",[552,578,580],{"class":579},"sTEyZ"," [ ] CI 全绿（main 最新 commit）\n",[552,582,584,586],{"class":554,"line":583},4,[552,585,576],{"class":558},[552,587,588],{"class":579}," [ ] 变更影响报告已审阅\n",[552,590,592,594],{"class":554,"line":591},5,[552,593,576],{"class":558},[552,595,596],{"class":579}," [ ] 回归测试 100% 通过\n",[552,598,600,602],{"class":554,"line":599},6,[552,601,576],{"class":558},[552,603,604],{"class":579}," [ ] 压测报告 p95 \u003C 500ms、错误率 \u003C 0.1%\n",[552,606,608,610],{"class":554,"line":607},7,[552,609,576],{"class":558},[552,611,612],{"class":579}," [ ] gitleaks 扫描无密钥泄漏\n",[552,614,616,618],{"class":554,"line":615},8,[552,617,576],{"class":558},[552,619,620],{"class":579}," [ ] pnpm audit 无 critical 漏洞\n",[552,622,624,626],{"class":554,"line":623},9,[552,625,576],{"class":558},[552,627,628],{"class":579}," [ ] API 文档已同步\n",[552,630,632,634],{"class":554,"line":631},10,[552,633,576],{"class":558},[552,635,636],{"class":579}," [ ] CHANGELOG.md 已更新\n",[552,638,640,642],{"class":554,"line":639},11,[552,641,576],{"class":558},[552,643,644],{"class":579}," [ ] 回滚脚本已演练（staging 环境）\n",[552,646,648,650],{"class":554,"line":647},12,[552,649,576],{"class":558},[552,651,652],{"class":579}," [ ] On-call 值班同学已通知\n",[552,654,656,658],{"class":554,"line":655},13,[552,657,576],{"class":558},[552,659,660],{"class":579}," [ ] 灰度策略已确认（10% → 50% → 100%）\n",[552,662,664,666],{"class":554,"line":663},14,[552,665,576],{"class":558},[552,667,668],{"class":579}," [ ] 监控告警已配置\n",[195,670,671,672,675],{},"这份清单不是装饰，而是",[199,673,674],{},"强制性放行门","。任何一项未打钩都不放行。让 Claude 把它写成 Skill，每次上线自动生成、自动校验。",[229,677],{},[232,679,681],{"id":680},"二部署策略选择适合产品阶段的发布节奏","二、部署策略——选择适合产品阶段的发布节奏",[237,683,685],{"id":684},"_21-蓝绿滚动金丝雀的本质差异","2.1 蓝绿、滚动、金丝雀的本质差异",[195,687,688],{},"四种主流部署策略各有适用场景：",[327,690,691,713],{},[330,692,693],{},[333,694,695,698,701,704,707,710],{},[336,696,697],{},"策略",[336,699,700],{},"工作机制",[336,702,703],{},"切换速度",[336,705,706],{},"资源开销",[336,708,709],{},"回滚速度",[336,711,712],{},"适用场景",[346,714,715,737,759,781],{},[333,716,717,722,725,728,731,734],{},[351,718,719],{},[199,720,721],{},"蓝绿部署（Blue-Green）",[351,723,724],{},"新旧两套环境共存，路由整体切换",[351,726,727],{},"秒级",[351,729,730],{},"2× 资源",[351,732,733],{},"秒级（路由切回）",[351,735,736],{},"状态机简单、停机敏感",[333,738,739,744,747,750,753,756],{},[351,740,741],{},[199,742,743],{},"滚动发布（Rolling）",[351,745,746],{},"实例分批替换，逐步替代",[351,748,749],{},"分钟级",[351,751,752],{},"1× 资源",[351,754,755],{},"慢（需重新部署旧版）",[351,757,758],{},"K8s 集群常规更新",[333,760,761,766,769,772,775,778],{},[351,762,763],{},[199,764,765],{},"金丝雀（Canary）",[351,767,768],{},"新版本先承接小流量验证",[351,770,771],{},"渐进式",[351,773,774],{},"1.x 资源",[351,776,777],{},"中等（缩量后回滚）",[351,779,780],{},"大用户量、变更高风险",[333,782,783,788,791,794,796,799],{},[351,784,785],{},[199,786,787],{},"特性开关（Feature Flag）",[351,789,790],{},"同一份部署内通过开关切换",[351,792,793],{},"即时",[351,795,752],{},[351,797,798],{},"即时（关开关）",[351,800,801],{},"多功能并行实验",[195,803,804,805,808],{},"四种策略不是互斥的——成熟团队会",[199,806,807],{},"组合使用","。常见组合：底层用滚动发布（资源效率高）、上层用 Feature Flag（精确控制功能曝光）、关键变更用金丝雀（小流量验证）、灾备演练用蓝绿（整体切换便于回滚）。组合的代价是运维复杂度上升，需要清晰的\"哪个变更走哪条路径\"的决策树。让 Claude 协助起草这棵决策树是不错的起点：",[268,810,813],{"className":811,"code":812,"language":273},[271],"我们的产品有以下技术变更类型：\n- 类型 A：纯前端 UI 改动（无 API 变更）\n- 类型 B：API 增量扩展（不破坏旧 client）\n- 类型 C：API breaking change（需要客户端升级）\n- 类型 D：数据库 schema 变更（含数据迁移）\n- 类型 E：依赖库重大升级\n\n请为每种类型推荐最合适的部署策略（蓝绿 \u002F 滚动 \u002F 金丝雀 \u002F Feature Flag），\n并解释为什么。输出表格供团队 review。\n",[275,814,812],{"__ignoreMap":277},[237,816,818],{"id":817},"_22-早期产品-vs-成熟产品的不同节奏","2.2 早期产品 vs 成熟产品的不同节奏",[292,820,821,827,833],{},[252,822,823,826],{},[199,824,825],{},"早期产品（\u003C 1000 DAU）","：直接发布即可，配合 Feature Flag 应对突发问题。过度复杂的灰度链路反而拖慢迭代节奏。",[252,828,829,832],{},[199,830,831],{},"成长期产品（1k - 100k DAU）","：开始引入金丝雀（10% → 50% → 100%），观察真实用户数据再放量。",[252,834,835,838],{},[199,836,837],{},"成熟产品（> 100k DAU）","：金丝雀 + 蓝绿 + 灰度全链路，配合精细化监控、自动回滚。",[195,840,841,842,845],{},"判断阶段的简易标准是\"",[199,843,844],{},"一次彻底失败的影响半径有多大？","\"——影响 100 个用户与影响 100 万个用户的承受力完全不同，部署策略也应当随之分层。",[237,847,849],{"id":848},"_23-平台选型serverless-容器-paas","2.3 平台选型——Serverless \u002F 容器 \u002F PaaS",[292,851,852,858,864],{},[252,853,854,857],{},[199,855,856],{},"Serverless（Vercel、Cloudflare Workers、AWS Lambda）","：冷启动友好、免运维、按量计费。适合前端、Edge 函数、低频后台任务。",[252,859,860,863],{},[199,861,862],{},"容器（Docker + Kubernetes）","：完全可控、生态最大、复杂度高。适合长生命周期服务、自定义网络\u002F存储需求。",[252,865,866,869],{},[199,867,868],{},"PaaS（Render、Fly.io、Railway）","：介于两者之间。免去 K8s 心智负担，又比 Serverless 自由。适合中小团队的后端服务。",[195,871,872,873,461],{},"让 Claude 帮你做选型对比但",[199,874,875],{},"不替你下决定",[268,877,880],{"className":878,"code":879,"language":273},[271],"我要部署一个 Node.js + Postgres 的中型 SaaS 后端，预计 50 万 DAU、\n峰值 QPS 800。请对比 Vercel、Fly.io、AWS ECS 三种方案，\n按以下维度输出表格：\n- 成本（月费用估算）\n- 冷启动延迟\n- Postgres 集成方式\n- 监控生态\n- 厂商锁定风险\n\n不要给出单一推荐结论，把判断权留给我。\n",[275,881,879],{"__ignoreMap":277},[237,883,885],{"id":884},"_24-让-claude-阅读部署日志并生成回滚-plan","2.4 让 Claude 阅读部署日志并生成回滚 plan",[195,887,888],{},"每次部署后让 Claude 拉一份\"部署后 5 分钟健康报告\"：",[268,890,893],{"className":891,"code":892,"language":273},[271],"我刚把 v1.5.0 部署到 staging。请：\n1. 拉取最近 5 分钟的应用日志\n2. 拉取最近 5 分钟的 Sentry 异常\n3. 拉取最近 5 分钟的 p95、p99 延迟数据\n4. 与上一版（v1.4.2）的同时间段数据对比\n\n输出\"健康度评分（0-100）\"以及任何异常的具体定位。\n若评分 \u003C 80，输出回滚 plan（仅展示，不要执行）。\n",[275,894,892],{"__ignoreMap":277},[195,896,897,898,901],{},"回滚 plan 的执行权一定握在工程师手里，",[199,899,900],{},"Claude 只能\"生成 plan\"，不能\"按下回滚按钮\"","——这是部署阶段最关键的人机分工底线。",[229,903],{},[232,905,907],{"id":906},"三cicd-与-claude-code-的协同","三、CI\u002FCD 与 Claude Code 的协同",[237,909,911],{"id":910},"_31-github-actions-gitlab-ci-中调用-claude-自动化","3.1 GitHub Actions \u002F GitLab CI 中调用 Claude 自动化",[195,913,914],{},"CI 流水线本身可以调用 Claude API 做自动化任务，例如自动写 PR 描述、自动生成 changelog、自动审查代码。一个最小的 GitHub Actions 示例：",[268,916,920],{"className":917,"code":918,"language":919,"meta":277,"style":277},"language-yaml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","# .github\u002Fworkflows\u002Fclaude-pr-review.yml\nname: Claude PR Review\non:\n  pull_request:\n    types: [opened, synchronize]\n\njobs:\n  review:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n        with:\n          fetch-depth: 0\n\n      - name: Generate diff\n        run: git diff origin\u002Fmain..HEAD > \u002Ftmp\u002Fdiff.patch\n\n      - name: Claude review\n        env:\n          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}\n        run: |\n          curl -X POST https:\u002F\u002Fapi.anthropic.com\u002Fv1\u002Fmessages \\\n            -H \"x-api-key: $ANTHROPIC_API_KEY\" \\\n            -H \"anthropic-version: 2023-06-01\" \\\n            -H \"content-type: application\u002Fjson\" \\\n            -d @- \u003C\u003CEOF | jq -r '.content[0].text' > review.md\n          {\n            \"model\": \"claude-sonnet-4-6\",\n            \"max_tokens\": 4096,\n            \"messages\": [{\n              \"role\": \"user\",\n              \"content\": \"Review this diff for correctness, security, and style:\\n\\n$(cat \u002Ftmp\u002Fdiff.patch | jq -Rs .)\"\n            }]\n          }\n          EOF\n\n      - name: Comment on PR\n        uses: actions\u002Fgithub-script@v7\n        with:\n          script: |\n            const fs = require('fs');\n            const review = fs.readFileSync('review.md', 'utf8');\n            github.rest.issues.createComment({\n              issue_number: context.issue.number,\n              owner: context.repo.owner,\n              repo: context.repo.repo,\n              body: `## Claude Review\\n\\n${review}`\n            });\n","yaml",[275,921,922,928,941,950,957,979,983,990,997,1007,1014,1027,1034,1045,1049,1062,1073,1078,1090,1098,1109,1120,1126,1132,1138,1144,1150,1156,1162,1168,1174,1180,1186,1192,1198,1204,1209,1221,1232,1239,1249,1255,1261,1267,1273,1279,1285,1291],{"__ignoreMap":277},[552,923,924],{"class":554,"line":555},[552,925,927],{"class":926},"sHwdD","# .github\u002Fworkflows\u002Fclaude-pr-review.yml\n",[552,929,930,934,937],{"class":554,"line":566},[552,931,933],{"class":932},"swJcz","name",[552,935,936],{"class":558},":",[552,938,940],{"class":939},"sfazB"," Claude PR Review\n",[552,942,943,947],{"class":554,"line":573},[552,944,946],{"class":945},"sfNiH","on",[552,948,949],{"class":558},":\n",[552,951,952,955],{"class":554,"line":583},[552,953,954],{"class":932},"  pull_request",[552,956,949],{"class":558},[552,958,959,962,964,967,970,973,976],{"class":554,"line":591},[552,960,961],{"class":932},"    types",[552,963,936],{"class":558},[552,965,966],{"class":558}," [",[552,968,969],{"class":939},"opened",[552,971,972],{"class":558},",",[552,974,975],{"class":939}," synchronize",[552,977,978],{"class":558},"]\n",[552,980,981],{"class":554,"line":599},[552,982,570],{"emptyLinePlaceholder":569},[552,984,985,988],{"class":554,"line":607},[552,986,987],{"class":932},"jobs",[552,989,949],{"class":558},[552,991,992,995],{"class":554,"line":615},[552,993,994],{"class":932},"  review",[552,996,949],{"class":558},[552,998,999,1002,1004],{"class":554,"line":623},[552,1000,1001],{"class":932},"    runs-on",[552,1003,936],{"class":558},[552,1005,1006],{"class":939}," ubuntu-latest\n",[552,1008,1009,1012],{"class":554,"line":631},[552,1010,1011],{"class":932},"    steps",[552,1013,949],{"class":558},[552,1015,1016,1019,1022,1024],{"class":554,"line":639},[552,1017,1018],{"class":558},"      -",[552,1020,1021],{"class":932}," uses",[552,1023,936],{"class":558},[552,1025,1026],{"class":939}," actions\u002Fcheckout@v4\n",[552,1028,1029,1032],{"class":554,"line":647},[552,1030,1031],{"class":932},"        with",[552,1033,949],{"class":558},[552,1035,1036,1039,1041],{"class":554,"line":655},[552,1037,1038],{"class":932},"          fetch-depth",[552,1040,936],{"class":558},[552,1042,1044],{"class":1043},"sbssI"," 0\n",[552,1046,1047],{"class":554,"line":663},[552,1048,570],{"emptyLinePlaceholder":569},[552,1050,1052,1054,1057,1059],{"class":554,"line":1051},15,[552,1053,1018],{"class":558},[552,1055,1056],{"class":932}," name",[552,1058,936],{"class":558},[552,1060,1061],{"class":939}," Generate diff\n",[552,1063,1065,1068,1070],{"class":554,"line":1064},16,[552,1066,1067],{"class":932},"        run",[552,1069,936],{"class":558},[552,1071,1072],{"class":939}," git diff origin\u002Fmain..HEAD > \u002Ftmp\u002Fdiff.patch\n",[552,1074,1076],{"class":554,"line":1075},17,[552,1077,570],{"emptyLinePlaceholder":569},[552,1079,1081,1083,1085,1087],{"class":554,"line":1080},18,[552,1082,1018],{"class":558},[552,1084,1056],{"class":932},[552,1086,936],{"class":558},[552,1088,1089],{"class":939}," Claude review\n",[552,1091,1093,1096],{"class":554,"line":1092},19,[552,1094,1095],{"class":932},"        env",[552,1097,949],{"class":558},[552,1099,1101,1104,1106],{"class":554,"line":1100},20,[552,1102,1103],{"class":932},"          ANTHROPIC_API_KEY",[552,1105,936],{"class":558},[552,1107,1108],{"class":939}," ${{ secrets.ANTHROPIC_API_KEY }}\n",[552,1110,1112,1114,1116],{"class":554,"line":1111},21,[552,1113,1067],{"class":932},[552,1115,936],{"class":558},[552,1117,1119],{"class":1118},"s7zQu"," |\n",[552,1121,1123],{"class":554,"line":1122},22,[552,1124,1125],{"class":939},"          curl -X POST https:\u002F\u002Fapi.anthropic.com\u002Fv1\u002Fmessages \\\n",[552,1127,1129],{"class":554,"line":1128},23,[552,1130,1131],{"class":939},"            -H \"x-api-key: $ANTHROPIC_API_KEY\" \\\n",[552,1133,1135],{"class":554,"line":1134},24,[552,1136,1137],{"class":939},"            -H \"anthropic-version: 2023-06-01\" \\\n",[552,1139,1141],{"class":554,"line":1140},25,[552,1142,1143],{"class":939},"            -H \"content-type: application\u002Fjson\" \\\n",[552,1145,1147],{"class":554,"line":1146},26,[552,1148,1149],{"class":939},"            -d @- \u003C\u003CEOF | jq -r '.content[0].text' > review.md\n",[552,1151,1153],{"class":554,"line":1152},27,[552,1154,1155],{"class":939},"          {\n",[552,1157,1159],{"class":554,"line":1158},28,[552,1160,1161],{"class":939},"            \"model\": \"claude-sonnet-4-6\",\n",[552,1163,1165],{"class":554,"line":1164},29,[552,1166,1167],{"class":939},"            \"max_tokens\": 4096,\n",[552,1169,1171],{"class":554,"line":1170},30,[552,1172,1173],{"class":939},"            \"messages\": [{\n",[552,1175,1177],{"class":554,"line":1176},31,[552,1178,1179],{"class":939},"              \"role\": \"user\",\n",[552,1181,1183],{"class":554,"line":1182},32,[552,1184,1185],{"class":939},"              \"content\": \"Review this diff for correctness, security, and style:\\n\\n$(cat \u002Ftmp\u002Fdiff.patch | jq -Rs .)\"\n",[552,1187,1189],{"class":554,"line":1188},33,[552,1190,1191],{"class":939},"            }]\n",[552,1193,1195],{"class":554,"line":1194},34,[552,1196,1197],{"class":939},"          }\n",[552,1199,1201],{"class":554,"line":1200},35,[552,1202,1203],{"class":939},"          EOF\n",[552,1205,1207],{"class":554,"line":1206},36,[552,1208,570],{"emptyLinePlaceholder":569},[552,1210,1212,1214,1216,1218],{"class":554,"line":1211},37,[552,1213,1018],{"class":558},[552,1215,1056],{"class":932},[552,1217,936],{"class":558},[552,1219,1220],{"class":939}," Comment on PR\n",[552,1222,1224,1227,1229],{"class":554,"line":1223},38,[552,1225,1226],{"class":932},"        uses",[552,1228,936],{"class":558},[552,1230,1231],{"class":939}," actions\u002Fgithub-script@v7\n",[552,1233,1235,1237],{"class":554,"line":1234},39,[552,1236,1031],{"class":932},[552,1238,949],{"class":558},[552,1240,1242,1245,1247],{"class":554,"line":1241},40,[552,1243,1244],{"class":932},"          script",[552,1246,936],{"class":558},[552,1248,1119],{"class":1118},[552,1250,1252],{"class":554,"line":1251},41,[552,1253,1254],{"class":939},"            const fs = require('fs');\n",[552,1256,1258],{"class":554,"line":1257},42,[552,1259,1260],{"class":939},"            const review = fs.readFileSync('review.md', 'utf8');\n",[552,1262,1264],{"class":554,"line":1263},43,[552,1265,1266],{"class":939},"            github.rest.issues.createComment({\n",[552,1268,1270],{"class":554,"line":1269},44,[552,1271,1272],{"class":939},"              issue_number: context.issue.number,\n",[552,1274,1276],{"class":554,"line":1275},45,[552,1277,1278],{"class":939},"              owner: context.repo.owner,\n",[552,1280,1282],{"class":554,"line":1281},46,[552,1283,1284],{"class":939},"              repo: context.repo.repo,\n",[552,1286,1288],{"class":554,"line":1287},47,[552,1289,1290],{"class":939},"              body: `## Claude Review\\n\\n${review}`\n",[552,1292,1294],{"class":554,"line":1293},48,[552,1295,1296],{"class":939},"            });\n",[195,1298,1299],{},"这种模式让\"AI 审查\"成为流水线的一部分，与人工审查并行。",[237,1301,1303],{"id":1302},"_32-每次-pr-自动跑-linttestbuilddeploy-预览","3.2 每次 PR 自动跑 lint\u002Ftest\u002Fbuild\u002Fdeploy 预览",[195,1305,1306],{},"PR 阶段就把\"是否能上线\"的所有信号摆出来：",[292,1308,1309,1315,1321,1327],{},[252,1310,1311,1314],{},[199,1312,1313],{},"lint + typecheck + test","：基础质量门",[252,1316,1317,1320],{},[199,1318,1319],{},"构建检查","：避免\"本地能跑、CI 跑不出\"",[252,1322,1323,1326],{},[199,1324,1325],{},"预览部署","（Vercel、Netlify 自动）：让 Reviewer 直接点开看效果",[252,1328,1329,1332],{},[199,1330,1331],{},"bundle size 检查","：阻止意外的依赖膨胀",[195,1334,1335],{},"工程师 review 时能同时看到\"代码改动 + 实际效果 + 关键指标\"。这条流程实现后，PR 评审效率提升 30% - 50% 是常见的（这是行业内多个团队的共识，但具体数字依赖团队基线）。",[195,1337,1338,461],{},[199,1339,1340],{},"预览环境（Preview Environments）的进阶用法",[292,1342,1343,1349,1355],{},[252,1344,1345,1348],{},[199,1346,1347],{},"每个 PR 一个独立 URL + 独立数据库","：避免 PR 之间互相干扰，让 reviewer 与产品经理可以放心点击。",[252,1350,1351,1354],{},[199,1352,1353],{},"预览环境集成测试","：CI 在预览环境上跑 e2e 测试，进一步前置质量门。",[252,1356,1357,1360],{},[199,1358,1359],{},"预览环境 Claude 演示","：让产品经理与 Claude 在预览环境上\"对话\"，验证功能是否符合需求。这种\"AI 主导的 UAT\"是新型工作模式的雏形——产品经理不需要工程师协助就能完成验收测试。",[195,1362,1363,1364,1367],{},"预览环境的成本主要是云资源费用。早期项目可以用 Serverless 平台（Vercel \u002F Cloudflare）的免费配额，到一定规模再考虑自建。",[199,1365,1366],{},"不要因为\"省钱\"而砍掉预览环境","——它带来的 review 效率与质量提升远超资源成本。",[237,1369,1371],{"id":1370},"_33-让-claude-解读-ci-失败日志","3.3 让 Claude 解读 CI 失败日志",[195,1373,1374],{},"CI 失败日志往往很长，最有价值的信号通常被埋在数百行 stack trace 中。让 Claude 协助：",[268,1376,1379],{"className":1377,"code":1378,"language":273},[271],"我在 GitHub Actions 上有一次失败的构建，日志在附件。请：\n1. 找到根本错误（root cause），引用原始日志行号\n2. 分析可能的原因（环境差异 \u002F 依赖版本 \u002F 代码 bug）\n3. 给出 3 个修复方案，按推荐度排序\n4. 不要直接改代码，等我确认方向后再写\n\n附件：[CI 日志 URL 或粘贴]\n",[275,1380,1378],{"__ignoreMap":277},[237,1382,1384],{"id":1383},"_34-hooks-ci-的双层守门","3.4 Hooks + CI 的双层守门",[195,1386,1387,1388,213],{},"最稳健的设计：本地 Hooks 拦下大部分问题，CI 兜底拦下漏网之鱼。两者结合的好处是——",[199,1389,1390],{},"Hooks 给开发者快速反馈，CI 给团队可信保证",[268,1392,1396],{"className":1393,"code":1394,"language":1395,"meta":277,"style":277},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","# 本地 .husky\u002Fpre-push（开发者快速反馈）\npnpm lint --max-warnings=0\npnpm typecheck\npnpm test --run\n\n# CI（团队可信保证）\npnpm lint --max-warnings=0\npnpm typecheck\npnpm test --coverage --run\npnpm build\npnpm test:e2e\n","bash",[275,1397,1398,1403,1414,1421,1431,1435,1440,1448,1454,1465,1472],{"__ignoreMap":277},[552,1399,1400],{"class":554,"line":555},[552,1401,1402],{"class":926},"# 本地 .husky\u002Fpre-push（开发者快速反馈）\n",[552,1404,1405,1408,1411],{"class":554,"line":566},[552,1406,1407],{"class":562},"pnpm",[552,1409,1410],{"class":939}," lint",[552,1412,1413],{"class":939}," --max-warnings=0\n",[552,1415,1416,1418],{"class":554,"line":573},[552,1417,1407],{"class":562},[552,1419,1420],{"class":939}," typecheck\n",[552,1422,1423,1425,1428],{"class":554,"line":583},[552,1424,1407],{"class":562},[552,1426,1427],{"class":939}," test",[552,1429,1430],{"class":939}," --run\n",[552,1432,1433],{"class":554,"line":591},[552,1434,570],{"emptyLinePlaceholder":569},[552,1436,1437],{"class":554,"line":599},[552,1438,1439],{"class":926},"# CI（团队可信保证）\n",[552,1441,1442,1444,1446],{"class":554,"line":607},[552,1443,1407],{"class":562},[552,1445,1410],{"class":939},[552,1447,1413],{"class":939},[552,1449,1450,1452],{"class":554,"line":615},[552,1451,1407],{"class":562},[552,1453,1420],{"class":939},[552,1455,1456,1458,1460,1463],{"class":554,"line":623},[552,1457,1407],{"class":562},[552,1459,1427],{"class":939},[552,1461,1462],{"class":939}," --coverage",[552,1464,1430],{"class":939},[552,1466,1467,1469],{"class":554,"line":631},[552,1468,1407],{"class":562},[552,1470,1471],{"class":939}," build\n",[552,1473,1474,1476],{"class":554,"line":639},[552,1475,1407],{"class":562},[552,1477,1478],{"class":939}," test:e2e\n",[237,1480,1482],{"id":1481},"_35-部署密钥与-secrets-管理","3.5 部署密钥与 secrets 管理",[195,1484,1485,1488],{},[199,1486,1487],{},"绝不让 Claude 触碰生产密钥","。这条规则没有例外。",[292,1490,1491,1500,1510],{},[252,1492,1493,427,1496,1499],{},[199,1494,1495],{},"密钥不进仓库",[275,1497,1498],{},".env.local","、CI Secrets、或专用 secret manager（Vault、AWS Secrets Manager、Doppler）。",[252,1501,1502,1505,1506,1509],{},[199,1503,1504],{},"密钥不进 prompt","：哪怕调试时也用占位符（",[275,1507,1508],{},"\u003CAPI_KEY>","），不要把真实值贴给 Claude。",[252,1511,1512,1515],{},[199,1513,1514],{},"密钥访问审计","：所有 Claude 触发的部署动作都应有审计日志。Hooks 可以记录\"哪个 prompt 引发了哪次部署\"。",[195,1517,1518],{},"把这条铁律写进 CLAUDE.md：",[268,1520,1522],{"className":546,"code":1521,"language":548,"meta":277,"style":277},"## 安全铁律\n- 永远不要在 prompt 中粘贴 API Key、Token、Password\n- 永远不要让 Claude 直接读 .env \u002F .env.local\n- 永远不要让 Claude 执行 deploy \u002F publish \u002F migration 命令\n  （Claude 只能 *生成 plan*，由工程师手动执行）\n",[275,1523,1524,1531,1538,1545,1552],{"__ignoreMap":277},[552,1525,1526,1528],{"class":554,"line":555},[552,1527,559],{"class":558},[552,1529,1530],{"class":562},"安全铁律\n",[552,1532,1533,1535],{"class":554,"line":566},[552,1534,576],{"class":558},[552,1536,1537],{"class":579}," 永远不要在 prompt 中粘贴 API Key、Token、Password\n",[552,1539,1540,1542],{"class":554,"line":573},[552,1541,576],{"class":558},[552,1543,1544],{"class":579}," 永远不要让 Claude 直接读 .env \u002F .env.local\n",[552,1546,1547,1549],{"class":554,"line":583},[552,1548,576],{"class":558},[552,1550,1551],{"class":579}," 永远不要让 Claude 执行 deploy \u002F publish \u002F migration 命令\n",[552,1553,1554,1557,1560,1564,1566],{"class":554,"line":591},[552,1555,1556],{"class":579},"  （Claude 只能 ",[552,1558,1559],{"class":1118},"*",[552,1561,1563],{"class":1562},"s5tWE","生成 plan",[552,1565,1559],{"class":1118},[552,1567,1568],{"class":579},"，由工程师手动执行）\n",[229,1570],{},[232,1572,1574],{"id":1573},"四上线后的可观测性与告警","四、上线后的可观测性与告警",[237,1576,1578],{"id":1577},"_41-日志追踪指标三位一体","4.1 日志、追踪、指标三位一体",[195,1580,1581],{},"可观测性（Observability）的三根支柱：",[292,1583,1584,1590,1596],{},[252,1585,1586,1589],{},[199,1587,1588],{},"日志（Logs）","：结构化、可搜索、带 trace_id。工具：Loki、ELK、Datadog Logs。",[252,1591,1592,1595],{},[199,1593,1594],{},"追踪（Traces）","：一次请求穿过所有服务的全链路记录。工具：Jaeger、Tempo、OpenTelemetry。",[252,1597,1598,1601],{},[199,1599,1600],{},"指标（Metrics）","：聚合的数值时间序列。工具：Prometheus + Grafana、Datadog Metrics。",[195,1603,1604,1605,1608],{},"三者打通后，工程师能在告警时",[199,1606,1607],{},"从指标飙升 → 找到关联 trace → 找到具体日志 → 定位代码行","——这条链路是上线后排障的高速公路。",[195,1610,1611,1614],{},[199,1612,1613],{},"结构化日志的最小契约","：本人在多个项目中固化了一份 8 字段结构化日志规范，让 Claude 与人都能高效查询：",[268,1616,1620],{"className":1617,"code":1618,"language":1619,"meta":277,"style":277},"language-typescript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u002F\u002F src\u002Flog\u002Flogger.ts\nexport interface LogEntry {\n  level: \"debug\" | \"info\" | \"warn\" | \"error\" | \"fatal\";\n  timestamp: string; \u002F\u002F ISO 8601\n  trace_id: string;  \u002F\u002F 全链路追踪 ID\n  span_id?: string;  \u002F\u002F 可选，子调用 ID\n  service: string;   \u002F\u002F 服务名（user-api \u002F billing-svc）\n  user_id?: string;  \u002F\u002F 可选，关联用户（脱敏）\n  event: string;     \u002F\u002F 事件类型（USER_LOGIN_FAILED）\n  payload: Record\u003Cstring, unknown>; \u002F\u002F 事件结构化数据\n}\n","typescript",[275,1621,1622,1627,1642,1698,1714,1728,1743,1757,1771,1785,1812],{"__ignoreMap":277},[552,1623,1624],{"class":554,"line":555},[552,1625,1626],{"class":926},"\u002F\u002F src\u002Flog\u002Flogger.ts\n",[552,1628,1629,1632,1636,1639],{"class":554,"line":566},[552,1630,1631],{"class":1118},"export",[552,1633,1635],{"class":1634},"spNyl"," interface",[552,1637,1638],{"class":562}," LogEntry",[552,1640,1641],{"class":558}," {\n",[552,1643,1644,1647,1649,1652,1655,1658,1661,1663,1666,1668,1670,1672,1675,1677,1679,1681,1684,1686,1688,1690,1693,1695],{"class":554,"line":573},[552,1645,1646],{"class":932},"  level",[552,1648,936],{"class":558},[552,1650,1651],{"class":558}," \"",[552,1653,1654],{"class":939},"debug",[552,1656,1657],{"class":558},"\"",[552,1659,1660],{"class":558}," |",[552,1662,1651],{"class":558},[552,1664,1665],{"class":939},"info",[552,1667,1657],{"class":558},[552,1669,1660],{"class":558},[552,1671,1651],{"class":558},[552,1673,1674],{"class":939},"warn",[552,1676,1657],{"class":558},[552,1678,1660],{"class":558},[552,1680,1651],{"class":558},[552,1682,1683],{"class":939},"error",[552,1685,1657],{"class":558},[552,1687,1660],{"class":558},[552,1689,1651],{"class":558},[552,1691,1692],{"class":939},"fatal",[552,1694,1657],{"class":558},[552,1696,1697],{"class":558},";\n",[552,1699,1700,1703,1705,1708,1711],{"class":554,"line":583},[552,1701,1702],{"class":932},"  timestamp",[552,1704,936],{"class":558},[552,1706,1707],{"class":562}," string",[552,1709,1710],{"class":558},";",[552,1712,1713],{"class":926}," \u002F\u002F ISO 8601\n",[552,1715,1716,1719,1721,1723,1725],{"class":554,"line":591},[552,1717,1718],{"class":932},"  trace_id",[552,1720,936],{"class":558},[552,1722,1707],{"class":562},[552,1724,1710],{"class":558},[552,1726,1727],{"class":926},"  \u002F\u002F 全链路追踪 ID\n",[552,1729,1730,1733,1736,1738,1740],{"class":554,"line":599},[552,1731,1732],{"class":932},"  span_id",[552,1734,1735],{"class":558},"?:",[552,1737,1707],{"class":562},[552,1739,1710],{"class":558},[552,1741,1742],{"class":926},"  \u002F\u002F 可选，子调用 ID\n",[552,1744,1745,1748,1750,1752,1754],{"class":554,"line":607},[552,1746,1747],{"class":932},"  service",[552,1749,936],{"class":558},[552,1751,1707],{"class":562},[552,1753,1710],{"class":558},[552,1755,1756],{"class":926},"   \u002F\u002F 服务名（user-api \u002F billing-svc）\n",[552,1758,1759,1762,1764,1766,1768],{"class":554,"line":615},[552,1760,1761],{"class":932},"  user_id",[552,1763,1735],{"class":558},[552,1765,1707],{"class":562},[552,1767,1710],{"class":558},[552,1769,1770],{"class":926},"  \u002F\u002F 可选，关联用户（脱敏）\n",[552,1772,1773,1776,1778,1780,1782],{"class":554,"line":623},[552,1774,1775],{"class":932},"  event",[552,1777,936],{"class":558},[552,1779,1707],{"class":562},[552,1781,1710],{"class":558},[552,1783,1784],{"class":926},"     \u002F\u002F 事件类型（USER_LOGIN_FAILED）\n",[552,1786,1787,1790,1792,1795,1798,1801,1803,1806,1809],{"class":554,"line":631},[552,1788,1789],{"class":932},"  payload",[552,1791,936],{"class":558},[552,1793,1794],{"class":562}," Record",[552,1796,1797],{"class":558},"\u003C",[552,1799,1800],{"class":562},"string",[552,1802,972],{"class":558},[552,1804,1805],{"class":562}," unknown",[552,1807,1808],{"class":558},">;",[552,1810,1811],{"class":926}," \u002F\u002F 事件结构化数据\n",[552,1813,1814],{"class":554,"line":639},[552,1815,1816],{"class":558},"}\n",[195,1818,1819,1820,1823,1824,1827],{},"每条日志强制走这个 schema，禁止 ",[275,1821,1822],{},"console.log(\"xxx\")"," 直接打印。带来的好处是——",[199,1825,1826],{},"当事故发生时，工程师可以让 Claude 直接基于 trace_id 拼接全链路时间线","，而不是手工 grep 数十个微服务的日志文件。",[268,1829,1832],{"className":1830,"code":1831,"language":273},[271],"请基于 trace_id=abc123 查询过去 1 小时的所有日志，按时间排序，\n输出该请求经过的所有服务、每一步的耗时、最终错误码。\n我要重建用户报告的\"付款失败\"完整路径。\n",[275,1833,1831],{"__ignoreMap":277},[237,1835,1837],{"id":1836},"_42-错误监控平台的选型","4.2 错误监控平台的选型",[327,1839,1840,1855],{},[330,1841,1842],{},[333,1843,1844,1846,1849,1852],{},[336,1845,344],{},[336,1847,1848],{},"强项",[336,1850,1851],{},"弱项",[336,1853,1854],{},"价格",[346,1856,1857,1873,1889,1905,1921],{},[333,1858,1859,1864,1867,1870],{},[351,1860,1861],{},[199,1862,1863],{},"Sentry",[351,1865,1866],{},"错误聚合、source map 完美",[351,1868,1869],{},"性能监控功能较新",[351,1871,1872],{},"中",[333,1874,1875,1880,1883,1886],{},[351,1876,1877],{},[199,1878,1879],{},"Datadog",[351,1881,1882],{},"全栈、APM 强",[351,1884,1885],{},"价格陡",[351,1887,1888],{},"高",[333,1890,1891,1896,1899,1902],{},[351,1892,1893],{},[199,1894,1895],{},"Logfire（Pydantic）",[351,1897,1898],{},"LLM 友好、OpenTelemetry 原生",[351,1900,1901],{},"生态较新",[351,1903,1904],{},"低-中",[333,1906,1907,1912,1915,1918],{},[351,1908,1909],{},[199,1910,1911],{},"Honeycomb",[351,1913,1914],{},"高基数查询、SRE 友好",[351,1916,1917],{},"学习曲线陡",[351,1919,1920],{},"中-高",[333,1922,1923,1928,1931,1934],{},[351,1924,1925],{},[199,1926,1927],{},"自建 Loki + Grafana",[351,1929,1930],{},"成本可控、数据自有",[351,1932,1933],{},"运维负担",[351,1935,1936],{},"低（成本时间）",[195,1938,1939],{},"早期项目用 Sentry 起步、长期向 Logfire 或 Datadog 演进，是相对稳妥的路径。",[237,1941,1943],{"id":1942},"_43-让-claude-阅读异常堆栈并生成根因假设","4.3 让 Claude 阅读异常堆栈并生成根因假设",[268,1945,1948],{"className":1946,"code":1947,"language":273},[271],"Sentry 上有一条新异常：\n- 错误类：TypeError: Cannot read properties of undefined (reading 'map')\n- 出现位置：src\u002Fapi\u002Fuser\u002Flist.ts:42\n- 频次：过去 1 小时 327 次\n- 影响用户：89 人\n\n请：\n1. 阅读 src\u002Fapi\u002Fuser\u002Flist.ts:30-60\n2. 输出 3 个最可能的根因假设\n3. 对每个假设，建议一个最快的验证方法\n4. 不要修改代码，等我确认假设后再写补丁\n",[275,1949,1947],{"__ignoreMap":277},[195,1951,1952,1953,1956],{},"让 Claude 提\"假设\"而不是\"答案\"。",[199,1954,1955],{},"LLM 的强项是快速生成多个候选解释，弱项是分辨哪个是真相","——分辨的工作必须由工程师承担。",[195,1958,1959,461],{},[199,1960,1961],{},"根因分析的\"五个为什么\"模板",[268,1963,1966],{"className":1964,"code":1965,"language":273},[271],"我已经定位到表层错误：[贴错误]\n请以\"五个为什么\"形式逐层追问，找到根因。每一层基于上一层的答案继续追问。\n\n格式：\n- 为什么 1：[问题] → [答案]\n- 为什么 2：基于上一答案的新问题 → [答案]\n- ...\n- 为什么 5：[问题] → [根因]\n\n根因找到后，输出 3 个层次的修复方案：\n- 短期（停血）：1-2 小时内可执行的缓解\n- 中期（防再次发生）：1 周内可执行的代码改进\n- 长期（系统性改进）：1 个月内可执行的架构调整\n",[275,1967,1965],{"__ignoreMap":277},[195,1969,1970],{},"这种结构化追问能避免\"看到表层错误就修补\"的浅层处理。LLM 善于结构化思考，工程师善于在每一层中识别\"哪个答案有问题、哪个答案需要继续追问\"。两者结合的效果远超任一独立工作。",[237,1972,1974],{"id":1973},"_44-slo-sli-的最小可行设置","4.4 SLO \u002F SLI 的最小可行设置",[195,1976,1977],{},"刚开始不需要复杂的 SLO 体系。三条基线即可：",[292,1979,1980,1986,1992],{},[252,1981,1982,1985],{},[199,1983,1984],{},"可用性（Availability）","：99.9%（每月允许约 43 分钟不可用）",[252,1987,1988,1991],{},[199,1989,1990],{},"延迟（Latency）","：p95 \u003C 500ms、p99 \u003C 1500ms",[252,1993,1994,1997],{},[199,1995,1996],{},"错误率（Error Rate）","：\u003C 0.5%（5xx 占总请求）",[195,1999,2000],{},"把这三条写进监控仪表板，并设置自动告警（任何一项跌出阈值连续 5 分钟就触发 PagerDuty）。",[195,2002,2003,2006,2007,461],{},[199,2004,2005],{},"SLO 不是越严越好","。99.99% 比 99.9% 在用户体感上几乎无差别，但工程成本可能差一个数量级（错误预算从每月 43 分钟收紧到 4.3 分钟，每一次\"非预期重启\"都会消耗大量预算）。",[199,2008,2009],{},"SLO 应该贴合用户实际期待与公司商业目标",[292,2011,2012,2015,2018,2021],{},[252,2013,2014],{},"内部工具：99% 已足够，过度投入是浪费。",[252,2016,2017],{},"普通 SaaS：99.9% 是常见基线。",[252,2019,2020],{},"金融、医疗、关键基础设施：99.99% 起步，且需要专门的容灾架构。",[252,2022,2023],{},"超高并发互联网（搜索、广告）：99.95%-99.99% 视具体业务而定。",[195,2025,2026,2027,2030],{},"把 SLO 写进",[199,2028,2029],{},"与产品团队的\"服务等级协议\"","——不只是工程内部的指标，而是产品\u002F工程之间对\"什么是可接受\"的明确约定。每季度 review 一次，根据真实用户投诉与业务影响调整。这条机制能避免\"工程团队默默把 SLO 调到无法实现的高度\"或\"产品团队只盯功能不关心可用性\"两种极端。",[195,2032,2033,2036],{},[199,2034,2035],{},"错误预算（Error Budget）的妙用","：错误预算是 SLO 的\"反面表述\"——99.9% 可用性意味着每月有 43 分钟的\"预算\"可以失败。这 43 分钟的预算可以怎么用？",[292,2038,2039,2042,2045],{},[252,2040,2041],{},"主动用于实验（混沌工程、故障演练、新部署策略试验）",[252,2043,2044],{},"被动消耗在生产事故上",[252,2046,2047],{},"用于 SRE 团队的非紧急维护窗口",[195,2049,2050,2051,2054],{},"错误预算耗尽时，团队应当",[199,2052,2053],{},"冻结非关键变更","，把工程精力投入\"把可用性恢复到 SLO 之上\"。这条机制把\"上线节奏\"与\"系统稳定性\"绑定起来——稳定性差时自动慢下来，稳定性好时自动快起来——比靠\"管理直觉\"做决定更可量化。",[237,2056,2058],{"id":2057},"_45-用-plan-模式守住线上事故响应","4.5 用 Plan 模式守住\"线上事故响应\"",[195,2060,2061],{},"线上事故是最容易\"在压力下做错事\"的场景。Plan 模式在这里价值倍增：",[268,2063,2066],{"className":2064,"code":2065,"language":273},[271],"线上事故 P1：用户登录失败率从 0.3% 飙到 18%。\n我已经初步定位是 v1.5.0 引入的 JWT 校验逻辑变更。\n\n请进入 Plan 模式，输出：\n1. 立即缓解方案（3 个候选）\n2. 每个方案的执行步骤、风险、预计耗时\n3. 推荐的最小动作\n\n不要直接执行。我看完 plan 再决定按哪一个。\n",[275,2067,2065],{"__ignoreMap":277},[195,2069,2070],{},"事故现场 90% 的\"二次灾害\"都源于\"想得不够清楚就动手\"。Plan 模式的强制延迟就是给工程师的\"刹车\"。",[229,2072],{},[232,2074,2076],{"id":2075},"五灰度回滚与故障恢复","五、灰度、回滚与故障恢复",[237,2078,2080],{"id":2079},"_51-灰度策略按用户按地域按比例","5.1 灰度策略——按用户、按地域、按比例",[195,2082,2083],{},"灰度的颗粒度选择取决于变更性质：",[292,2085,2086,2092,2098,2104],{},[252,2087,2088,2091],{},[199,2089,2090],{},"按比例","（10% → 50% → 100%）：通用兜底策略，适合无明显用户分层的功能。",[252,2093,2094,2097],{},[199,2095,2096],{},"按用户分层","（内部员工 → Alpha → Beta → 公测 → 全量）：适合高风险功能，先在最能容忍故障的群体中验证。",[252,2099,2100,2103],{},[199,2101,2102],{},"按地域","（先发某区域）：适合地域高度独立的业务（电商、本地化服务）。",[252,2105,2106,2109],{},[199,2107,2108],{},"按设备","（先发某机型 \u002F OS）：适合移动端原生应用，与商店审核节奏配合。",[195,2111,2112,2113,2116],{},"灰度的间隔时间也很关键。本人的经验：",[199,2114,2115],{},"每个灰度阶段至少观察 24 小时再放量","。低于这个时间窗，长尾问题（缓存穿透、定时任务、低频路径）来不及暴露就被推全量了。",[195,2118,2119,461],{},[199,2120,2121],{},"灰度数据的\"四看一不看\"原则",[292,2123,2124,2130,2136,2142,2148],{},[252,2125,2126,2129],{},[199,2127,2128],{},"看错误率","：5xx、4xx（特别是 401\u002F403\u002F422）的绝对值与变化率。",[252,2131,2132,2135],{},[199,2133,2134],{},"看延迟","：p50、p95、p99 三档分位数，特别关注 p99 的尾部恶化。",[252,2137,2138,2141],{},[199,2139,2140],{},"看业务指标","：转化率、留存率、付费率。技术指标正常但业务指标骤降，说明功能本身有问题。",[252,2143,2144,2147],{},[199,2145,2146],{},"看用户反馈","：客服工单、社交媒体抱怨、应用商店评分。",[252,2149,2150,2153,2154,213],{},[199,2151,2152],{},"不看","：\"灰度组的开发者本人手动验证\"——这种验证带有强烈的确认偏差（confirmation bias），开发者无意识地往\"我希望它工作\"的路径走，会放过真实用户场景才会触发的问题。",[199,2155,2156],{},"生产数据胜过开发者的直觉",[195,2158,2159,2160,2163],{},"灰度过程中如果\"看\"到任何一项指标异常（哪怕只是趋势可疑），第一动作不是\"分析原因\"，而是",[199,2161,2162],{},"先把灰度量级冻结","——不放量，等查清楚再说。这个反应速度往往决定了最后是\"小范围灰度故障\"还是\"全量爆炸\"。",[237,2165,2167],{"id":2166},"_52-回滚的两种姿势版本回滚-vs-feature-flag-关闭","5.2 回滚的两种姿势——版本回滚 vs feature flag 关闭",[292,2169,2170,2176],{},[252,2171,2172,2175],{},[199,2173,2174],{},"版本回滚","：通过 CI\u002FCD 把上一版本的镜像重新部署。适合\"代码层级\"出问题。",[252,2177,2178,2181],{},[199,2179,2180],{},"Feature Flag 关闭","：保留代码、关闭开关。适合\"功能层级\"出问题，且代码本身没有破坏其他功能。",[195,2183,2184],{},"Feature Flag 的优势是\"秒级回退、不影响其他变更\"。建议所有\"用户可见的新功能\"上线时都默认放在 Flag 后面，至少在前两周保留这个安全阀。",[195,2186,2187,2190],{},[199,2188,2189],{},"Feature Flag 的反模式","：再好的工具用错了也会变成负债。常见的 Feature Flag 反模式：",[292,2192,2193,2199,2205,2211],{},[252,2194,2195,2198],{},[199,2196,2197],{},"Flag 长期不清理","：项目里堆了 200 个 Flag，没人知道哪些还有效。建议每季度清理一次\"已稳定 6 周以上\"的 Flag。",[252,2200,2201,2204],{},[199,2202,2203],{},"Flag 嵌套地狱","：A Flag 里检查 B Flag 里检查 C Flag——逻辑变成无人能读懂的迷宫。建议 Flag 嵌套层数限制为 1，超过就重构。",[252,2206,2207,2210],{},[199,2208,2209],{},"Flag 管理无审计","：谁在什么时候打开了哪个 Flag、为什么？没有日志的 Flag 操作是潜在风险源。建议把 Flag 切换接入审计系统（CloudTrail、自建日志）。",[252,2212,2213,2216],{},[199,2214,2215],{},"配置即开关","：把环境变量当 Flag 用，每次切换都要重启。建议用专用 Flag 平台（LaunchDarkly、Unleash、Flagsmith）以支持热切换。",[195,2218,2219,461],{},[199,2220,2221],{},"让 Claude 协助 Flag 治理",[268,2223,2226],{"className":2224,"code":2225,"language":273},[271],"请扫描代码库，列出所有 Feature Flag 使用情况：\n1. Flag 名称\n2. 引用位置（文件 + 行号）\n3. Flag 创建时间（基于 git blame）\n4. Flag 是否还在 active 配置中\n\n输出 Markdown 表格。对于\"创建 > 6 周且默认值已固定\"的 Flag，\n标记为\"可清理候选\"。我审阅后决定是否真的清理。\n",[275,2227,2225],{"__ignoreMap":277},[195,2229,2230],{},"每季度跑一次这个对话，团队的 Flag 健康度会保持在可控状态。",[237,2232,2234],{"id":2233},"_53-让-claude-协助故障复盘","5.3 让 Claude 协助故障复盘",[195,2236,2237],{},"故障复盘（Postmortem）写好不容易，写得既客观又有可执行结论更难。让 Claude 协助：",[268,2239,2242],{"className":2240,"code":2241,"language":273},[271],"请基于以下材料起草故障复盘文档：\n- 事故时间线：[贴时间戳与关键事件]\n- 影响范围：用户数、收入损失、SLA 违约\n- 根本原因（已确认）：[贴根因分析]\n- 缓解步骤：[贴实际操作]\n\n输出格式遵循 Google SRE Book 的 Postmortem 模板：\n1. 摘要 \u002F 2. 影响 \u002F 3. 根本原因 \u002F 4. 触发因素 \u002F\n5. 已生效的缓解 \u002F 6. 检测耗时 \u002F 7. 修复耗时 \u002F\n8. 行动项（短期 \u002F 中期 \u002F 长期，每项指定负责人与截止日）\n\n要求：客观、不指责个人、关注系统问题。\n",[275,2243,2241],{"__ignoreMap":277},[195,2245,2246,2247,213],{},"复盘的真正价值不是\"找到谁错了\"，而是\"系统怎么改才不会重复发生\"。Claude 在这里的角色是结构化记录者，",[199,2248,2249],{},"不是责任分配者",[195,2251,2252,2255],{},[199,2253,2254],{},"Blameless Postmortem 的三条核心原则","（来自 Google SRE Book）：",[249,2257,2258,2264,2270],{},[252,2259,2260,2263],{},[199,2261,2262],{},"聚焦系统、不聚焦个人","：永远问\"系统为什么允许这个错误发生\"，而不是\"谁犯了错\"。即使根因是\"工程师 A 误删了配置\"，复盘也应该追问\"为什么系统没有防止误删 \u002F 没有自动告警 \u002F 没有快速恢复机制\"。",[252,2265,2266,2269],{},[199,2267,2268],{},"诚实优于面子","：复盘文档对内透明，鼓励工程师如实记录\"我当时以为 X 但实际是 Y\"。隐瞒细节会让团队失去从错误中学习的机会。",[252,2271,2272,2275],{},[199,2273,2274],{},"行动项必须是 SMART 的","（Specific、Measurable、Achievable、Relevant、Time-bound）：避免\"加强监控\"这种空话，应该写成\"在 2026-05-15 前为 user-svc 添加 5xx > 1% 持续 3 分钟的 PagerDuty 告警\"。",[195,2277,2278],{},"让 Claude 在生成复盘草稿时强制套用 SMART 模板，能避免大多数\"看起来很全但落不了地\"的复盘文档。",[237,2280,2282],{"id":2281},"_54-把每次故障沉淀为-claudemd-与-skills","5.4 把每次故障沉淀为 CLAUDE.md 与 Skills",[195,2284,2285],{},"每次故障复盘的\"行动项\"应该被分解到三个去处：",[292,2287,2288,2294,2300],{},[252,2289,2290,2293],{},[199,2291,2292],{},"代码改动","：通过 PR 改进具体逻辑。",[252,2295,2296,2299],{},[199,2297,2298],{},"CLAUDE.md 更新","：把这次的教训写成\"未来 Claude 协作时的规则\"。",[252,2301,2302,2305],{},[199,2303,2304],{},"Skills 沉淀","：如果同类故障在其他模块也可能发生，把检测\u002F修复流程封装为可复用 skill。",[195,2307,2308],{},"举例：经过一次\"Redis 雪崩\"故障，CLAUDE.md 里追加：",[268,2310,2312],{"className":546,"code":2311,"language":548,"meta":277,"style":277},"## 缓存设计规则（来自 2026-04-15 P1 事故）\n- 缓存失效时间必须随机化（基础 TTL ± 20%），避免雪崩\n- 任何 Redis 读必须有降级路径（DB 直读 + 限流）\n- 新增缓存键前必须在 PR 描述里说明：键命名、TTL、降级策略\n",[275,2313,2314,2321,2328,2335],{"__ignoreMap":277},[552,2315,2316,2318],{"class":554,"line":555},[552,2317,559],{"class":558},[552,2319,2320],{"class":562},"缓存设计规则（来自 2026-04-15 P1 事故）\n",[552,2322,2323,2325],{"class":554,"line":566},[552,2324,576],{"class":558},[552,2326,2327],{"class":579}," 缓存失效时间必须随机化（基础 TTL ± 20%），避免雪崩\n",[552,2329,2330,2332],{"class":554,"line":573},[552,2331,576],{"class":558},[552,2333,2334],{"class":579}," 任何 Redis 读必须有降级路径（DB 直读 + 限流）\n",[552,2336,2337,2339],{"class":554,"line":583},[552,2338,576],{"class":558},[552,2340,2341],{"class":579}," 新增缓存键前必须在 PR 描述里说明：键命名、TTL、降级策略\n",[195,2343,2344],{},"下一次有人在 Claude Code 里写新的缓存逻辑，这条规则会自动被 Claude 注意到，避免同类故障复发。",[195,2346,2347,2350],{},[199,2348,2349],{},"主动故障演练（Chaos Engineering）的最低门槛实践","：与其等故障到来，不如主动制造可控故障。最简单的入门门槛只需要做四件事：",[249,2352,2353,2359,2365,2371],{},[252,2354,2355,2358],{},[199,2356,2357],{},"每月一次\"杀进程演练\"","：在 staging 环境随机 kill 一个服务实例，验证服务发现、负载均衡、自动重启是否生效。",[252,2360,2361,2364],{},[199,2362,2363],{},"每季度一次\"依赖宕机演练\"","：手动断开 Redis、DB、第三方 API 的连接，验证降级路径与告警是否触发。",[252,2366,2367,2370],{},[199,2368,2369],{},"每半年一次\"全量切流演练\"","：把流量从主可用区切到备可用区，验证灾备链路。",[252,2372,2373,2376],{},[199,2374,2375],{},"每年一次\"红蓝对抗\"","：让一个工程师扮演\"攻击者\"主动制造问题，另一个工程师扮演\"防御者\"复现处理流程。",[195,2378,2379,2380,2383],{},"每一次演练都让 Claude 协助撰写\"演练报告 + 改进项\"，并在月度复盘会上 review。半年后团队的事故响应能力会显著提升——",[199,2381,2382],{},"因为他们已经在受控环境下\"演练过\"几乎所有可能的故障类型","。这是把\"运维侥幸心理\"转化为\"工程系统韧性\"的最直接路径。",[229,2385],{},[232,2387,2389],{"id":2388},"六成果分享与团队复盘","六、成果分享与团队复盘",[237,2391,2393],{"id":2392},"_61-内部分享技术分享知识沉淀团队庆祝","6.1 内部分享——技术分享、知识沉淀、团队庆祝",[195,2395,2396],{},"产品上线不是终点，是\"知识资产沉淀\"的开始。建议每次较大上线后做三件事：",[292,2398,2399,2405,2411],{},[252,2400,2401,2404],{},[199,2402,2403],{},"技术分享会","（30-60 分钟）：负责人讲架构选型与踩坑经历，团队提问。",[252,2406,2407,2410],{},[199,2408,2409],{},"知识库更新","：把项目中沉淀的 CLAUDE.md、Skills、运维 runbook 全部归档到团队 wiki。",[252,2412,2413,2416,2417,2420],{},[199,2414,2415],{},"团队庆祝","：哪怕只是订一顿好吃的，也要让付出的工程师感到被看见。",[199,2418,2419],{},"仪式感是工程文化的重要组成部分","——长期忽视会让团队节奏慢慢掉到\"完成任务\"而失去\"创造产品\"的兴奋感。",[195,2422,2423,2426],{},[199,2424,2425],{},"技术分享会的内容设计","：好的内部分享应当回答四个问题：",[249,2428,2429,2435,2441,2447],{},[252,2430,2431,2434],{},[199,2432,2433],{},"我们解决了什么问题？","——以用户场景或业务痛点开篇，而不是技术术语。",[252,2436,2437,2440],{},[199,2438,2439],{},"我们尝试了哪些方案？","——展示真实的决策路径，包括被淘汰的备选方案。这部分往往比\"最终方案\"更有教学价值。",[252,2442,2443,2446],{},[199,2444,2445],{},"我们最终选择了什么？为什么？","——决策依据、trade-off、当时的约束条件。",[252,2448,2449,2452],{},[199,2450,2451],{},"回头看，如果重来一次会怎么做？","——已知的遗憾、改进方向、未来计划。",[195,2454,2455],{},"让 Claude 协助起草分享会大纲：",[268,2457,2460],{"className":2458,"code":2459,"language":273},[271],"请基于以下材料起草 30 分钟内部分享会大纲：\n- 项目背景：[贴 PRD]\n- 关键技术决策：[贴 ADR 列表]\n- 主要踩坑：[贴 Postmortem 列表]\n- 上线后数据：[贴 KPI 汇总]\n\n要求：\n1. 大纲分四部分（What\u002FWhy\u002FHow\u002FReflection），每部分 5-10 分钟\n2. 每部分至少 1 个具体代码示例或数据图表\n3. 留出 10 分钟问答时间\n4. 突出\"我们尝试了什么、为什么没选\"——这部分往往最有教学价值\n",[275,2461,2459],{"__ignoreMap":277},[237,2463,2465],{"id":2464},"_62-外部分享博客演讲开源发布会","6.2 外部分享——博客、演讲、开源、发布会",[195,2467,2468],{},"向外部分享的好处：建立工程影响力、吸引人才、获取真实用户反馈。Claude 在这里能扮演\"协作写作者\"的角色：",[268,2470,2473],{"className":2471,"code":2472,"language":273},[271],"我们刚上线了一个使用 Claude Code 协作开发的产品。请帮我起草一篇技术博客，\n包含：\n- 项目背景（30 字）\n- 我们如何与 Claude 协作（具体的 prompt 模式 \u002F Skills \u002F Hooks 配置）\n- 踩过的坑（3-5 个具体例子）\n- 学到的最佳实践（带数据支持）\n- 开源链接 \u002F 演示链接\n\n要求：第一人称、技术细节具体、不夸大 AI 能力、避免营销腔。长度 2000-3000 字。\n我审阅后再发布。\n",[275,2474,2472],{"__ignoreMap":277},[195,2476,2477,2480],{},[199,2478,2479],{},"不要让 Claude 全自动发布","——内容由 Claude 起草、工程师把关、再发布。",[195,2482,2483,2486],{},[199,2484,2485],{},"外部分享的\"三层目标\"","：每次外部分享都应当问自己——这次的目标是什么？",[292,2488,2489,2495,2501],{},[252,2490,2491,2494],{},[199,2492,2493],{},"第一层：知识贡献","——让其他工程师从我们的经验中学到具体方法。",[252,2496,2497,2500],{},[199,2498,2499],{},"第二层：吸引人才","——展示团队工程文化，让对的人主动找上门。",[252,2502,2503,2506],{},[199,2504,2505],{},"第三层：建立长期话语权","——让团队\u002F公司在某个细分领域被持续记住。",[195,2508,2509],{},"三层目标不冲突，但优先级会决定文章的写作风格——",[292,2511,2512,2519,2525],{},[252,2513,2514,2515,2518],{},"第一层为主时，文章应当",[199,2516,2517],{},"技术密度高、代码示例多、避免主观判断","；",[252,2520,2521,2522,2518],{},"第二层为主时，文章应当",[199,2523,2524],{},"展现独特工程文化、有故事感、有\"人味\"",[252,2526,2527,2528,213],{},"第三层为主时，文章应当",[199,2529,2530],{},"形成系列、相互引用、长期累积",[195,2532,2533],{},"让 Claude 协助前先明确告诉它本次目标，避免输出\"什么都顾及但什么都不深入\"的平庸内容。",[195,2535,2536,2539,2540,2543],{},[199,2537,2538],{},"开源的隐藏价值","：开源不只是\"贡献代码给社区\"，更是",[199,2541,2542],{},"强迫团队提高代码质量与文档水准","——因为外部贡献者的眼光比内部 review 更挑剔。本人见过多个团队在开源后才意识到自己的代码\"原来很多隐性约定都没写下来\"，被迫做了一轮整体梳理。这一轮梳理本身就是巨大的工程债清算机会。",[237,2545,2547],{"id":2546},"_63-让-claude-协助生成项目复盘报告","6.3 让 Claude 协助生成项目复盘报告",[195,2549,2550],{},"项目复盘（Project Retrospective）与故障复盘不同——它聚焦\"整个项目的得失\"。让 Claude 基于完整的 git 历史与会议记录起草：",[268,2552,2555],{"className":2553,"code":2554,"language":273},[271],"请基于以下材料起草 v1.0.0 项目复盘报告：\n- git log（自项目启动到上线 v1.0.0）\n- 全部 PR 描述（导出为 .json）\n- 会议记录（导出为 markdown）\n\n复盘维度：\n1. What went well：哪些做对了？\n2. What didn't：哪些做得不够好？\n3. What surprised us：哪些超出预期？\n4. AI 协作收益：节省了多少时间？引入了哪些新工作？\n5. 给下个项目的 5 条建议\n\n输出格式：Markdown，包含表格与时间线。\n",[275,2556,2554],{"__ignoreMap":277},[195,2558,2559],{},"这份报告是团队下一个项目的起跑线。",[237,2561,2563],{"id":2562},"_64-度量产品成功的四象限","6.4 度量产品成功的\"四象限\"",[195,2565,2566],{},"不要只盯着技术指标。一个完整的成功度量需要四个维度：",[327,2568,2569,2581],{},[330,2570,2571],{},[333,2572,2573,2575,2578],{},[336,2574,338],{},[336,2576,2577],{},"示例指标",[336,2579,2580],{},"适用阶段",[346,2582,2583,2596,2609,2621],{},[333,2584,2585,2590,2593],{},[351,2586,2587],{},[199,2588,2589],{},"业务指标",[351,2591,2592],{},"收入、付费用户数、留存率",[351,2594,2595],{},"任何阶段",[333,2597,2598,2603,2606],{},[351,2599,2600],{},[199,2601,2602],{},"用户指标",[351,2604,2605],{},"DAU、NPS、功能使用率",[351,2607,2608],{},"MVP 之后",[333,2610,2611,2616,2619],{},[351,2612,2613],{},[199,2614,2615],{},"技术指标",[351,2617,2618],{},"可用性、延迟、错误率",[351,2620,2595],{},[333,2622,2623,2628,2631],{},[351,2624,2625],{},[199,2626,2627],{},"团队指标",[351,2629,2630],{},"交付节奏、Bug 率、心情指数",[351,2632,2595],{},[195,2634,2635],{},"四个维度同时改善，才算真正的\"成功\"。任何一个长期失衡（例如技术指标好但团队心情差），都需要主动调整。",[195,2637,2638,461],{},[199,2639,2640],{},"四象限指标的反模式",[292,2642,2643,2649,2655,2661],{},[252,2644,2645,2648],{},[199,2646,2647],{},"业务好、团队差","——典型现象是销售\u002F客户成功疯狂索取功能，工程团队疲于奔命、士气低落。表面 KPI 漂亮，留存率却暗中恶化（核心工程师陆续离职）。短期续命、长期透支。",[252,2650,2651,2654],{},[199,2652,2653],{},"技术好、用户差","——典型现象是过度工程，把每个延迟都优化到极致、把每个边界都覆盖到 100%，但用户其实抱怨的是核心交互体验差。这是\"工程师的自我满足\"而非\"用户的真实价值\"。",[252,2656,2657,2660],{},[199,2658,2659],{},"用户好、业务差","——典型现象是产品被用户喜欢但变现路径不通。需要重新审视商业模型而非加大研发投入。",[252,2662,2663,2666],{},[199,2664,2665],{},"团队好、业务差","——典型现象是团队工作氛围好但产品没有市场拉力。需要重新评估 PMF（Product-Market Fit）。",[195,2668,2669,2670,2673],{},"四象限的真正作用不是\"打分\"，而是",[199,2671,2672],{},"早期识别失衡的信号","。每月 review 一次，找到弱项最严重的象限，作为下个月的工作重心。这条机制比\"光看 OKR 数字\"更能反映项目的真实健康度。",[195,2675,2676,461],{},[199,2677,2678],{},"让 Claude 协助生成四象限月报",[268,2680,2683],{"className":2681,"code":2682,"language":273},[271],"请基于以下数据源，生成 2026-04 月度四象限报告：\n- 业务数据（导出 CSV）：[贴 URL]\n- 产品分析（Mixpanel \u002F Amplitude）：[贴查询结果]\n- 监控指标（Grafana 截图描述 + Prometheus 数据）：[贴]\n- 团队指标（git 活动 + 1-on-1 反馈摘要）：[贴]\n\n输出：\n1. 每个象限的 3 条核心结论（数据支撑）\n2. 最弱象限的根因分析\n3. 给下个月的 5 条行动建议（含负责人与截止日）\n",[275,2684,2682],{"__ignoreMap":277},[237,2686,2688],{"id":2687},"_65-从这次实战学到的ai-协作风格如何沉淀到下一个项目","6.5 从这次实战学到的\"AI 协作风格\"如何沉淀到下一个项目",[195,2690,2691,2692],{},"每个项目结束后，团队应该问自己一个问题：",[199,2693,2694],{},"\"如果重新做一遍这个项目，哪些 AI 协作模式应该带走，哪些应该丢掉？\"",[195,2696,2697,2698,461],{},"带走的部分写进",[199,2699,2700],{},"模板仓库",[292,2702,2703,2706,2709,2712,2715],{},[252,2704,2705],{},"通用 CLAUDE.md（团队级共识）",[252,2707,2708],{},"通用 Skills（已被多个项目验证）",[252,2710,2711],{},"通用 Hooks 配置",[252,2713,2714],{},"CI\u002FCD 模板",[252,2716,2717],{},"Postmortem 模板",[195,2719,2720,2721,461],{},"丢掉的部分写进",[199,2722,2723],{},"反模式清单",[292,2725,2726,2729,2732,2735],{},[252,2727,2728],{},"哪些 prompt 风格容易让 Claude 跑偏？",[252,2730,2731],{},"哪些 Skill 颗粒度太大或太小？",[252,2733,2734],{},"哪些 Hooks 频繁失效？",[252,2736,2737],{},"哪些\"AI 自动化\"反而拖慢了节奏？",[195,2739,2740,2741,2744],{},"下一个项目启动时，",[199,2742,2743],{},"这两份清单一起注入","——好的部分被复用，坏的部分被规避。半年累积下来，团队的 AI 协作能力会形成一条清晰的\"复利曲线\"，远高于\"每个项目从零摸索\"的团队。",[195,2746,2747,2750],{},[199,2748,2749],{},"复利效应的量化案例","：本人参与过的一个 8 人工程团队，在使用 Claude Code 一年后做了一次回顾——",[292,2752,2753,2756,2759,2762],{},[252,2754,2755],{},"第 1 个月：人均交付速度 1.0×（基线），AI 协作占工作时间约 15%。",[252,2757,2758],{},"第 3 个月：人均交付速度 1.4×，AI 协作占比约 40%，CLAUDE.md 沉淀 ~80 行核心规则。",[252,2760,2761],{},"第 6 个月：人均交付速度 1.8×，AI 协作占比约 55%，Skills 库 ~12 个，Hooks 配置 ~6 条。",[252,2763,2764],{},"第 12 个月：人均交付速度 2.4×，AI 协作占比约 65%，Skills 库 ~25 个，跨项目复用率 60%。",[195,2766,2767,2768,2771],{},"复利的关键不在某一个 Skill 或某一条 CLAUDE.md，而在",[199,2769,2770],{},"这些资产在多个项目间的复用率","。复用率从 60% → 80% 的跨越，往往伴随着团队从\"每个项目都重新摸索\"到\"每个新项目自动继承上一个项目的肌肉记忆\"的质变。",[195,2773,2774,461],{},[199,2775,2776],{},"让复利不被打断的三条习惯",[249,2778,2779,2785,2795],{},[252,2780,2781,2784],{},[199,2782,2783],{},"每个项目结束都做\"AI 资产盘点\"","：列出本项目沉淀的 CLAUDE.md \u002F Skills \u002F Hooks，标记可复用部分。",[252,2786,2787,2790,2791,2794],{},[199,2788,2789],{},"维护一个\"团队 AI 资产中心仓库\"","：把可复用资产发布到这个内部仓库，新项目通过 ",[275,2792,2793],{},"pnpm create @team\u002Fscaffold"," 一键继承。",[252,2796,2797,2800],{},[199,2798,2799],{},"每季度做一次资产 review","：淘汰过时资产、合并相似资产、补充缺失资产。把资产中心当作\"活的代码\"维护，而非\"冻结的归档\"。",[195,2802,2803],{},"这三条习惯看似简单，但坚持执行的团队往往是那些把 Claude Code 真正用出复利的团队。",[229,2805],{},[232,2807,2808],{"id":2808},"总结",[195,2810,2811],{},"部署上线把\"代码\"变成\"产品\"，把\"团队的劳动\"变成\"用户感受到的价值\"。本节给出的所有清单、对话脚本、平台对比、灰度策略、复盘模板，目标只有一个——让\"上线\"从工程师的高压时刻，变成 AI 协作的稳定流水线动作。当上线被结构化、可观测、可回滚、可复盘地嵌入团队工作流之后，工程师可以把注意力从\"今天会不会出事\"转移到\"下一个产品要解决什么问题\"。",[195,2813,2814,2817,2818,2821],{},[199,2815,2816],{},"最重要的态度转变","：在 AI 协作时代，部署上线的\"难\"不再是\"技术难\"，而是\"心智难\"——团队是否愿意把曾经的\"凭经验\"升级为\"凭流程\"、把曾经的\"个人英雄主义\"升级为\"集体可观测性\"。Claude Code 提供的所有工具（Plan 模式、Hooks、Skills、CLAUDE.md）都是",[199,2819,2820],{},"心智升级的杠杆","，但杠杆需要一个真正想撬动的人。读完本节的工程师与产品经理，回到团队后做的第一件事不应该是\"立即开始用 Hooks\"，而应该是\"和团队对齐：我们想成为什么样的工程组织？\"——回答这个问题之后，所有工具的使用方式才会自然浮现而稳健落地。",[195,2823,2824],{},"第十章实战章节到此落幕。第十一章我们将进入\"心法层\"——那些不依赖某个具体工具、却决定团队长期生产力的\"基础原则\"。下一节 7.1 已经开始讨论\"提示词设计原则\"，把每一次与 Claude 的对话变成一次有效的协作契约。",[195,2826,2827],{},"留给读者的两个习题：",[249,2829,2830,2837],{},[252,2831,2832,2833,2836],{},"在你当前项目里，写一份\"上线前清单\"模板，至少包含 10 项，每项配一行说明。把它纳入 ",[275,2834,2835],{},".claude\u002Fskills\u002Frelease-checklist\u002F","，下次发布时跑一遍。",[252,2838,2839],{},"选一次最近的故障，用本节的\"故障复盘模板\"重写一份 Postmortem。完成后让团队的另一位工程师读一遍——如果他能从中看出至少 1 条之前不知道的系统改进点，复盘就成功了。",[195,2841,2842],{},"这两个习题做完之后，你会发现\"上线\"不再是开发的负担，而是一段被 AI 协作打磨过的稳定流水线。",[195,2844,2845,2848,2849,2852],{},[199,2846,2847],{},"最后一条建议","：把本节内容打印出来贴在团队会议室的墙上，下次有人提议\"我们直接发吧、问题不大\"时，让所有人抬头看一眼这份清单。",[199,2850,2851],{},"仪式感本身就是工程文化的重要组成部分","——那些坚持流程、不省小步的团队，长期下来事故率往往是不坚持流程团队的 1\u002F5 甚至更低。Claude Code 能加速流程的执行，但不能替代流程的存在。把流程坚持下去，是工程团队对用户、对自己最朴素的负责。",[232,2854,2855],{"id":2855},"延伸阅读",[292,2857,2858,2868,2876,2884,2892,2900,2908,2916,2924,2932,2940,2948,2956,2964],{},[252,2859,2860,2867],{},[2861,2862,2866],"a",{"href":2863,"rel":2864},"https:\u002F\u002Fdocs.anthropic.com\u002Fclaude\u002Fdocs\u002Fclaude-code",[2865],"nofollow","Anthropic Claude Code 官方文档"," — Plan 模式、Hooks、Skills 全览",[252,2869,2870,2875],{},[2861,2871,2874],{"href":2872,"rel":2873},"https:\u002F\u002Fsre.google\u002Fsre-book\u002Ftable-of-contents\u002F",[2865],"Google SRE Book"," — 站点可靠性工程经典著作",[252,2877,2878,2883],{},[2861,2879,2882],{"href":2880,"rel":2881},"https:\u002F\u002Fsre.google\u002Fworkbook\u002Ftable-of-contents\u002F",[2865],"Google SRE Workbook"," — SRE 实践手册",[252,2885,2886,2891],{},[2861,2887,2890],{"href":2888,"rel":2889},"https:\u002F\u002F12factor.net\u002Fzh_cn\u002F",[2865],"The Twelve-Factor App"," — 现代应用部署 12 准则（中文）",[252,2893,2894,2899],{},[2861,2895,2898],{"href":2896,"rel":2897},"https:\u002F\u002Fvercel.com\u002Fdocs",[2865],"Vercel 官方文档"," — Serverless 前端部署平台",[252,2901,2902,2907],{},[2861,2903,2906],{"href":2904,"rel":2905},"https:\u002F\u002Ffly.io\u002Fdocs\u002F",[2865],"Fly.io 官方文档"," — 全球边缘 PaaS",[252,2909,2910,2915],{},[2861,2911,2914],{"href":2912,"rel":2913},"https:\u002F\u002Fdocs.sentry.io\u002F",[2865],"Sentry 官方文档"," — 错误监控与性能监控",[252,2917,2918,2923],{},[2861,2919,2922],{"href":2920,"rel":2921},"https:\u002F\u002Fdocs.datadoghq.com\u002F",[2865],"Datadog 官方文档"," — 全栈可观测性平台",[252,2925,2926,2931],{},[2861,2927,2930],{"href":2928,"rel":2929},"https:\u002F\u002Fopentelemetry.io\u002Fdocs\u002F",[2865],"OpenTelemetry 官方文档"," — 可观测性数据规范",[252,2933,2934,2939],{},[2861,2935,2938],{"href":2936,"rel":2937},"https:\u002F\u002Flogfire.pydantic.dev\u002Fdocs\u002F",[2865],"Logfire 官方文档（Pydantic）"," — LLM 友好的可观测性平台",[252,2941,2942,2947],{},[2861,2943,2946],{"href":2944,"rel":2945},"https:\u002F\u002Fk6.io\u002Fdocs\u002F",[2865],"k6 负载测试官方文档"," — 现代压测工具",[252,2949,2950,2955],{},[2861,2951,2954],{"href":2952,"rel":2953},"https:\u002F\u002Fdocs.github.com\u002Factions",[2865],"GitHub Actions 官方文档"," — CI\u002FCD 流水线",[252,2957,2958,2963],{},[2861,2959,2962],{"href":2960,"rel":2961},"https:\u002F\u002Fwww.conventionalcommits.org\u002Fzh-hans\u002F",[2865],"Conventional Commits 规范"," — 提交信息规范",[252,2965,2966,2971],{},[2861,2967,2970],{"href":2968,"rel":2969},"https:\u002F\u002Fcharity.wtf\u002F",[2865],"Charity Majors: Why I Hate Five Whys"," — Honeycomb 创始人的 SRE 文化文章集",[2973,2974,2975],"style",{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .s5tWE, html code.shiki .s5tWE{--shiki-light:#E53935;--shiki-light-font-style:italic;--shiki-default:#F07178;--shiki-default-font-style:italic;--shiki-dark:#F07178;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}",{"title":277,"searchDepth":555,"depth":566,"links":2977},[2978,2985,2991,2998,3005,3011,3018,3019],{"id":234,"depth":566,"text":235,"children":2979},[2980,2981,2982,2983,2984],{"id":239,"depth":573,"text":240},{"id":321,"depth":573,"text":322},{"id":415,"depth":573,"text":416},{"id":523,"depth":573,"text":524},{"id":539,"depth":573,"text":540},{"id":680,"depth":566,"text":681,"children":2986},[2987,2988,2989,2990],{"id":684,"depth":573,"text":685},{"id":817,"depth":573,"text":818},{"id":848,"depth":573,"text":849},{"id":884,"depth":573,"text":885},{"id":906,"depth":566,"text":907,"children":2992},[2993,2994,2995,2996,2997],{"id":910,"depth":573,"text":911},{"id":1302,"depth":573,"text":1303},{"id":1370,"depth":573,"text":1371},{"id":1383,"depth":573,"text":1384},{"id":1481,"depth":573,"text":1482},{"id":1573,"depth":566,"text":1574,"children":2999},[3000,3001,3002,3003,3004],{"id":1577,"depth":573,"text":1578},{"id":1836,"depth":573,"text":1837},{"id":1942,"depth":573,"text":1943},{"id":1973,"depth":573,"text":1974},{"id":2057,"depth":573,"text":2058},{"id":2075,"depth":566,"text":2076,"children":3006},[3007,3008,3009,3010],{"id":2079,"depth":573,"text":2080},{"id":2166,"depth":573,"text":2167},{"id":2233,"depth":573,"text":2234},{"id":2281,"depth":573,"text":2282},{"id":2388,"depth":566,"text":2389,"children":3012},[3013,3014,3015,3016,3017],{"id":2392,"depth":573,"text":2393},{"id":2464,"depth":573,"text":2465},{"id":2546,"depth":573,"text":2547},{"id":2562,"depth":573,"text":2563},{"id":2687,"depth":573,"text":2688},{"id":2808,"depth":566,"text":2808},{"id":2855,"depth":566,"text":2855},"6.4 的尾声留下一句承诺：带着\"质量已达标\"的代码进入部署上线环节。这一节兑现承诺。部署不是开发的下游，而是产品价值真正开始流动的起点——代码静静躺在仓库里时它的价值是零，只有当真实用户在真实场景中调用它，价值才被点亮。","md",null,{"date":3024},"2026-04-26",{"title":146,"description":3020},"vRDeM1Y_apoU0IGJKS1SG4dVg6oQyu4Kw56lR_add10",[3028,3030],{"title":142,"path":143,"stem":144,"description":3029,"children":-1},"经过 6.3 节的多轮迭代，我们已经把一个空的脚手架推向了功能可用的最小可行产品（Minimum Viable Product, MVP）。表面上看，主流程跑通了、UI 截图也拿得出手，但任何一位真正把代码送上过生产环境的工程师都知道：从「Demo 跑通」到「敢交付」之间，还隔着一整条质量保障链路——测试、审查、调优、门禁。这条链路的每个环节，过去由人主导、AI 辅助；从 Claude Code 普及之后，许多团队开始反过来：让 AI 主导执行，让人主导决策。",{"title":156,"path":157,"stem":158,"description":3031,"children":-1},"让 Claude 准确理解你的意图",1777395310238]