[{"data":1,"prerenderedAt":7855},["ShallowReactive",2],{"article-/topics/ai/ai-agent-security-testing-ci-credential-scan":3,"related-ai":2804,"content-query-eNiln9ZlNT":5560},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"tags":11,"category":17,"author":18,"status":19,"image":20,"body":21,"_type":1473,"_id":2799,"_source":2800,"_file":2801,"_stem":2802,"_extension":2803},"/topics/ai/ai-agent-security-testing-ci-credential-scan","ai",false,"","AI Agent Security Testing in CI: Credential Scan, Permission Audit, and Log Sanitization","在 CI/CD 流程中自动化检测 AI agent 的凭证泄露、权限过宽和日志污染问题，构建 DevSecOps 安全防线。","2026-06-15",[12,13,14,15,16],"ai-agent","security-testing","ci-cd","credential-scan","devsecops","AI Engineering","AI Agent Engineering Team","published","/images/articles/as10-featured.jpeg",{"type":22,"children":23,"toc":2708},"root",[24,33,45,55,100,109,212,216,222,229,234,244,253,286,292,300,309,342,348,353,477,486,540,606,609,615,621,629,638,799,805,811,993,1003,1008,1117,1126,1131,1237,1246,1252,1263,1266,1272,1278,1283,1294,1299,1308,1317,1325,1339,1348,1354,1360,1369,1381,1390,1396,1405,1414,1423,1429,1435,1444,1455,1461,1470,1481,1492,1500,1506,1511,1520,1523,1529,1535,1548,1559,1565,1578,1589,1595,1604,1612,1621,1627,1632,1641,1646,1655,1658,1664,1670,1683,1692,1698,1711,1722,1727,1736,1742,1747,1756,1759,1765,1771,1909,1915,1921,1930,1936,1945,1951,1956,1967,1976,1985,1988,1994,2000,2009,2015,2020,2028,2034,2043,2046,2052,2058,2172,2178,2272,2278,2357,2363,2442,2445,2451,2457,2521,2527,2592,2598,2637,2640,2646,2651,2660,2703],{"type":25,"tag":26,"props":27,"children":29},"element","h2",{"id":28},"tldr",[30],{"type":31,"value":32},"text","TL;DR",{"type":25,"tag":34,"props":35,"children":36},"p",{},[37,43],{"type":25,"tag":38,"props":39,"children":40},"strong",{},[41],{"type":31,"value":42},"本文解决的核心问题",{"type":31,"value":44},"：如何在代码提交前自动检测 AI agent 项目中的安全风险（硬编码凭证、过度授权、日志泄露敏感信息），并将其集成到 CI/CD 流水线中实现\"安全左移\"。",{"type":25,"tag":34,"props":46,"children":47},{},[48,53],{"type":25,"tag":38,"props":49,"children":50},{},[51],{"type":31,"value":52},"关键决策点",{"type":31,"value":54},"：",{"type":25,"tag":56,"props":57,"children":58},"ul",{},[59,70,80,90],{"type":25,"tag":60,"props":61,"children":62},"li",{},[63,68],{"type":25,"tag":38,"props":64,"children":65},{},[66],{"type":31,"value":67},"扫描时机",{"type":31,"value":69},"：Pre-commit Hook → Pull Request → Merge to Main → Production Deploy",{"type":25,"tag":60,"props":71,"children":72},{},[73,78],{"type":25,"tag":38,"props":74,"children":75},{},[76],{"type":31,"value":77},"工具选型",{"type":31,"value":79},"：TruffleHog（凭证扫描）+ OPA（权限审计）+ Custom Rules（日志脱敏验证）",{"type":25,"tag":60,"props":81,"children":82},{},[83,88],{"type":25,"tag":38,"props":84,"children":85},{},[86],{"type":31,"value":87},"阻断策略",{"type":31,"value":89},"：Critical 级别直接失败，High 级别需要人工审批，Medium/Low 仅警告",{"type":25,"tag":60,"props":91,"children":92},{},[93,98],{"type":25,"tag":38,"props":94,"children":95},{},[96],{"type":31,"value":97},"误报处理",{"type":31,"value":99},"：建立白名单机制 + 定期 Review + 反馈闭环优化规则",{"type":25,"tag":34,"props":101,"children":102},{},[103,108],{"type":25,"tag":38,"props":104,"children":105},{},[106],{"type":31,"value":107},"适用场景判断表",{"type":31,"value":54},{"type":25,"tag":110,"props":111,"children":112},"table",{},[113,137],{"type":25,"tag":114,"props":115,"children":116},"thead",{},[117],{"type":25,"tag":118,"props":119,"children":120},"tr",{},[121,127,132],{"type":25,"tag":122,"props":123,"children":124},"th",{},[125],{"type":31,"value":126},"场景特征",{"type":25,"tag":122,"props":128,"children":129},{},[130],{"type":31,"value":131},"推荐方案",{"type":25,"tag":122,"props":133,"children":134},{},[135],{"type":31,"value":136},"优先级",{"type":25,"tag":138,"props":139,"children":140},"tbody",{},[141,160,178,195],{"type":25,"tag":118,"props":142,"children":143},{},[144,150,155],{"type":25,"tag":145,"props":146,"children":147},"td",{},[148],{"type":31,"value":149},"初创团队，快速迭代",{"type":25,"tag":145,"props":151,"children":152},{},[153],{"type":31,"value":154},"Pre-commit Hook + TruffleHog",{"type":25,"tag":145,"props":156,"children":157},{},[158],{"type":31,"value":159},"🔴 P0",{"type":25,"tag":118,"props":161,"children":162},{},[163,168,173],{"type":25,"tag":145,"props":164,"children":165},{},[166],{"type":31,"value":167},"中型团队，多环境部署",{"type":25,"tag":145,"props":169,"children":170},{},[171],{"type":31,"value":172},"PR 扫描 + 权限基线检查",{"type":25,"tag":145,"props":174,"children":175},{},[176],{"type":31,"value":177},"🟡 P1",{"type":25,"tag":118,"props":179,"children":180},{},[181,186,191],{"type":25,"tag":145,"props":182,"children":183},{},[184],{"type":31,"value":185},"金融/医疗行业，强合规要求",{"type":25,"tag":145,"props":187,"children":188},{},[189],{"type":31,"value":190},"全链路扫描 + 人工审批 + 审计报告",{"type":25,"tag":145,"props":192,"children":193},{},[194],{"type":31,"value":159},{"type":25,"tag":118,"props":196,"children":197},{},[198,203,208],{"type":25,"tag":145,"props":199,"children":200},{},[201],{"type":31,"value":202},"开源项目，社区协作",{"type":25,"tag":145,"props":204,"children":205},{},[206],{"type":31,"value":207},"Public Repo 专用规则集 + Secret Alert",{"type":25,"tag":145,"props":209,"children":210},{},[211],{"type":31,"value":177},{"type":25,"tag":213,"props":214,"children":215},"hr",{},[],{"type":25,"tag":26,"props":217,"children":219},{"id":218},"_1-为什么需要在-ci-中进行安全测试",[220],{"type":31,"value":221},"1. 为什么需要在 CI 中进行安全测试？",{"type":25,"tag":223,"props":224,"children":226},"h3",{"id":225},"_11-传统安全测试的痛点",[227],{"type":31,"value":228},"1.1 传统安全测试的痛点",{"type":25,"tag":34,"props":230,"children":231},{},[232],{"type":31,"value":233},"在传统开发流程中，安全测试通常在以下阶段进行：",{"type":25,"tag":235,"props":236,"children":238},"pre",{"code":237},"需求 → 设计 → 开发 → 测试 → 部署 → ⚠️ 安全审计（太晚了！）\n",[239],{"type":25,"tag":240,"props":241,"children":242},"code",{"__ignoreMap":7},[243],{"type":31,"value":237},{"type":25,"tag":34,"props":245,"children":246},{},[247,252],{"type":25,"tag":38,"props":248,"children":249},{},[250],{"type":31,"value":251},"问题",{"type":31,"value":54},{"type":25,"tag":56,"props":254,"children":255},{},[256,266,276],{"type":25,"tag":60,"props":257,"children":258},{},[259,264],{"type":25,"tag":38,"props":260,"children":261},{},[262],{"type":31,"value":263},"发现晚",{"type":31,"value":265},"：安全问题在生产环境或上线前才被发现，修复成本高",{"type":25,"tag":60,"props":267,"children":268},{},[269,274],{"type":25,"tag":38,"props":270,"children":271},{},[272],{"type":31,"value":273},"责任分离",{"type":31,"value":275},"：开发人员不关注安全，安全团队不了解业务逻辑",{"type":25,"tag":60,"props":277,"children":278},{},[279,284],{"type":25,"tag":38,"props":280,"children":281},{},[282],{"type":31,"value":283},"手动操作",{"type":31,"value":285},"：依赖人工审查，容易遗漏，效率低下",{"type":25,"tag":223,"props":287,"children":289},{"id":288},"_12-devsecops-的核心理念",[290],{"type":31,"value":291},"1.2 DevSecOps 的核心理念",{"type":25,"tag":235,"props":293,"children":295},{"code":294},"需求 → 设计 → 开发 → [安全扫描] → 测试 → [安全扫描] → 部署 → [持续监控]\n         ↑              ↑                    ↑                ↑\n      Threat Model   Pre-commit           PR Check        Runtime Guard\n",[296],{"type":25,"tag":240,"props":297,"children":298},{"__ignoreMap":7},[299],{"type":31,"value":294},{"type":25,"tag":34,"props":301,"children":302},{},[303,308],{"type":25,"tag":38,"props":304,"children":305},{},[306],{"type":31,"value":307},"优势",{"type":31,"value":54},{"type":25,"tag":56,"props":310,"children":311},{},[312,322,332],{"type":25,"tag":60,"props":313,"children":314},{},[315,320],{"type":25,"tag":38,"props":316,"children":317},{},[318],{"type":31,"value":319},"左移（Shift Left）",{"type":31,"value":321},"：在开发早期发现问题，修复成本降低 10-100 倍",{"type":25,"tag":60,"props":323,"children":324},{},[325,330],{"type":25,"tag":38,"props":326,"children":327},{},[328],{"type":31,"value":329},"自动化",{"type":31,"value":331},"：每次代码变更都经过安全检查，无遗漏",{"type":25,"tag":60,"props":333,"children":334},{},[335,340],{"type":25,"tag":38,"props":336,"children":337},{},[338],{"type":31,"value":339},"文化融合",{"type":31,"value":341},"：安全成为开发流程的一部分，而非独立环节",{"type":25,"tag":223,"props":343,"children":345},{"id":344},"_13-ai-agent-项目的特殊风险",[346],{"type":31,"value":347},"1.3 AI Agent 项目的特殊风险",{"type":25,"tag":34,"props":349,"children":350},{},[351],{"type":31,"value":352},"相比传统应用，AI agent 项目面临额外的安全挑战：",{"type":25,"tag":110,"props":354,"children":355},{},[356,382],{"type":25,"tag":114,"props":357,"children":358},{},[359],{"type":25,"tag":118,"props":360,"children":361},{},[362,367,372,377],{"type":25,"tag":122,"props":363,"children":364},{},[365],{"type":31,"value":366},"风险类型",{"type":25,"tag":122,"props":368,"children":369},{},[370],{"type":31,"value":371},"传统应用",{"type":25,"tag":122,"props":373,"children":374},{},[375],{"type":31,"value":376},"AI Agent 应用",{"type":25,"tag":122,"props":378,"children":379},{},[380],{"type":31,"value":381},"差异原因",{"type":25,"tag":138,"props":383,"children":384},{},[385,408,431,454],{"type":25,"tag":118,"props":386,"children":387},{},[388,393,398,403],{"type":25,"tag":145,"props":389,"children":390},{},[391],{"type":31,"value":392},"凭证管理",{"type":25,"tag":145,"props":394,"children":395},{},[396],{"type":31,"value":397},"API Key、数据库密码",{"type":25,"tag":145,"props":399,"children":400},{},[401],{"type":31,"value":402},"LLM API Key、Vector DB 凭证、OAuth Token",{"type":25,"tag":145,"props":404,"children":405},{},[406],{"type":31,"value":407},"更多外部服务依赖",{"type":25,"tag":118,"props":409,"children":410},{},[411,416,421,426],{"type":25,"tag":145,"props":412,"children":413},{},[414],{"type":31,"value":415},"权限模型",{"type":25,"tag":145,"props":417,"children":418},{},[419],{"type":31,"value":420},"RBAC、用户角色",{"type":25,"tag":145,"props":422,"children":423},{},[424],{"type":31,"value":425},"Agent 能力边界、Tool 调用权限",{"type":25,"tag":145,"props":427,"children":428},{},[429],{"type":31,"value":430},"动态执行不可预测",{"type":25,"tag":118,"props":432,"children":433},{},[434,439,444,449],{"type":25,"tag":145,"props":435,"children":436},{},[437],{"type":31,"value":438},"数据泄露",{"type":25,"tag":145,"props":440,"children":441},{},[442],{"type":31,"value":443},"用户隐私数据",{"type":25,"tag":145,"props":445,"children":446},{},[447],{"type":31,"value":448},"Prompt 内容、RAG 检索结果、Agent 推理过程",{"type":25,"tag":145,"props":450,"children":451},{},[452],{"type":31,"value":453},"更多中间状态暴露",{"type":25,"tag":118,"props":455,"children":456},{},[457,462,467,472],{"type":25,"tag":145,"props":458,"children":459},{},[460],{"type":31,"value":461},"日志污染",{"type":25,"tag":145,"props":463,"children":464},{},[465],{"type":31,"value":466},"错误堆栈、请求参数",{"type":25,"tag":145,"props":468,"children":469},{},[470],{"type":31,"value":471},"完整对话历史、思维链（CoT）、工具调用参数",{"type":25,"tag":145,"props":473,"children":474},{},[475],{"type":31,"value":476},"更详细的调试信息",{"type":25,"tag":34,"props":478,"children":479},{},[480,485],{"type":25,"tag":38,"props":481,"children":482},{},[483],{"type":31,"value":484},"真实案例",{"type":31,"value":54},{"type":25,"tag":487,"props":488,"children":489},"blockquote",{},[490,498],{"type":25,"tag":34,"props":491,"children":492},{},[493],{"type":25,"tag":38,"props":494,"children":495},{},[496],{"type":31,"value":497},"案例 1：GitHub Copilot 凭证泄露事件（2023）",{"type":25,"tag":56,"props":499,"children":500},{},[501,510,520,530],{"type":25,"tag":60,"props":502,"children":503},{},[504,508],{"type":25,"tag":38,"props":505,"children":506},{},[507],{"type":31,"value":251},{"type":31,"value":509},"：某开发者在示例代码中硬编码了 OpenAI API Key",{"type":25,"tag":60,"props":511,"children":512},{},[513,518],{"type":25,"tag":38,"props":514,"children":515},{},[516],{"type":31,"value":517},"传播",{"type":31,"value":519},"：代码被推送到公共仓库，被 TruffleHog 扫描发现",{"type":25,"tag":60,"props":521,"children":522},{},[523,528],{"type":25,"tag":38,"props":524,"children":525},{},[526],{"type":31,"value":527},"损失",{"type":31,"value":529},"：API Key 被恶意使用，产生 $2,000+ 费用",{"type":25,"tag":60,"props":531,"children":532},{},[533,538],{"type":25,"tag":38,"props":534,"children":535},{},[536],{"type":31,"value":537},"教训",{"type":31,"value":539},"：必须在 Pre-commit 阶段拦截",{"type":25,"tag":487,"props":541,"children":542},{},[543,551],{"type":25,"tag":34,"props":544,"children":545},{},[546],{"type":25,"tag":38,"props":547,"children":548},{},[549],{"type":31,"value":550},"案例 2：LangChain Agent 权限过宽（2024）",{"type":25,"tag":56,"props":552,"children":553},{},[554,577,587,597],{"type":25,"tag":60,"props":555,"children":556},{},[557,561,563,569,571],{"type":25,"tag":38,"props":558,"children":559},{},[560],{"type":31,"value":251},{"type":31,"value":562},"：Agent 被授予 ",{"type":25,"tag":240,"props":564,"children":566},{"className":565},[],[567],{"type":31,"value":568},"filesystem:read_write",{"type":31,"value":570}," 权限，但实际只需要 ",{"type":25,"tag":240,"props":572,"children":574},{"className":573},[],[575],{"type":31,"value":576},"read",{"type":25,"tag":60,"props":578,"children":579},{},[580,585],{"type":25,"tag":38,"props":581,"children":582},{},[583],{"type":31,"value":584},"风险",{"type":31,"value":586},"：攻击者通过 Prompt Injection 诱导 Agent 删除文件",{"type":25,"tag":60,"props":588,"children":589},{},[590,595],{"type":25,"tag":38,"props":591,"children":592},{},[593],{"type":31,"value":594},"发现",{"type":31,"value":596},"：生产环境发生数据丢失后才被发现",{"type":25,"tag":60,"props":598,"children":599},{},[600,604],{"type":25,"tag":38,"props":601,"children":602},{},[603],{"type":31,"value":537},{"type":31,"value":605},"：应在 CI 中验证权限最小化原则",{"type":25,"tag":213,"props":607,"children":608},{},[],{"type":25,"tag":26,"props":610,"children":612},{"id":611},"_2-ci-安全测试架构设计",[613],{"type":31,"value":614},"2. CI 安全测试架构设计",{"type":25,"tag":223,"props":616,"children":618},{"id":617},"_21-四层防御体系",[619],{"type":31,"value":620},"2.1 四层防御体系",{"type":25,"tag":235,"props":622,"children":624},{"code":623},"┌─────────────────────────────────────────────┐\n│ Layer 4: Production Runtime Monitoring      │ ← 运行时监控（不在本文范围）\n├─────────────────────────────────────────────┤\n│ Layer 3: Deployment Gate                    │ ← 部署前最终检查\n├─────────────────────────────────────────────┤\n│ Layer 2: Pull Request Checks                │ ← PR 合并前强制扫描\n├─────────────────────────────────────────────┤\n│ Layer 1: Pre-commit Hooks                   │ ← 本地提交前即时反馈\n└─────────────────────────────────────────────┘\n",[625],{"type":25,"tag":240,"props":626,"children":627},{"__ignoreMap":7},[628],{"type":31,"value":623},{"type":25,"tag":34,"props":630,"children":631},{},[632,637],{"type":25,"tag":38,"props":633,"children":634},{},[635],{"type":31,"value":636},"各层职责",{"type":31,"value":54},{"type":25,"tag":110,"props":639,"children":640},{},[641,672],{"type":25,"tag":114,"props":642,"children":643},{},[644],{"type":25,"tag":118,"props":645,"children":646},{},[647,652,657,662,667],{"type":25,"tag":122,"props":648,"children":649},{},[650],{"type":31,"value":651},"层级",{"type":25,"tag":122,"props":653,"children":654},{},[655],{"type":31,"value":656},"触发时机",{"type":25,"tag":122,"props":658,"children":659},{},[660],{"type":31,"value":661},"扫描内容",{"type":25,"tag":122,"props":663,"children":664},{},[665],{"type":31,"value":666},"响应时间",{"type":25,"tag":122,"props":668,"children":669},{},[670],{"type":31,"value":671},"阻断力度",{"type":25,"tag":138,"props":673,"children":674},{},[675,715,743,771],{"type":25,"tag":118,"props":676,"children":677},{},[678,683,692,697,702],{"type":25,"tag":145,"props":679,"children":680},{},[681],{"type":31,"value":682},"Layer 1",{"type":25,"tag":145,"props":684,"children":685},{},[686],{"type":25,"tag":240,"props":687,"children":689},{"className":688},[],[690],{"type":31,"value":691},"git commit",{"type":25,"tag":145,"props":693,"children":694},{},[695],{"type":31,"value":696},"硬编码凭证、敏感文件",{"type":25,"tag":145,"props":698,"children":699},{},[700],{"type":31,"value":701},"\u003C 5s",{"type":25,"tag":145,"props":703,"children":704},{},[705,707,713],{"type":31,"value":706},"可选（可 ",{"type":25,"tag":240,"props":708,"children":710},{"className":709},[],[711],{"type":31,"value":712},"--no-verify",{"type":31,"value":714}," 跳过）",{"type":25,"tag":118,"props":716,"children":717},{},[718,723,728,733,738],{"type":25,"tag":145,"props":719,"children":720},{},[721],{"type":31,"value":722},"Layer 2",{"type":25,"tag":145,"props":724,"children":725},{},[726],{"type":31,"value":727},"PR Create/Update",{"type":25,"tag":145,"props":729,"children":730},{},[731],{"type":31,"value":732},"凭证 + 权限 + 日志规则",{"type":25,"tag":145,"props":734,"children":735},{},[736],{"type":31,"value":737},"1-3 min",{"type":25,"tag":145,"props":739,"children":740},{},[741],{"type":31,"value":742},"强制（必须通过才能合并）",{"type":25,"tag":118,"props":744,"children":745},{},[746,751,756,761,766],{"type":25,"tag":145,"props":747,"children":748},{},[749],{"type":31,"value":750},"Layer 3",{"type":25,"tag":145,"props":752,"children":753},{},[754],{"type":31,"value":755},"Merge to Main",{"type":25,"tag":145,"props":757,"children":758},{},[759],{"type":31,"value":760},"全面扫描 + 依赖漏洞",{"type":25,"tag":145,"props":762,"children":763},{},[764],{"type":31,"value":765},"3-5 min",{"type":25,"tag":145,"props":767,"children":768},{},[769],{"type":31,"value":770},"强制（必须通过才能部署）",{"type":25,"tag":118,"props":772,"children":773},{},[774,779,784,789,794],{"type":25,"tag":145,"props":775,"children":776},{},[777],{"type":31,"value":778},"Layer 4",{"type":25,"tag":145,"props":780,"children":781},{},[782],{"type":31,"value":783},"Runtime",{"type":25,"tag":145,"props":785,"children":786},{},[787],{"type":31,"value":788},"异常行为检测",{"type":25,"tag":145,"props":790,"children":791},{},[792],{"type":31,"value":793},"实时",{"type":25,"tag":145,"props":795,"children":796},{},[797],{"type":31,"value":798},"告警 + 自动降级",{"type":25,"tag":223,"props":800,"children":802},{"id":801},"_22-技术栈选型",[803],{"type":31,"value":804},"2.2 技术栈选型",{"type":25,"tag":806,"props":807,"children":809},"h4",{"id":808},"凭证扫描工具对比",[810],{"type":31,"value":808},{"type":25,"tag":110,"props":812,"children":813},{},[814,850],{"type":25,"tag":114,"props":815,"children":816},{},[817],{"type":25,"tag":118,"props":818,"children":819},{},[820,825,830,835,840,845],{"type":25,"tag":122,"props":821,"children":822},{},[823],{"type":31,"value":824},"工具",{"type":25,"tag":122,"props":826,"children":827},{},[828],{"type":31,"value":829},"语言",{"type":25,"tag":122,"props":831,"children":832},{},[833],{"type":31,"value":834},"检测能力",{"type":25,"tag":122,"props":836,"children":837},{},[838],{"type":31,"value":839},"速度",{"type":25,"tag":122,"props":841,"children":842},{},[843],{"type":31,"value":844},"误报率",{"type":25,"tag":122,"props":846,"children":847},{},[848],{"type":31,"value":849},"推荐场景",{"type":25,"tag":138,"props":851,"children":852},{},[853,889,924,959],{"type":25,"tag":118,"props":854,"children":855},{},[856,864,869,874,879,884],{"type":25,"tag":145,"props":857,"children":858},{},[859],{"type":25,"tag":38,"props":860,"children":861},{},[862],{"type":31,"value":863},"TruffleHog",{"type":25,"tag":145,"props":865,"children":866},{},[867],{"type":31,"value":868},"Go",{"type":25,"tag":145,"props":870,"children":871},{},[872],{"type":31,"value":873},"700+ 规则，支持 Git 历史",{"type":25,"tag":145,"props":875,"children":876},{},[877],{"type":31,"value":878},"⭐⭐⭐⭐",{"type":25,"tag":145,"props":880,"children":881},{},[882],{"type":31,"value":883},"低",{"type":25,"tag":145,"props":885,"children":886},{},[887],{"type":31,"value":888},"🔥 首选",{"type":25,"tag":118,"props":890,"children":891},{},[892,900,904,909,914,919],{"type":25,"tag":145,"props":893,"children":894},{},[895],{"type":25,"tag":38,"props":896,"children":897},{},[898],{"type":31,"value":899},"GitLeaks",{"type":25,"tag":145,"props":901,"children":902},{},[903],{"type":31,"value":868},{"type":25,"tag":145,"props":905,"children":906},{},[907],{"type":31,"value":908},"通用密钥模式",{"type":25,"tag":145,"props":910,"children":911},{},[912],{"type":31,"value":913},"⭐⭐⭐⭐⭐",{"type":25,"tag":145,"props":915,"children":916},{},[917],{"type":31,"value":918},"中",{"type":25,"tag":145,"props":920,"children":921},{},[922],{"type":31,"value":923},"快速扫描",{"type":25,"tag":118,"props":925,"children":926},{},[927,935,940,945,950,954],{"type":25,"tag":145,"props":928,"children":929},{},[930],{"type":25,"tag":38,"props":931,"children":932},{},[933],{"type":31,"value":934},"Detect-Secrets",{"type":25,"tag":145,"props":936,"children":937},{},[938],{"type":31,"value":939},"Python",{"type":25,"tag":145,"props":941,"children":942},{},[943],{"type":31,"value":944},"Yelp 开源，可定制",{"type":25,"tag":145,"props":946,"children":947},{},[948],{"type":31,"value":949},"⭐⭐⭐",{"type":25,"tag":145,"props":951,"children":952},{},[953],{"type":31,"value":883},{"type":25,"tag":145,"props":955,"children":956},{},[957],{"type":31,"value":958},"Python 项目",{"type":25,"tag":118,"props":960,"children":961},{},[962,970,975,980,984,988],{"type":25,"tag":145,"props":963,"children":964},{},[965],{"type":25,"tag":38,"props":966,"children":967},{},[968],{"type":31,"value":969},"AWS GitSecrets",{"type":25,"tag":145,"props":971,"children":972},{},[973],{"type":31,"value":974},"Shell",{"type":25,"tag":145,"props":976,"children":977},{},[978],{"type":31,"value":979},"AWS 专用",{"type":25,"tag":145,"props":981,"children":982},{},[983],{"type":31,"value":878},{"type":25,"tag":145,"props":985,"children":986},{},[987],{"type":31,"value":883},{"type":25,"tag":145,"props":989,"children":990},{},[991],{"type":31,"value":992},"AWS 生态",{"type":25,"tag":34,"props":994,"children":995},{},[996,1001],{"type":25,"tag":38,"props":997,"children":998},{},[999],{"type":31,"value":1000},"推荐",{"type":31,"value":1002},"：TruffleHog（功能最全面，支持深度 Git 历史扫描）",{"type":25,"tag":806,"props":1004,"children":1006},{"id":1005},"权限审计工具",[1007],{"type":31,"value":1005},{"type":25,"tag":110,"props":1009,"children":1010},{},[1011,1036],{"type":25,"tag":114,"props":1012,"children":1013},{},[1014],{"type":25,"tag":118,"props":1015,"children":1016},{},[1017,1021,1026,1031],{"type":25,"tag":122,"props":1018,"children":1019},{},[1020],{"type":31,"value":824},{"type":25,"tag":122,"props":1022,"children":1023},{},[1024],{"type":31,"value":1025},"适用场景",{"type":25,"tag":122,"props":1027,"children":1028},{},[1029],{"type":31,"value":1030},"策略语言",{"type":25,"tag":122,"props":1032,"children":1033},{},[1034],{"type":31,"value":1035},"学习曲线",{"type":25,"tag":138,"props":1037,"children":1038},{},[1039,1065,1091],{"type":25,"tag":118,"props":1040,"children":1041},{},[1042,1050,1055,1060],{"type":25,"tag":145,"props":1043,"children":1044},{},[1045],{"type":25,"tag":38,"props":1046,"children":1047},{},[1048],{"type":31,"value":1049},"OPA (Open Policy Agent)",{"type":25,"tag":145,"props":1051,"children":1052},{},[1053],{"type":31,"value":1054},"通用权限策略",{"type":25,"tag":145,"props":1056,"children":1057},{},[1058],{"type":31,"value":1059},"Rego",{"type":25,"tag":145,"props":1061,"children":1062},{},[1063],{"type":31,"value":1064},"中等",{"type":25,"tag":118,"props":1066,"children":1067},{},[1068,1076,1081,1086],{"type":25,"tag":145,"props":1069,"children":1070},{},[1071],{"type":25,"tag":38,"props":1072,"children":1073},{},[1074],{"type":31,"value":1075},"Cedar (AWS)",{"type":25,"tag":145,"props":1077,"children":1078},{},[1079],{"type":31,"value":1080},"AWS IAM 策略",{"type":25,"tag":145,"props":1082,"children":1083},{},[1084],{"type":31,"value":1085},"Cedar",{"type":25,"tag":145,"props":1087,"children":1088},{},[1089],{"type":31,"value":1090},"较陡",{"type":25,"tag":118,"props":1092,"children":1093},{},[1094,1102,1107,1112],{"type":25,"tag":145,"props":1095,"children":1096},{},[1097],{"type":25,"tag":38,"props":1098,"children":1099},{},[1100],{"type":31,"value":1101},"Custom JSON Schema",{"type":25,"tag":145,"props":1103,"children":1104},{},[1105],{"type":31,"value":1106},"简单权限模型",{"type":25,"tag":145,"props":1108,"children":1109},{},[1110],{"type":31,"value":1111},"JSON",{"type":25,"tag":145,"props":1113,"children":1114},{},[1115],{"type":31,"value":1116},"简单",{"type":25,"tag":34,"props":1118,"children":1119},{},[1120,1124],{"type":25,"tag":38,"props":1121,"children":1122},{},[1123],{"type":31,"value":1000},{"type":31,"value":1125},"：OPA（灵活性强，社区活跃）",{"type":25,"tag":806,"props":1127,"children":1129},{"id":1128},"日志脱敏验证",[1130],{"type":31,"value":1128},{"type":25,"tag":110,"props":1132,"children":1133},{},[1134,1160],{"type":25,"tag":114,"props":1135,"children":1136},{},[1137],{"type":25,"tag":118,"props":1138,"children":1139},{},[1140,1145,1150,1155],{"type":25,"tag":122,"props":1141,"children":1142},{},[1143],{"type":31,"value":1144},"方法",{"type":25,"tag":122,"props":1146,"children":1147},{},[1148],{"type":31,"value":1149},"实现方式",{"type":25,"tag":122,"props":1151,"children":1152},{},[1153],{"type":31,"value":1154},"覆盖度",{"type":25,"tag":122,"props":1156,"children":1157},{},[1158],{"type":31,"value":1159},"维护成本",{"type":25,"tag":138,"props":1161,"children":1162},{},[1163,1187,1212],{"type":25,"tag":118,"props":1164,"children":1165},{},[1166,1174,1179,1183],{"type":25,"tag":145,"props":1167,"children":1168},{},[1169],{"type":25,"tag":38,"props":1170,"children":1171},{},[1172],{"type":31,"value":1173},"正则表达式匹配",{"type":25,"tag":145,"props":1175,"children":1176},{},[1177],{"type":31,"value":1178},"自定义规则文件",{"type":25,"tag":145,"props":1180,"children":1181},{},[1182],{"type":31,"value":1064},{"type":25,"tag":145,"props":1184,"children":1185},{},[1186],{"type":31,"value":883},{"type":25,"tag":118,"props":1188,"children":1189},{},[1190,1198,1203,1208],{"type":25,"tag":145,"props":1191,"children":1192},{},[1193],{"type":25,"tag":38,"props":1194,"children":1195},{},[1196],{"type":31,"value":1197},"AST 分析",{"type":25,"tag":145,"props":1199,"children":1200},{},[1201],{"type":31,"value":1202},"解析代码结构，检测日志语句",{"type":25,"tag":145,"props":1204,"children":1205},{},[1206],{"type":31,"value":1207},"高",{"type":25,"tag":145,"props":1209,"children":1210},{},[1211],{"type":31,"value":918},{"type":25,"tag":118,"props":1213,"children":1214},{},[1215,1223,1228,1233],{"type":25,"tag":145,"props":1216,"children":1217},{},[1218],{"type":25,"tag":38,"props":1219,"children":1220},{},[1221],{"type":31,"value":1222},"运行时插桩",{"type":25,"tag":145,"props":1224,"children":1225},{},[1226],{"type":31,"value":1227},"注入脱敏检查代码",{"type":25,"tag":145,"props":1229,"children":1230},{},[1231],{"type":31,"value":1232},"最高",{"type":25,"tag":145,"props":1234,"children":1235},{},[1236],{"type":31,"value":1207},{"type":25,"tag":34,"props":1238,"children":1239},{},[1240,1244],{"type":25,"tag":38,"props":1241,"children":1242},{},[1243],{"type":31,"value":1000},{"type":31,"value":1245},"：正则表达式 + AST 混合方案（平衡覆盖度和成本）",{"type":25,"tag":223,"props":1247,"children":1249},{"id":1248},"_23-ci-流水线集成示例github-actions",[1250],{"type":31,"value":1251},"2.3 CI 流水线集成示例（GitHub Actions）",{"type":25,"tag":235,"props":1253,"children":1258},{"code":1254,"language":1255,"meta":7,"className":1256},"# .github/workflows/security-scan.yml\nname: Security Scan\n\non:\n  pull_request:\n    branches: [main]\n  push:\n    branches: [main]\n\njobs:\n  # Layer 1: Pre-commit 已在本地执行，此处跳过\n  \n  # Layer 2: PR 扫描\n  credential-scan:\n    name: Credential Scan\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          fetch-depth: 0  # 完整 Git 历史\n      \n      - name: Run TruffleHog\n        uses: trufflesecurity/trufflehog@main\n        with:\n          extra_args: --only-verified --fail\n    \n  permission-audit:\n    name: Permission Audit\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      \n      - name: Install OPA\n        run: |\n          curl -L -o opa https://openpolicyagent.org/downloads/v0.60.0/opa_linux_amd64_static\n          chmod +x opa\n      \n      - name: Run Permission Check\n        run: |\n          ./opa eval --data policies/ --input agent-permissions.json \\\n            \"data.main.violations\" --format pretty\n  \n  log-sanitization-check:\n    name: Log Sanitization Check\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      \n      - name: Check for Sensitive Data in Logs\n        run: |\n          python scripts/check_log_sanitization.py \\\n            --source-dir src/ \\\n            --rules config/log-rules.json\n  \n  # Layer 3: 部署前综合检查\n  deployment-gate:\n    name: Deployment Gate\n    needs: [credential-scan, permission-audit, log-sanitization-check]\n    if: github.ref == 'refs/heads/main'\n    runs-on: ubuntu-latest\n    steps:\n      - name: Check All Scans Passed\n        run: echo \"All security checks passed!\"\n      \n      - name: Generate Security Report\n        run: |\n          python scripts/generate_security_report.py \\\n            --output reports/security-$(date +%Y%m%d).md\n","yaml",[1257],"language-yaml",[1259],{"type":25,"tag":240,"props":1260,"children":1261},{"__ignoreMap":7},[1262],{"type":31,"value":1254},{"type":25,"tag":213,"props":1264,"children":1265},{},[],{"type":25,"tag":26,"props":1267,"children":1269},{"id":1268},"_3-凭证扫描实战",[1270],{"type":31,"value":1271},"3. 凭证扫描实战",{"type":25,"tag":223,"props":1273,"children":1275},{"id":1274},"_31-trufflehog-配置",[1276],{"type":31,"value":1277},"3.1 TruffleHog 配置",{"type":25,"tag":806,"props":1279,"children":1281},{"id":1280},"安装",[1282],{"type":31,"value":1280},{"type":25,"tag":235,"props":1284,"children":1289},{"code":1285,"language":1286,"meta":7,"className":1287},"# macOS\nbrew install trufflehog\n\n# Linux\ncurl -sSfL https://raw.githubusercontent.com/trufflesecurity/trufflehog/main/scripts/install.sh | sh -s -- -b /usr/local/bin\n\n# Docker\ndocker run --rm -v \"$(pwd):/work\" trufflesecurity/trufflehog:latest git file:///work\n","bash",[1288],"language-bash",[1290],{"type":25,"tag":240,"props":1291,"children":1292},{"__ignoreMap":7},[1293],{"type":31,"value":1285},{"type":25,"tag":806,"props":1295,"children":1297},{"id":1296},"基础扫描",[1298],{"type":31,"value":1296},{"type":25,"tag":235,"props":1300,"children":1303},{"code":1301,"language":1286,"meta":7,"className":1302},"# 扫描当前仓库（包括 Git 历史）\ntrufflehog git file://. --only-verified\n\n# 扫描特定分支\ntrufflehog git https://github.com/org/repo.git --branch=main --only-verified\n\n# 扫描文件系统（不包含 Git 历史）\ntrufflehog filesystem /path/to/repo --only-verified\n",[1288],[1304],{"type":25,"tag":240,"props":1305,"children":1306},{"__ignoreMap":7},[1307],{"type":31,"value":1301},{"type":25,"tag":34,"props":1309,"children":1310},{},[1311,1316],{"type":25,"tag":38,"props":1312,"children":1313},{},[1314],{"type":31,"value":1315},"输出示例",{"type":31,"value":54},{"type":25,"tag":235,"props":1318,"children":1320},{"code":1319},"🐷 🔑  Found Verified Secret\nDetector: OpenAI\nRaw: sk-proj-abc123...xyz789\nRedacted: sk-proj-abc***xyz789\nFile: src/config/openai.ts\nLine: 5\nCommit: a1b2c3d4e5f6\nAuthor: John Doe \u003Cjohn@example.com>\nDate: 2024-01-15 10:30:00 +0000 UTC\n",[1321],{"type":25,"tag":240,"props":1322,"children":1323},{"__ignoreMap":7},[1324],{"type":31,"value":1319},{"type":25,"tag":806,"props":1326,"children":1328},{"id":1327},"配置文件trufflehogyaml",[1329,1331,1337],{"type":31,"value":1330},"配置文件（",{"type":25,"tag":240,"props":1332,"children":1334},{"className":1333},[],[1335],{"type":31,"value":1336},".trufflehog.yaml",{"type":31,"value":1338},"）",{"type":25,"tag":235,"props":1340,"children":1343},{"code":1341,"language":1255,"meta":7,"className":1342},"# 排除不需要扫描的路径\nexclude_paths:\n  - node_modules/\n  - dist/\n  - \"*.test.ts\"\n  - docs/examples/  # 示例代码可能包含假密钥\n\n# 自定义规则\ncustom_detectors:\n  - name: \"Custom AI Platform API Key\"\n    keywords:\n      - \"ai-platform-key\"\n    regex:\n      - 'ai-platform-key[\"\\s:=]+([A-Za-z0-9]{32})'\n    secret_group: 1\n\n# 忽略已知误报\nignore_rules:\n  - \"generic-api-key\"  # 过于宽泛，误报多\n",[1257],[1344],{"type":25,"tag":240,"props":1345,"children":1346},{"__ignoreMap":7},[1347],{"type":31,"value":1341},{"type":25,"tag":223,"props":1349,"children":1351},{"id":1350},"_32-pre-commit-hook-集成",[1352],{"type":31,"value":1353},"3.2 Pre-commit Hook 集成",{"type":25,"tag":806,"props":1355,"children":1357},{"id":1356},"安装-pre-commit",[1358],{"type":31,"value":1359},"安装 Pre-commit",{"type":25,"tag":235,"props":1361,"children":1364},{"code":1362,"language":1286,"meta":7,"className":1363},"pip install pre-commit\n",[1288],[1365],{"type":25,"tag":240,"props":1366,"children":1367},{"__ignoreMap":7},[1368],{"type":31,"value":1362},{"type":25,"tag":806,"props":1370,"children":1372},{"id":1371},"配置-pre-commit-configyaml",[1373,1375],{"type":31,"value":1374},"配置 ",{"type":25,"tag":240,"props":1376,"children":1378},{"className":1377},[],[1379],{"type":31,"value":1380},".pre-commit-config.yaml",{"type":25,"tag":235,"props":1382,"children":1385},{"code":1383,"language":1255,"meta":7,"className":1384},"repos:\n  - repo: https://github.com/trufflesecurity/trufflehog\n    rev: v3.67.0\n    hooks:\n      - id: trufflehog\n        name: TruffleHog Credential Scan\n        args: [\"git\", \"file://.\", \"--only-verified\", \"--fail\"]\n        stages: [commit]\n  \n  - repo: local\n    hooks:\n      - id: check-env-template\n        name: Check .env Template\n        entry: bash -c 'grep -q \"YOUR_API_KEY_HERE\" .env.example && echo \"⚠️  .env.example 包含占位符，请替换为实际说明\"'\n        language: system\n        files: \\.env\\.example$\n",[1257],[1386],{"type":25,"tag":240,"props":1387,"children":1388},{"__ignoreMap":7},[1389],{"type":31,"value":1383},{"type":25,"tag":806,"props":1391,"children":1393},{"id":1392},"启用-hook",[1394],{"type":31,"value":1395},"启用 Hook",{"type":25,"tag":235,"props":1397,"children":1400},{"code":1398,"language":1286,"meta":7,"className":1399},"pre-commit install\npre-commit install --hook-type pre-push  # 可选：推送时也扫描\n",[1288],[1401],{"type":25,"tag":240,"props":1402,"children":1403},{"__ignoreMap":7},[1404],{"type":31,"value":1398},{"type":25,"tag":34,"props":1406,"children":1407},{},[1408,1413],{"type":25,"tag":38,"props":1409,"children":1410},{},[1411],{"type":31,"value":1412},"效果",{"type":31,"value":54},{"type":25,"tag":235,"props":1415,"children":1418},{"code":1416,"language":1286,"meta":7,"className":1417},"$ git commit -m \"Add OpenAI integration\"\nTruffleHog Credential Scan...........................Failed\n- hook id: trufflehog\n- exit code: 1\n\n🐷 🔑  Found Verified Secret\nDetector: OpenAI\nFile: src/agents/customer-support.ts\nLine: 12\n\n❌ Commit blocked! Please remove the hardcoded API key.\n💡 Tip: Use environment variables or a secret manager.\n",[1288],[1419],{"type":25,"tag":240,"props":1420,"children":1421},{"__ignoreMap":7},[1422],{"type":31,"value":1416},{"type":25,"tag":223,"props":1424,"children":1426},{"id":1425},"_33-常见误报处理",[1427],{"type":31,"value":1428},"3.3 常见误报处理",{"type":25,"tag":806,"props":1430,"children":1432},{"id":1431},"误报类型-1测试用例中的假密钥",[1433],{"type":31,"value":1434},"误报类型 1：测试用例中的假密钥",{"type":25,"tag":34,"props":1436,"children":1437},{},[1438,1442],{"type":25,"tag":38,"props":1439,"children":1440},{},[1441],{"type":31,"value":251},{"type":31,"value":1443},"：测试代码中包含格式正确但无效的密钥",{"type":25,"tag":235,"props":1445,"children":1450},{"code":1446,"language":1447,"meta":7,"className":1448},"// ❌ 会被检测为真实密钥\nconst testApiKey = \"sk-test-1234567890abcdef\";\n\n// ✅ 解决方案 1：使用明显假的值\nconst testApiKey = \"sk-test-FAKE-KEY-FOR-TESTING\";\n\n// ✅ 解决方案 2：添加到白名单\n// .trufflehog.yaml\nexclude_paths:\n  - \"**/*.test.ts\"\n  - \"**/*.spec.ts\"\n","typescript",[1449],"language-typescript",[1451],{"type":25,"tag":240,"props":1452,"children":1453},{"__ignoreMap":7},[1454],{"type":31,"value":1446},{"type":25,"tag":806,"props":1456,"children":1458},{"id":1457},"误报类型-2文档中的示例代码",[1459],{"type":31,"value":1460},"误报类型 2：文档中的示例代码",{"type":25,"tag":34,"props":1462,"children":1463},{},[1464,1468],{"type":25,"tag":38,"props":1465,"children":1466},{},[1467],{"type":31,"value":251},{"type":31,"value":1469},"：README 或教程中包含示例密钥",{"type":25,"tag":235,"props":1471,"children":1476},{"code":1472,"language":1473,"meta":7,"className":1474},"\u003C!-- ❌ 可能被扫描器捕获 -->\n```ts\nconst apiKey = \"sk-proj-abc123xyz789\";\n","markdown",[1475],"language-markdown",[1477],{"type":25,"tag":240,"props":1478,"children":1479},{"__ignoreMap":7},[1480],{"type":31,"value":1472},{"type":25,"tag":235,"props":1482,"children":1487},{"code":1483,"language":1484,"meta":7,"className":1485},"const apiKey = process.env.OPENAI_API_KEY; // 从环境变量读取\n","ts",[1486],"language-ts",[1488],{"type":25,"tag":240,"props":1489,"children":1490},{"__ignoreMap":7},[1491],{"type":31,"value":1483},{"type":25,"tag":235,"props":1493,"children":1495},{"code":1494},"\n#### 误报类型 3：环境变量默认值\n\n**问题**：代码中提供默认值用于本地开发\n\n```typescript\n// ❌ 硬编码默认值\nconst apiKey = process.env.API_KEY || \"default-dev-key-12345\";\n\n// ✅ 解决方案：抛出错误提示配置\nconst apiKey = process.env.API_KEY;\nif (!apiKey) {\n  throw new Error(\"API_KEY environment variable is not set\");\n}\n",[1496],{"type":25,"tag":240,"props":1497,"children":1498},{"__ignoreMap":7},[1499],{"type":31,"value":1494},{"type":25,"tag":223,"props":1501,"children":1503},{"id":1502},"_34-扫描性能优化",[1504],{"type":31,"value":1505},"3.4 扫描性能优化",{"type":25,"tag":34,"props":1507,"children":1508},{},[1509],{"type":31,"value":1510},"对于大型仓库，完整 Git 历史扫描可能很慢：",{"type":25,"tag":235,"props":1512,"children":1515},{"code":1513,"language":1286,"meta":7,"className":1514},"# 优化策略 1：只扫描最近 N 次提交\ntrufflehog git file://. --max_depth=100 --only-verified\n\n# 优化策略 2：增量扫描（仅扫描变更文件）\ngit diff --name-only HEAD~1 HEAD | xargs trufflehog filesystem --only-verified\n\n# 优化策略 3：缓存扫描结果\n# 使用 GitHub Actions cache\n- uses: actions/cache@v3\n  with:\n    path: ~/.cache/trufflehog\n    key: trufflehog-${{ hashFiles('**/*.ts', '**/*.js') }}\n",[1288],[1516],{"type":25,"tag":240,"props":1517,"children":1518},{"__ignoreMap":7},[1519],{"type":31,"value":1513},{"type":25,"tag":213,"props":1521,"children":1522},{},[],{"type":25,"tag":26,"props":1524,"children":1526},{"id":1525},"_4-权限审计实战",[1527],{"type":31,"value":1528},"4. 权限审计实战",{"type":25,"tag":223,"props":1530,"children":1532},{"id":1531},"_41-agent-权限模型定义",[1533],{"type":31,"value":1534},"4.1 Agent 权限模型定义",{"type":25,"tag":806,"props":1536,"children":1538},{"id":1537},"权限声明文件agent-permissionsjson",[1539,1541,1547],{"type":31,"value":1540},"权限声明文件（",{"type":25,"tag":240,"props":1542,"children":1544},{"className":1543},[],[1545],{"type":31,"value":1546},"agent-permissions.json",{"type":31,"value":1338},{"type":25,"tag":235,"props":1549,"children":1554},{"code":1550,"language":1551,"meta":7,"className":1552},"{\n  \"agent_id\": \"customer-support-agent\",\n  \"version\": \"1.2.0\",\n  \"permissions\": {\n    \"tools\": [\n      {\n        \"tool_name\": \"database_query\",\n        \"allowed_operations\": [\"SELECT\"],\n        \"denied_operations\": [\"INSERT\", \"UPDATE\", \"DELETE\", \"DROP\"],\n        \"max_rows_returned\": 100,\n        \"allowed_tables\": [\"customers\", \"orders\", \"products\"],\n        \"denied_tables\": [\"users_passwords\", \"payment_details\"]\n      },\n      {\n        \"tool_name\": \"email_sender\",\n        \"allowed_recipients_pattern\": \"^.*@company\\\\.com$\",\n        \"max_emails_per_hour\": 50,\n        \"require_approval_for_external\": true\n      },\n      {\n        \"tool_name\": \"file_system\",\n        \"allowed_paths\": [\"/tmp/agent-workspace/*\"],\n        \"denied_paths\": [\"/etc/*\", \"/home/*\", \"/var/log/*\"],\n        \"allowed_operations\": [\"read\", \"write\"],\n        \"denied_operations\": [\"delete\", \"chmod\", \"chown\"]\n      }\n    ],\n    \"llm_access\": {\n      \"allowed_models\": [\"gpt-4-turbo\", \"gpt-3.5-turbo\"],\n      \"denied_models\": [\"gpt-4-all\"],\n      \"max_tokens_per_request\": 4000,\n      \"rate_limit_rpm\": 60\n    },\n    \"network\": {\n      \"allowed_domains\": [\"api.company.com\", \"docs.company.com\"],\n      \"denied_domains\": [\"*\"],\n      \"allowed_protocols\": [\"https\"],\n      \"denied_protocols\": [\"http\", \"ftp\"]\n    }\n  }\n}\n","json",[1553],"language-json",[1555],{"type":25,"tag":240,"props":1556,"children":1557},{"__ignoreMap":7},[1558],{"type":31,"value":1550},{"type":25,"tag":223,"props":1560,"children":1562},{"id":1561},"_42-opa-策略编写",[1563],{"type":31,"value":1564},"4.2 OPA 策略编写",{"type":25,"tag":806,"props":1566,"children":1568},{"id":1567},"策略文件policiesagent-permissionsrego",[1569,1571,1577],{"type":31,"value":1570},"策略文件（",{"type":25,"tag":240,"props":1572,"children":1574},{"className":1573},[],[1575],{"type":31,"value":1576},"policies/agent-permissions.rego",{"type":31,"value":1338},{"type":25,"tag":235,"props":1579,"children":1584},{"code":1580,"language":1581,"meta":7,"className":1582},"package main\n\nimport future.keywords.if\nimport future.keywords.in\n\n# 默认无违规\nviolations := []\n\n# 规则 1：检查是否包含 denied_operations\nviolations contains violation if\n    some tool in input.permissions.tools\n    some op in tool.denied_operations\n    op == \"DELETE\"\n    violation := {\n        \"severity\": \"critical\",\n        \"message\": sprintf(\"Tool '%s' allows DELETE operation, which is prohibited\", [tool.tool_name]),\n        \"tool\": tool.tool_name,\n        \"operation\": op\n    }\n\n# 规则 2：检查文件系统权限是否过宽\nviolations contains violation if\n    some tool in input.permissions.tools\n    tool.tool_name == \"file_system\"\n    not startswith(tool.allowed_paths[0], \"/tmp/\")\n    violation := {\n        \"severity\": \"high\",\n        \"message\": \"File system access should be restricted to /tmp/ directory\",\n        \"tool\": \"file_system\",\n        \"current_path\": tool.allowed_paths[0]\n    }\n\n# 规则 3：检查网络访问是否允许 HTTP\nviolations contains violation if\n    some protocol in input.permissions.network.denied_protocols\n    protocol == \"http\"\n    \"http\" in input.permissions.network.allowed_protocols\n    violation := {\n        \"severity\": \"high\",\n        \"message\": \"HTTP protocol is allowed but should be denied (use HTTPS only)\",\n        \"protocol\": \"http\"\n    }\n\n# 规则 4：检查邮件发送是否有外部审批\nviolations contains violation if\n    some tool in input.permissions.tools\n    tool.tool_name == \"email_sender\"\n    not tool.require_approval_for_external\n    violation := {\n        \"severity\": \"medium\",\n        \"message\": \"Email sender should require approval for external recipients\",\n        \"tool\": \"email_sender\"\n    }\n\n# 规则 5：检查 Token 限制是否合理\nviolations contains violation if\n    input.permissions.llm_access.max_tokens_per_request > 8000\n    violation := {\n        \"severity\": \"medium\",\n        \"message\": sprintf(\"Max tokens per request (%d) exceeds recommended limit (8000)\", \n            [input.permissions.llm_access.max_tokens_per_request]),\n        \"current_limit\": input.permissions.llm_access.max_tokens_per_request\n    }\n\n# 辅助函数：检查字符串是否以指定前缀开头\nstartswith(s, prefix) := true if\n    indexof(s, prefix) == 0\n","rego",[1583],"language-rego",[1585],{"type":25,"tag":240,"props":1586,"children":1587},{"__ignoreMap":7},[1588],{"type":31,"value":1580},{"type":25,"tag":223,"props":1590,"children":1592},{"id":1591},"_43-执行权限审计",[1593],{"type":31,"value":1594},"4.3 执行权限审计",{"type":25,"tag":235,"props":1596,"children":1599},{"code":1597,"language":1286,"meta":7,"className":1598},"# 安装 OPA\ncurl -L -o opa https://openpolicyagent.org/downloads/v0.60.0/opa_linux_amd64_static\nchmod +x opa\n\n# 运行审计\n./opa eval \\\n  --data policies/agent-permissions.rego \\\n  --input agent-permissions.json \\\n  \"data.main.violations\" \\\n  --format pretty\n",[1288],[1600],{"type":25,"tag":240,"props":1601,"children":1602},{"__ignoreMap":7},[1603],{"type":31,"value":1597},{"type":25,"tag":34,"props":1605,"children":1606},{},[1607,1611],{"type":25,"tag":38,"props":1608,"children":1609},{},[1610],{"type":31,"value":1315},{"type":31,"value":54},{"type":25,"tag":235,"props":1613,"children":1616},{"code":1614,"language":1551,"meta":7,"className":1615},"[\n  {\n    \"severity\": \"critical\",\n    \"message\": \"Tool 'database_query' allows DELETE operation, which is prohibited\",\n    \"tool\": \"database_query\",\n    \"operation\": \"DELETE\"\n  },\n  {\n    \"severity\": \"medium\",\n    \"message\": \"Max tokens per request (10000) exceeds recommended limit (8000)\",\n    \"current_limit\": 10000\n  }\n]\n",[1553],[1617],{"type":25,"tag":240,"props":1618,"children":1619},{"__ignoreMap":7},[1620],{"type":31,"value":1614},{"type":25,"tag":223,"props":1622,"children":1624},{"id":1623},"_44-权限基线管理",[1625],{"type":31,"value":1626},"4.4 权限基线管理",{"type":25,"tag":806,"props":1628,"children":1630},{"id":1629},"建立权限基线",[1631],{"type":31,"value":1629},{"type":25,"tag":235,"props":1633,"children":1636},{"code":1634,"language":1286,"meta":7,"className":1635},"# 生成当前权限快照\n./opa eval \\\n  --data policies/ \\\n  --input agent-permissions.json \\\n  \"data.main\" \\\n  --format json > baseline-permissions.json\n\n# 提交到版本控制\ngit add baseline-permissions.json\ngit commit -m \"Update permission baseline\"\n",[1288],[1637],{"type":25,"tag":240,"props":1638,"children":1639},{"__ignoreMap":7},[1640],{"type":31,"value":1634},{"type":25,"tag":806,"props":1642,"children":1644},{"id":1643},"检测权限漂移",[1645],{"type":31,"value":1643},{"type":25,"tag":235,"props":1647,"children":1650},{"code":1648,"language":1286,"meta":7,"className":1649},"# 比较当前权限与基线的差异\ndiff \u003C(jq -S . baseline-permissions.json) \u003C(jq -S . agent-permissions.json)\n\n# 如果有差异，触发告警\nif [ $? -ne 0 ]; then\n  echo \"⚠️  Permission drift detected!\"\n  echo \"Please review changes and update baseline if intentional.\"\n  exit 1\nfi\n",[1288],[1651],{"type":25,"tag":240,"props":1652,"children":1653},{"__ignoreMap":7},[1654],{"type":31,"value":1648},{"type":25,"tag":213,"props":1656,"children":1657},{},[],{"type":25,"tag":26,"props":1659,"children":1661},{"id":1660},"_5-日志脱敏验证实战",[1662],{"type":31,"value":1663},"5. 日志脱敏验证实战",{"type":25,"tag":223,"props":1665,"children":1667},{"id":1666},"_51-日志脱敏规则定义",[1668],{"type":31,"value":1669},"5.1 日志脱敏规则定义",{"type":25,"tag":806,"props":1671,"children":1673},{"id":1672},"规则配置文件configlog-rulesjson",[1674,1676,1682],{"type":31,"value":1675},"规则配置文件（",{"type":25,"tag":240,"props":1677,"children":1679},{"className":1678},[],[1680],{"type":31,"value":1681},"config/log-rules.json",{"type":31,"value":1338},{"type":25,"tag":235,"props":1684,"children":1687},{"code":1685,"language":1551,"meta":7,"className":1686},"{\n  \"rules\": [\n    {\n      \"id\": \"pii_email\",\n      \"description\": \"Email addresses in logs\",\n      \"pattern\": \"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\\\.[a-zA-Z]{2,}\",\n      \"replacement\": \"***@***.***\",\n      \"severity\": \"critical\",\n      \"contexts\": [\"console.log\", \"logger.info\", \"logger.error\", \"console.warn\"]\n    },\n    {\n      \"id\": \"pii_phone\",\n      \"description\": \"Phone numbers in logs\",\n      \"pattern\": \"\\\\b\\\\d{3}[-.]?\\\\d{3}[-.]?\\\\d{4}\\\\b\",\n      \"replacement\": \"***-***-****\",\n      \"severity\": \"critical\",\n      \"contexts\": [\"console.log\", \"logger.info\", \"logger.error\"]\n    },\n    {\n      \"id\": \"credit_card\",\n      \"description\": \"Credit card numbers\",\n      \"pattern\": \"\\\\b\\\\d{4}[- ]?\\\\d{4}[- ]?\\\\d{4}[- ]?(\\\\d{4})\\\\b\",\n      \"replacement\": \"****-****-****-$1\",\n      \"severity\": \"critical\",\n      \"contexts\": [\"*\"]\n    },\n    {\n      \"id\": \"api_key_pattern\",\n      \"description\": \"API keys (generic)\",\n      \"pattern\": \"(?:api[_-]?key|apikey)[\\\"'\\\\s:=]+([A-Za-z0-9]{20,})\",\n      \"replacement\": \"$1[REDACTED]\",\n      \"severity\": \"critical\",\n      \"contexts\": [\"*\"]\n    },\n    {\n      \"id\": \"jwt_token\",\n      \"description\": \"JWT tokens\",\n      \"pattern\": \"eyJ[A-Za-z0-9_-]+\\\\.eyJ[A-Za-z0-9_-]+\\\\.[A-Za-z0-9_-]+\",\n      \"replacement\": \"[JWT_TOKEN_REDACTED]\",\n      \"severity\": \"high\",\n      \"contexts\": [\"*\"]\n    },\n    {\n      \"id\": \"password_field\",\n      \"description\": \"Password fields in objects\",\n      \"pattern\": \"(?:password|passwd|pwd)[\\\"'\\\\s:=]+[^\\\\s,}]+\",\n      \"replacement\": \"$1[REDACTED]\",\n      \"severity\": \"critical\",\n      \"contexts\": [\"*\"]\n    }\n  ],\n  \"exclusions\": [\n    {\n      \"file_pattern\": \"*.test.ts\",\n      \"reason\": \"Test files may contain mock data\"\n    },\n    {\n      \"file_pattern\": \"docs/**/*.md\",\n      \"reason\": \"Documentation examples\"\n    }\n  ]\n}\n",[1553],[1688],{"type":25,"tag":240,"props":1689,"children":1690},{"__ignoreMap":7},[1691],{"type":31,"value":1685},{"type":25,"tag":223,"props":1693,"children":1695},{"id":1694},"_52-静态分析脚本",[1696],{"type":31,"value":1697},"5.2 静态分析脚本",{"type":25,"tag":806,"props":1699,"children":1701},{"id":1700},"python-实现scriptscheck_log_sanitizationpy",[1702,1704,1710],{"type":31,"value":1703},"Python 实现（",{"type":25,"tag":240,"props":1705,"children":1707},{"className":1706},[],[1708],{"type":31,"value":1709},"scripts/check_log_sanitization.py",{"type":31,"value":1338},{"type":25,"tag":235,"props":1712,"children":1717},{"code":1713,"language":1714,"meta":7,"className":1715},"#!/usr/bin/env python3\n\"\"\"\nLog Sanitization Checker\nScans source code for potential sensitive data leakage in log statements.\n\"\"\"\n\nimport re\nimport json\nimport sys\nimport os\nfrom pathlib import Path\nfrom typing import List, Dict, Tuple\n\nclass LogSanitizationChecker:\n    def __init__(self, rules_file: str):\n        with open(rules_file, 'r') as f:\n            self.config = json.load(f)\n        self.rules = self.config['rules']\n        self.exclusions = self.config.get('exclusions', [])\n        self.violations = []\n    \n    def should_exclude(self, file_path: str) -> bool:\n        \"\"\"Check if file should be excluded from scanning.\"\"\"\n        for exclusion in self.exclusions:\n            pattern = exclusion['file_pattern'].replace('*', '.*')\n            if re.match(pattern, file_path):\n                print(f\"⏭️  Excluding {file_path}: {exclusion['reason']}\")\n                return True\n        return False\n    \n    def extract_log_statements(self, content: str, file_path: str) -> List[Tuple[str, int]]:\n        \"\"\"Extract log statements from source code.\"\"\"\n        log_patterns = [\n            r'console\\.(log|warn|error|info|debug)\\((.*?)\\)',\n            r'logger\\.(info|warn|error|debug|trace)\\((.*?)\\)',\n            r'logging\\.(info|warning|error|debug)\\((.*?)\\)',\n        ]\n        \n        statements = []\n        lines = content.split('\\n')\n        \n        for line_num, line in enumerate(lines, 1):\n            for pattern in log_patterns:\n                matches = re.finditer(pattern, line)\n                for match in matches:\n                    log_content = match.group(2)\n                    statements.append((log_content, line_num))\n        \n        return statements\n    \n    def check_violations(self, content: str, file_path: str) -> List[Dict]:\n        \"\"\"Check for sensitive data in log statements.\"\"\"\n        if self.should_exclude(file_path):\n            return []\n        \n        violations = []\n        log_statements = self.extract_log_statements(content, file_path)\n        \n        for log_content, line_num in log_statements:\n            for rule in self.rules:\n                pattern = rule['pattern']\n                if re.search(pattern, log_content, re.IGNORECASE):\n                    violation = {\n                        'file': file_path,\n                        'line': line_num,\n                        'rule_id': rule['id'],\n                        'description': rule['description'],\n                        'severity': rule['severity'],\n                        'content_preview': log_content[:100] + '...' if len(log_content) > 100 else log_content\n                    }\n                    violations.append(violation)\n        \n        return violations\n    \n    def scan_directory(self, source_dir: str) -> List[Dict]:\n        \"\"\"Scan all files in directory.\"\"\"\n        all_violations = []\n        source_path = Path(source_dir)\n        \n        for file_path in source_path.rglob('*'):\n            if file_path.is_file() and file_path.suffix in ['.ts', '.js', '.py', '.java']:\n                try:\n                    with open(file_path, 'r', encoding='utf-8') as f:\n                        content = f.read()\n                    \n                    violations = self.check_violations(content, str(file_path))\n                    all_violations.extend(violations)\n                except Exception as e:\n                    print(f\"⚠️  Error reading {file_path}: {e}\")\n        \n        return all_violations\n    \n    def generate_report(self, violations: List[Dict]) -> str:\n        \"\"\"Generate human-readable report.\"\"\"\n        if not violations:\n            return \"✅ No log sanitization violations found!\"\n        \n        report = []\n        report.append(\"=\" * 80)\n        report.append(\"LOG SANITIZATION VIOLATION REPORT\")\n        report.append(\"=\" * 80)\n        report.append(f\"Total violations: {len(violations)}\")\n        report.append(\"\")\n        \n        # Group by severity\n        by_severity = {}\n        for v in violations:\n            severity = v['severity']\n            if severity not in by_severity:\n                by_severity[severity] = []\n            by_severity[severity].append(v)\n        \n        for severity in ['critical', 'high', 'medium', 'low']:\n            if severity in by_severity:\n                report.append(f\"\\n{'='*60}\")\n                report.append(f\"{severity.upper()} ({len(by_severity[severity])} violations)\")\n                report.append('=' * 60)\n                \n                for v in by_severity[severity]:\n                    report.append(f\"\\n📄 File: {v['file']}\")\n                    report.append(f\"📍 Line: {v['line']}\")\n                    report.append(f\"🔍 Rule: {v['rule_id']} - {v['description']}\")\n                    report.append(f\"📝 Preview: {v['content_preview']}\")\n        \n        report.append(\"\\n\" + \"=\" * 80)\n        report.append(\"RECOMMENDATIONS:\")\n        report.append(\"=\" * 80)\n        report.append(\"1. Use a logging library with built-in redaction (e.g., pino-redact)\")\n        report.append(\"2. Implement middleware to sanitize logs before output\")\n        report.append(\"3. Add unit tests to verify sensitive data is not logged\")\n        report.append(\"4. Review and update redaction rules regularly\")\n        \n        return \"\\n\".join(report)\n\n\ndef main():\n    import argparse\n    \n    parser = argparse.ArgumentParser(description='Check log sanitization')\n    parser.add_argument('--source-dir', required=True, help='Source directory to scan')\n    parser.add_argument('--rules', default='config/log-rules.json', help='Rules file path')\n    parser.add_argument('--output', help='Output report file (optional)')\n    \n    args = parser.parse_args()\n    \n    checker = LogSanitizationChecker(args.rules)\n    violations = checker.scan_directory(args.source_dir)\n    report = checker.generate_report(violations)\n    \n    print(report)\n    \n    if args.output:\n        with open(args.output, 'w') as f:\n            f.write(report)\n        print(f\"\\n📄 Report saved to {args.output}\")\n    \n    # Exit with error code if critical violations found\n    critical_count = sum(1 for v in violations if v['severity'] == 'critical')\n    if critical_count > 0:\n        print(f\"\\n❌ Found {critical_count} critical violations!\")\n        sys.exit(1)\n    else:\n        print(\"\\n✅ All checks passed!\")\n        sys.exit(0)\n\n\nif __name__ == '__main__':\n    main()\n","python",[1716],"language-python",[1718],{"type":25,"tag":240,"props":1719,"children":1720},{"__ignoreMap":7},[1721],{"type":31,"value":1713},{"type":25,"tag":806,"props":1723,"children":1725},{"id":1724},"使用方法",[1726],{"type":31,"value":1724},{"type":25,"tag":235,"props":1728,"children":1731},{"code":1729,"language":1286,"meta":7,"className":1730},"# 安装依赖（如果需要）\npip install argparse\n\n# 运行检查\npython scripts/check_log_sanitization.py \\\n  --source-dir src/ \\\n  --rules config/log-rules.json \\\n  --output reports/log-sanitization-report.md\n\n# 在 CI 中使用\nif ! python scripts/check_log_sanitization.py --source-dir src/; then\n  echo \"❌ Log sanitization check failed!\"\n  exit 1\nfi\n",[1288],[1732],{"type":25,"tag":240,"props":1733,"children":1734},{"__ignoreMap":7},[1735],{"type":31,"value":1729},{"type":25,"tag":223,"props":1737,"children":1739},{"id":1738},"_53-运行时验证可选高级方案",[1740],{"type":31,"value":1741},"5.3 运行时验证（可选高级方案）",{"type":25,"tag":34,"props":1743,"children":1744},{},[1745],{"type":31,"value":1746},"对于更严格的场景，可以在运行时注入脱敏检查：",{"type":25,"tag":235,"props":1748,"children":1751},{"code":1749,"language":1447,"meta":7,"className":1750},"// middleware/log-sanitizer.ts\nimport winston from 'winston';\n\nconst sensitivePatterns = [\n  { name: 'email', regex: /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}/g, replacement: '***@***.***' },\n  { name: 'phone', regex: /\\b\\d{3}[-.]?\\d{3}[-.]?\\d{4}\\b/g, replacement: '***-***-****' },\n  { name: 'credit_card', regex: /\\b\\d{4}[- ]?\\d{4}[- ]?\\d{4}[- ]?(\\d{4})\\b/g, replacement: '****-****-****-$1' },\n];\n\nfunction sanitizeLogMessage(message: string): string {\n  let sanitized = message;\n  \n  for (const pattern of sensitivePatterns) {\n    sanitized = sanitized.replace(pattern.regex, pattern.replacement);\n  }\n  \n  return sanitized;\n}\n\n// 创建自定义 Transport\nconst sanitizedConsoleTransport = new winston.transports.Console({\n  format: winston.format.printf(({ level, message, timestamp }) => {\n    const sanitizedMessage = sanitizeLogMessage(message);\n    return `${timestamp} [${level}]: ${sanitizedMessage}`;\n  }),\n});\n\nconst logger = winston.createLogger({\n  transports: [sanitizedConsoleTransport],\n});\n\n// 使用\nlogger.info('User email: john@example.com'); \n// 输出: 2024-01-15T10:30:00.000Z [info]: User email: ***@***.***\n",[1449],[1752],{"type":25,"tag":240,"props":1753,"children":1754},{"__ignoreMap":7},[1755],{"type":31,"value":1749},{"type":25,"tag":213,"props":1757,"children":1758},{},[],{"type":25,"tag":26,"props":1760,"children":1762},{"id":1761},"_6-误报处理与规则优化",[1763],{"type":31,"value":1764},"6. 误报处理与规则优化",{"type":25,"tag":223,"props":1766,"children":1768},{"id":1767},"_61-误报分类",[1769],{"type":31,"value":1770},"6.1 误报分类",{"type":25,"tag":110,"props":1772,"children":1773},{},[1774,1795],{"type":25,"tag":114,"props":1775,"children":1776},{},[1777],{"type":25,"tag":118,"props":1778,"children":1779},{},[1780,1785,1790],{"type":25,"tag":122,"props":1781,"children":1782},{},[1783],{"type":31,"value":1784},"误报类型",{"type":25,"tag":122,"props":1786,"children":1787},{},[1788],{"type":31,"value":1789},"示例",{"type":25,"tag":122,"props":1791,"children":1792},{},[1793],{"type":31,"value":1794},"解决方案",{"type":25,"tag":138,"props":1796,"children":1797},{},[1798,1819,1840,1867,1888],{"type":25,"tag":118,"props":1799,"children":1800},{},[1801,1809,1814],{"type":25,"tag":145,"props":1802,"children":1803},{},[1804],{"type":25,"tag":38,"props":1805,"children":1806},{},[1807],{"type":31,"value":1808},"测试数据",{"type":25,"tag":145,"props":1810,"children":1811},{},[1812],{"type":31,"value":1813},"单元测试中的假密钥",{"type":25,"tag":145,"props":1815,"children":1816},{},[1817],{"type":31,"value":1818},"排除测试文件或使用明显假值",{"type":25,"tag":118,"props":1820,"children":1821},{},[1822,1830,1835],{"type":25,"tag":145,"props":1823,"children":1824},{},[1825],{"type":25,"tag":38,"props":1826,"children":1827},{},[1828],{"type":31,"value":1829},"文档示例",{"type":25,"tag":145,"props":1831,"children":1832},{},[1833],{"type":31,"value":1834},"README 中的示例代码",{"type":25,"tag":145,"props":1836,"children":1837},{},[1838],{"type":31,"value":1839},"排除文档目录或使用占位符",{"type":25,"tag":118,"props":1841,"children":1842},{},[1843,1851,1862],{"type":25,"tag":145,"props":1844,"children":1845},{},[1846],{"type":25,"tag":38,"props":1847,"children":1848},{},[1849],{"type":31,"value":1850},"环境变量模板",{"type":25,"tag":145,"props":1852,"children":1853},{},[1854,1860],{"type":25,"tag":240,"props":1855,"children":1857},{"className":1856},[],[1858],{"type":31,"value":1859},".env.example",{"type":31,"value":1861}," 中的说明",{"type":25,"tag":145,"props":1863,"children":1864},{},[1865],{"type":31,"value":1866},"使用描述性文本而非真实格式",{"type":25,"tag":118,"props":1868,"children":1869},{},[1870,1878,1883],{"type":25,"tag":145,"props":1871,"children":1872},{},[1873],{"type":25,"tag":38,"props":1874,"children":1875},{},[1876],{"type":31,"value":1877},"加密数据",{"type":25,"tag":145,"props":1879,"children":1880},{},[1881],{"type":31,"value":1882},"Base64 编码的非敏感数据",{"type":25,"tag":145,"props":1884,"children":1885},{},[1886],{"type":31,"value":1887},"添加上下文感知规则",{"type":25,"tag":118,"props":1889,"children":1890},{},[1891,1899,1904],{"type":25,"tag":145,"props":1892,"children":1893},{},[1894],{"type":25,"tag":38,"props":1895,"children":1896},{},[1897],{"type":31,"value":1898},"哈希值",{"type":25,"tag":145,"props":1900,"children":1901},{},[1902],{"type":31,"value":1903},"Git commit hash、文件校验和",{"type":25,"tag":145,"props":1905,"children":1906},{},[1907],{"type":31,"value":1908},"排除特定模式（如 SHA-256）",{"type":25,"tag":223,"props":1910,"children":1912},{"id":1911},"_62-白名单机制",[1913],{"type":31,"value":1914},"6.2 白名单机制",{"type":25,"tag":806,"props":1916,"children":1918},{"id":1917},"trufflehog-白名单",[1919],{"type":31,"value":1920},"TruffleHog 白名单",{"type":25,"tag":235,"props":1922,"children":1925},{"code":1923,"language":1255,"meta":7,"className":1924},"# .trufflehog.yaml\nallowlist:\n  commits:\n    - \"abc123def456\"  # 已知安全的提交\n  paths:\n    - \"tests/fixtures/api-keys.txt\"  # 测试文件\n  regexes:\n    - \"SK-TEST-[A-Z0-9]+\"  # 测试密钥模式\n",[1257],[1926],{"type":25,"tag":240,"props":1927,"children":1928},{"__ignoreMap":7},[1929],{"type":31,"value":1923},{"type":25,"tag":806,"props":1931,"children":1933},{"id":1932},"opa-策略豁免",[1934],{"type":31,"value":1935},"OPA 策略豁免",{"type":25,"tag":235,"props":1937,"children":1940},{"code":1938,"language":1581,"meta":7,"className":1939},"# 为特定 Agent 豁免某些规则\nexemptions := {\n  \"experimental-agent-v2\": [\"rule_5\"],  # 允许更高的 token 限制\n  \"legacy-agent\": [\"rule_2\"],  # 允许访问旧的文件路径\n}\n\nviolations contains violation if\n    not input.agent_id in exemptions\n    # ... 原有规则逻辑\n",[1583],[1941],{"type":25,"tag":240,"props":1942,"children":1943},{"__ignoreMap":7},[1944],{"type":31,"value":1938},{"type":25,"tag":223,"props":1946,"children":1948},{"id":1947},"_63-反馈闭环",[1949],{"type":31,"value":1950},"6.3 反馈闭环",{"type":25,"tag":34,"props":1952,"children":1953},{},[1954],{"type":31,"value":1955},"建立误报报告和优化流程：",{"type":25,"tag":235,"props":1957,"children":1962},{"code":1958,"language":1959,"meta":7,"className":1960},"graph LR\n    A[CI 扫描发现违规] --> B{是否为误报?}\n    B -->|是| C[提交误报报告]\n    B -->|否| D[修复代码]\n    C --> E[安全团队审核]\n    E --> F{确认为误报?}\n    F -->|是| G[更新规则/白名单]\n    F -->|否| H[重新分类为真实违规]\n    G --> I[重新运行 CI]\n    H --> D\n    D --> I\n    I --> J[合并代码]\n","mermaid",[1961],"language-mermaid",[1963],{"type":25,"tag":240,"props":1964,"children":1965},{"__ignoreMap":7},[1966],{"type":31,"value":1958},{"type":25,"tag":34,"props":1968,"children":1969},{},[1970,1975],{"type":25,"tag":38,"props":1971,"children":1972},{},[1973],{"type":31,"value":1974},"误报报告模板",{"type":31,"value":54},{"type":25,"tag":235,"props":1977,"children":1980},{"code":1978,"language":1473,"meta":7,"className":1979},"## False Positive Report\n\n**Scan Type**: Credential Scan / Permission Audit / Log Sanitization\n\n**File**: `src/config/example.ts`\n\n**Line**: 42\n\n**Detected Issue**: Hardcoded API key\n\n**Why It's a False Positive**:\n- This is a test fixture with an invalid key format\n- The key is used only in unit tests\n- Already excluded in `.trufflehog.yaml` but rule was updated\n\n**Proposed Solution**:\n- [ ] Add to allowlist\n- [ ] Update regex pattern\n- [ ] Move to separate test directory\n\n**Reporter**: @developer-name\n**Date**: 2024-01-15\n",[1475],[1981],{"type":25,"tag":240,"props":1982,"children":1983},{"__ignoreMap":7},[1984],{"type":31,"value":1978},{"type":25,"tag":213,"props":1986,"children":1987},{},[],{"type":25,"tag":26,"props":1989,"children":1991},{"id":1990},"_7-完整-cicd-集成示例",[1992],{"type":31,"value":1993},"7. 完整 CI/CD 集成示例",{"type":25,"tag":223,"props":1995,"children":1997},{"id":1996},"_71-github-actions-完整工作流",[1998],{"type":31,"value":1999},"7.1 GitHub Actions 完整工作流",{"type":25,"tag":235,"props":2001,"children":2004},{"code":2002,"language":1255,"meta":7,"className":2003},"# .github/workflows/security-pipeline.yml\nname: Security Pipeline\n\non:\n  pull_request:\n    branches: [main, develop]\n  push:\n    branches: [main]\n\nenv:\n  TRUFFLEHOG_VERSION: v3.67.0\n  OPA_VERSION: v0.60.0\n\njobs:\n  # ==========================================\n  # Stage 1: Quick Checks (Fast Feedback)\n  # ==========================================\n  quick-checks:\n    name: Quick Security Checks\n    runs-on: ubuntu-latest\n    timeout-minutes: 5\n    \n    steps:\n      - uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n      \n      - name: Cache TruffleHog\n        uses: actions/cache@v3\n        with:\n          path: ~/.cache/trufflehog\n          key: trufflehog-${{ env.TRUFFLEHOG_VERSION }}\n      \n      - name: Install TruffleHog\n        run: |\n          curl -sSfL https://raw.githubusercontent.com/trufflesecurity/trufflehog/main/scripts/install.sh | sh -s -- -b /usr/local/bin\n      \n      - name: Run Credential Scan\n        run: |\n          trufflehog git file://. \\\n            --only-verified \\\n            --fail \\\n            --json > trufflehog-results.json\n        \n      - name: Upload TruffleHog Results\n        if: always()\n        uses: actions/upload-artifact@v3\n        with:\n          name: trufflehog-results\n          path: trufflehog-results.json\n      \n      - name: Check for Critical Violations\n        run: |\n          if jq -e '.[] | select(.Verified == true)' trufflehog-results.json > /dev/null; then\n            echo \"❌ Found verified secrets!\"\n            jq '.[] | select(.Verified == true)' trufflehog-results.json\n            exit 1\n          fi\n          echo \"✅ No verified secrets found\"\n  \n  # ==========================================\n  # Stage 2: Deep Analysis\n  # ==========================================\n  deep-analysis:\n    name: Deep Security Analysis\n    runs-on: ubuntu-latest\n    timeout-minutes: 10\n    needs: quick-checks\n    \n    steps:\n      - uses: actions/checkout@v4\n      \n      - name: Setup Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: '20'\n          cache: 'npm'\n      \n      - name: Install Dependencies\n        run: npm ci\n      \n      - name: Install OPA\n        run: |\n          curl -L -o opa https://openpolicyagent.org/downloads/${{ env.OPA_VERSION }}/opa_linux_amd64_static\n          chmod +x opa\n          sudo mv opa /usr/local/bin/\n      \n      - name: Run Permission Audit\n        run: |\n          opa eval \\\n            --data policies/ \\\n            --input agent-permissions.json \\\n            \"data.main.violations\" \\\n            --format json > opa-results.json\n      \n      - name: Check Permission Violations\n        run: |\n          VIOLATION_COUNT=$(jq 'length' opa-results.json)\n          if [ \"$VIOLATION_COUNT\" -gt 0 ]; then\n            echo \"❌ Found $VIOLATION_COUNT permission violations:\"\n            jq '.' opa-results.json\n            exit 1\n          fi\n          echo \"✅ No permission violations found\"\n      \n      - name: Run Log Sanitization Check\n        run: |\n          python scripts/check_log_sanitization.py \\\n            --source-dir src/ \\\n            --rules config/log-rules.json \\\n            --output log-sanitization-report.md\n      \n      - name: Upload Reports\n        if: always()\n        uses: actions/upload-artifact@v3\n        with:\n          name: security-reports\n          path: |\n            opa-results.json\n            log-sanitization-report.md\n  \n  # ==========================================\n  # Stage 3: Dependency & License Check\n  # ==========================================\n  dependency-check:\n    name: Dependency Security Check\n    runs-on: ubuntu-latest\n    timeout-minutes: 5\n    \n    steps:\n      - uses: actions/checkout@v4\n      \n      - name: Setup Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: '20'\n          cache: 'npm'\n      \n      - name: Install Dependencies\n        run: npm ci\n      \n      - name: Run npm audit\n        run: |\n          npm audit --audit-level=moderate || true\n          npm audit --json > npm-audit-results.json\n      \n      - name: Check for High/Critical Vulnerabilities\n        run: |\n          HIGH_VULNS=$(jq '.metadata.vulnerabilities.high + .metadata.vulnerabilities.critical' npm-audit-results.json)\n          if [ \"$HIGH_VULNS\" -gt 0 ]; then\n            echo \"❌ Found $HIGH_VULNS high/critical vulnerabilities\"\n            exit 1\n          fi\n          echo \"✅ No high/critical vulnerabilities\"\n  \n  # ==========================================\n  # Stage 4: Summary & Reporting\n  # ==========================================\n  security-summary:\n    name: Security Summary\n    runs-on: ubuntu-latest\n    needs: [quick-checks, deep-analysis, dependency-check]\n    if: always()\n    \n    steps:\n      - uses: actions/checkout@v4\n      \n      - name: Download All Artifacts\n        uses: actions/download-artifact@v3\n      \n      - name: Generate Summary\n        run: |\n          echo \"## 🔒 Security Scan Summary\" >> $GITHUB_STEP_SUMMARY\n          echo \"\" >> $GITHUB_STEP_SUMMARY\n          \n          # Check each job status\n          if [ \"${{ needs.quick-checks.result }}\" == \"success\" ]; then\n            echo \"✅ **Credential Scan**: Passed\" >> $GITHUB_STEP_SUMMARY\n          else\n            echo \"❌ **Credential Scan**: Failed\" >> $GITHUB_STEP_SUMMARY\n          fi\n          \n          if [ \"${{ needs.deep-analysis.result }}\" == \"success\" ]; then\n            echo \"✅ **Permission Audit**: Passed\" >> $GITHUB_STEP_SUMMARY\n            echo \"✅ **Log Sanitization**: Passed\" >> $GITHUB_STEP_SUMMARY\n          else\n            echo \"❌ **Deep Analysis**: Failed\" >> $GITHUB_STEP_SUMMARY\n          fi\n          \n          if [ \"${{ needs.dependency-check.result }}\" == \"success\" ]; then\n            echo \"✅ **Dependency Check**: Passed\" >> $GITHUB_STEP_SUMMARY\n          else\n            echo \"❌ **Dependency Check**: Failed\" >> $GITHUB_STEP_SUMMARY\n          fi\n          \n          echo \"\" >> $GITHUB_STEP_SUMMARY\n          echo \"📄 Detailed reports are available in the Artifacts section.\" >> $GITHUB_STEP_SUMMARY\n",[1257],[2005],{"type":25,"tag":240,"props":2006,"children":2007},{"__ignoreMap":7},[2008],{"type":31,"value":2002},{"type":25,"tag":223,"props":2010,"children":2012},{"id":2011},"_72-分支保护规则",[2013],{"type":31,"value":2014},"7.2 分支保护规则",{"type":25,"tag":34,"props":2016,"children":2017},{},[2018],{"type":31,"value":2019},"在 GitHub 仓库设置中配置：",{"type":25,"tag":235,"props":2021,"children":2023},{"code":2022},"Settings → Branches → Branch protection rules → Add rule\n\nBranch name pattern: main\n\n✓ Require status checks to pass before merging\n  ✓ Status checks that are required:\n    - Quick Security Checks\n    - Deep Security Analysis\n    - Dependency Security Check\n\n✓ Require pull request reviews before merging\n  ✓ Required approving reviews: 1\n\n✓ Require conversation resolution before merging\n\n✓ Include administrators\n",[2024],{"type":25,"tag":240,"props":2025,"children":2026},{"__ignoreMap":7},[2027],{"type":31,"value":2022},{"type":25,"tag":223,"props":2029,"children":2031},{"id":2030},"_73-slack-告警集成",[2032],{"type":31,"value":2033},"7.3 Slack 告警集成",{"type":25,"tag":235,"props":2035,"children":2038},{"code":2036,"language":1255,"meta":7,"className":2037},"# 在 security-summary job 中添加\nnotify-slack:\n  name: Notify Slack\n  runs-on: ubuntu-latest\n  needs: [security-summary]\n  if: failure()\n  \n  steps:\n    - name: Send Slack Notification\n      uses: slackapi/slack-github-action@v1\n      with:\n        payload: |\n          {\n            \"text\": \"🚨 Security Scan Failed!\",\n            \"blocks\": [\n              {\n                \"type\": \"header\",\n                \"text\": {\n                  \"type\": \"plain_text\",\n                  \"text\": \"🚨 Security Scan Failed\"\n                }\n              },\n              {\n                \"type\": \"section\",\n                \"fields\": [\n                  {\n                    \"type\": \"mrkdwn\",\n                    \"text\": \"*Repository:*\\n${{ github.repository }}\"\n                  },\n                  {\n                    \"type\": \"mrkdwn\",\n                    \"text\": \"*Branch:*\\n${{ github.ref_name }}\"\n                  },\n                  {\n                    \"type\": \"mrkdwn\",\n                    \"text\": \"*PR:*\\n\u003C${{ github.event.pull_request.html_url }}|#${{ github.event.pull_request.number }}>\"\n                  },\n                  {\n                    \"type\": \"mrkdwn\",\n                    \"text\": \"*Author:*\\n${{ github.actor }}\"\n                  }\n                ]\n              },\n              {\n                \"type\": \"actions\",\n                \"elements\": [\n                  {\n                    \"type\": \"button\",\n                    \"text\": {\n                      \"type\": \"plain_text\",\n                      \"text\": \"View Workflow\"\n                    },\n                    \"url\": \"${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}\"\n                  }\n                ]\n              }\n            ]\n          }\n      env:\n        SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}\n",[1257],[2039],{"type":25,"tag":240,"props":2040,"children":2041},{"__ignoreMap":7},[2042],{"type":31,"value":2036},{"type":25,"tag":213,"props":2044,"children":2045},{},[],{"type":25,"tag":26,"props":2047,"children":2049},{"id":2048},"_8-最佳实践-checklist",[2050],{"type":31,"value":2051},"8. 最佳实践 Checklist",{"type":25,"tag":223,"props":2053,"children":2055},{"id":2054},"_81-凭证管理",[2056],{"type":31,"value":2057},"8.1 凭证管理",{"type":25,"tag":56,"props":2059,"children":2062},{"className":2060},[2061],"contains-task-list",[2063,2083,2112,2127,2142,2157],{"type":25,"tag":60,"props":2064,"children":2067},{"className":2065},[2066],"task-list-item",[2068,2074,2076,2081],{"type":25,"tag":2069,"props":2070,"children":2073},"input",{"disabled":2071,"type":2072},true,"checkbox",[],{"type":31,"value":2075}," ",{"type":25,"tag":38,"props":2077,"children":2078},{},[2079],{"type":31,"value":2080},"绝不硬编码",{"type":31,"value":2082},"：所有敏感信息使用环境变量或密钥管理服务",{"type":25,"tag":60,"props":2084,"children":2086},{"className":2085},[2066],[2087,2090,2091,2096,2098,2104,2106],{"type":25,"tag":2069,"props":2088,"children":2089},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":2092,"children":2093},{},[2094],{"type":31,"value":2095},"使用 .env 文件",{"type":31,"value":2097},"：本地开发时使用 ",{"type":25,"tag":240,"props":2099,"children":2101},{"className":2100},[],[2102],{"type":31,"value":2103},".env",{"type":31,"value":2105},"，并添加到 ",{"type":25,"tag":240,"props":2107,"children":2109},{"className":2108},[],[2110],{"type":31,"value":2111},".gitignore",{"type":25,"tag":60,"props":2113,"children":2115},{"className":2114},[2066],[2116,2119,2120,2125],{"type":25,"tag":2069,"props":2117,"children":2118},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":2121,"children":2122},{},[2123],{"type":31,"value":2124},"提供 .env.example",{"type":31,"value":2126},"：包含占位符和说明，不包含真实值",{"type":25,"tag":60,"props":2128,"children":2130},{"className":2129},[2066],[2131,2134,2135,2140],{"type":25,"tag":2069,"props":2132,"children":2133},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":2136,"children":2137},{},[2138],{"type":31,"value":2139},"定期轮换",{"type":31,"value":2141},"：至少每 90 天轮换一次 API Key",{"type":25,"tag":60,"props":2143,"children":2145},{"className":2144},[2066],[2146,2149,2150,2155],{"type":25,"tag":2069,"props":2147,"children":2148},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":2151,"children":2152},{},[2153],{"type":31,"value":2154},"最小权限原则",{"type":31,"value":2156},"：每个 Agent 只授予必需的权限",{"type":25,"tag":60,"props":2158,"children":2160},{"className":2159},[2066],[2161,2164,2165,2170],{"type":25,"tag":2069,"props":2162,"children":2163},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":2166,"children":2167},{},[2168],{"type":31,"value":2169},"审计日志",{"type":31,"value":2171},"：记录所有凭证使用情况",{"type":25,"tag":223,"props":2173,"children":2175},{"id":2174},"_82-ci-配置",[2176],{"type":31,"value":2177},"8.2 CI 配置",{"type":25,"tag":56,"props":2179,"children":2181},{"className":2180},[2061],[2182,2197,2212,2227,2242,2257],{"type":25,"tag":60,"props":2183,"children":2185},{"className":2184},[2066],[2186,2189,2190,2195],{"type":25,"tag":2069,"props":2187,"children":2188},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":2191,"children":2192},{},[2193],{"type":31,"value":2194},"多层防御",{"type":31,"value":2196},"：Pre-commit + PR Check + Deployment Gate",{"type":25,"tag":60,"props":2198,"children":2200},{"className":2199},[2066],[2201,2204,2205,2210],{"type":25,"tag":2069,"props":2202,"children":2203},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":2206,"children":2207},{},[2208],{"type":31,"value":2209},"快速反馈",{"type":31,"value":2211},"：Quick Checks 在 5 分钟内完成",{"type":25,"tag":60,"props":2213,"children":2215},{"className":2214},[2066],[2216,2219,2220,2225],{"type":25,"tag":2069,"props":2217,"children":2218},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":2221,"children":2222},{},[2223],{"type":31,"value":2224},"并行执行",{"type":31,"value":2226},"：独立的 Job 并行运行，减少总时长",{"type":25,"tag":60,"props":2228,"children":2230},{"className":2229},[2066],[2231,2234,2235,2240],{"type":25,"tag":2069,"props":2232,"children":2233},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":2236,"children":2237},{},[2238],{"type":31,"value":2239},"缓存优化",{"type":31,"value":2241},"：缓存工具和依赖，加速后续运行",{"type":25,"tag":60,"props":2243,"children":2245},{"className":2244},[2066],[2246,2249,2250,2255],{"type":25,"tag":2069,"props":2247,"children":2248},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":2251,"children":2252},{},[2253],{"type":31,"value":2254},"超时保护",{"type":31,"value":2256},"：设置合理的 timeout，避免无限等待",{"type":25,"tag":60,"props":2258,"children":2260},{"className":2259},[2066],[2261,2264,2265,2270],{"type":25,"tag":2069,"props":2262,"children":2263},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":2266,"children":2267},{},[2268],{"type":31,"value":2269},"Artifact 保留",{"type":31,"value":2271},"：保存扫描结果供后续审计",{"type":25,"tag":223,"props":2273,"children":2275},{"id":2274},"_83-规则维护",[2276],{"type":31,"value":2277},"8.3 规则维护",{"type":25,"tag":56,"props":2279,"children":2281},{"className":2280},[2061],[2282,2297,2312,2327,2342],{"type":25,"tag":60,"props":2283,"children":2285},{"className":2284},[2066],[2286,2289,2290,2295],{"type":25,"tag":2069,"props":2287,"children":2288},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":2291,"children":2292},{},[2293],{"type":31,"value":2294},"定期 Review",{"type":31,"value":2296},"：每月审查误报率和漏报率",{"type":25,"tag":60,"props":2298,"children":2300},{"className":2299},[2066],[2301,2304,2305,2310],{"type":25,"tag":2069,"props":2302,"children":2303},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":2306,"children":2307},{},[2308],{"type":31,"value":2309},"更新规则库",{"type":31,"value":2311},"：跟踪最新的安全威胁和检测规则",{"type":25,"tag":60,"props":2313,"children":2315},{"className":2314},[2066],[2316,2319,2320,2325],{"type":25,"tag":2069,"props":2317,"children":2318},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":2321,"children":2322},{},[2323],{"type":31,"value":2324},"文档化",{"type":31,"value":2326},"：记录每条规则的意图和例外情况",{"type":25,"tag":60,"props":2328,"children":2330},{"className":2329},[2066],[2331,2334,2335,2340],{"type":25,"tag":2069,"props":2332,"children":2333},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":2336,"children":2337},{},[2338],{"type":31,"value":2339},"培训团队",{"type":31,"value":2341},"：确保所有开发者理解安全要求",{"type":25,"tag":60,"props":2343,"children":2345},{"className":2344},[2066],[2346,2349,2350,2355],{"type":25,"tag":2069,"props":2347,"children":2348},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":2351,"children":2352},{},[2353],{"type":31,"value":2354},"反馈机制",{"type":31,"value":2356},"：建立便捷的误报报告渠道",{"type":25,"tag":223,"props":2358,"children":2360},{"id":2359},"_84-应急响应",[2361],{"type":31,"value":2362},"8.4 应急响应",{"type":25,"tag":56,"props":2364,"children":2366},{"className":2365},[2061],[2367,2382,2397,2412,2427],{"type":25,"tag":60,"props":2368,"children":2370},{"className":2369},[2066],[2371,2374,2375,2380],{"type":25,"tag":2069,"props":2372,"children":2373},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":2376,"children":2377},{},[2378],{"type":31,"value":2379},"定义严重级别",{"type":31,"value":2381},"：Critical/High/Medium/Low 的响应时间要求",{"type":25,"tag":60,"props":2383,"children":2385},{"className":2384},[2066],[2386,2389,2390,2395],{"type":25,"tag":2069,"props":2387,"children":2388},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":2391,"children":2392},{},[2393],{"type":31,"value":2394},"自动化阻断",{"type":31,"value":2396},"：Critical 级别自动阻止合并/部署",{"type":25,"tag":60,"props":2398,"children":2400},{"className":2399},[2066],[2401,2404,2405,2410],{"type":25,"tag":2069,"props":2402,"children":2403},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":2406,"children":2407},{},[2408],{"type":31,"value":2409},"人工审批",{"type":31,"value":2411},"：High 级别需要安全团队审批",{"type":25,"tag":60,"props":2413,"children":2415},{"className":2414},[2066],[2416,2419,2420,2425],{"type":25,"tag":2069,"props":2417,"children":2418},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":2421,"children":2422},{},[2423],{"type":31,"value":2424},"事后复盘",{"type":31,"value":2426},"：每次安全事件后进行根因分析",{"type":25,"tag":60,"props":2428,"children":2430},{"className":2429},[2066],[2431,2434,2435,2440],{"type":25,"tag":2069,"props":2432,"children":2433},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":2436,"children":2437},{},[2438],{"type":31,"value":2439},"持续改进",{"type":31,"value":2441},"：根据事件更新规则和流程",{"type":25,"tag":213,"props":2443,"children":2444},{},[],{"type":25,"tag":26,"props":2446,"children":2448},{"id":2447},"_9-延伸阅读",[2449],{"type":31,"value":2450},"9. 延伸阅读",{"type":25,"tag":223,"props":2452,"children":2454},{"id":2453},"_91-官方文档",[2455],{"type":31,"value":2456},"9.1 官方文档",{"type":25,"tag":56,"props":2458,"children":2459},{},[2460,2477,2491,2506],{"type":25,"tag":60,"props":2461,"children":2462},{},[2463,2467,2469],{"type":25,"tag":38,"props":2464,"children":2465},{},[2466],{"type":31,"value":863},{"type":31,"value":2468},": ",{"type":25,"tag":2470,"props":2471,"children":2475},"a",{"href":2472,"rel":2473},"https://github.com/trufflesecurity/trufflehog",[2474],"nofollow",[2476],{"type":31,"value":2472},{"type":25,"tag":60,"props":2478,"children":2479},{},[2480,2484,2485],{"type":25,"tag":38,"props":2481,"children":2482},{},[2483],{"type":31,"value":1049},{"type":31,"value":2468},{"type":25,"tag":2470,"props":2486,"children":2489},{"href":2487,"rel":2488},"https://www.openpolicyagent.org/",[2474],[2490],{"type":31,"value":2487},{"type":25,"tag":60,"props":2492,"children":2493},{},[2494,2499,2500],{"type":25,"tag":38,"props":2495,"children":2496},{},[2497],{"type":31,"value":2498},"GitHub Actions Security",{"type":31,"value":2468},{"type":25,"tag":2470,"props":2501,"children":2504},{"href":2502,"rel":2503},"https://docs.github.com/en/actions/security-guides",[2474],[2505],{"type":31,"value":2502},{"type":25,"tag":60,"props":2507,"children":2508},{},[2509,2514,2515],{"type":25,"tag":38,"props":2510,"children":2511},{},[2512],{"type":31,"value":2513},"OWASP Top 10",{"type":31,"value":2468},{"type":25,"tag":2470,"props":2516,"children":2519},{"href":2517,"rel":2518},"https://owasp.org/www-project-top-ten/",[2474],[2520],{"type":31,"value":2517},{"type":25,"tag":223,"props":2522,"children":2524},{"id":2523},"_92-相关工具",[2525],{"type":31,"value":2526},"9.2 相关工具",{"type":25,"tag":56,"props":2528,"children":2529},{},[2530,2544,2558,2575],{"type":25,"tag":60,"props":2531,"children":2532},{},[2533,2537,2538],{"type":25,"tag":38,"props":2534,"children":2535},{},[2536],{"type":31,"value":899},{"type":31,"value":2468},{"type":25,"tag":2470,"props":2539,"children":2542},{"href":2540,"rel":2541},"https://github.com/gitleaks/gitleaks",[2474],[2543],{"type":31,"value":2540},{"type":25,"tag":60,"props":2545,"children":2546},{},[2547,2551,2552],{"type":25,"tag":38,"props":2548,"children":2549},{},[2550],{"type":31,"value":934},{"type":31,"value":2468},{"type":25,"tag":2470,"props":2553,"children":2556},{"href":2554,"rel":2555},"https://github.com/Yelp/detect-secrets",[2474],[2557],{"type":31,"value":2554},{"type":25,"tag":60,"props":2559,"children":2560},{},[2561,2566,2567,2573],{"type":25,"tag":38,"props":2562,"children":2563},{},[2564],{"type":31,"value":2565},"Snyk",{"type":31,"value":2468},{"type":25,"tag":2470,"props":2568,"children":2571},{"href":2569,"rel":2570},"https://snyk.io/",[2474],[2572],{"type":31,"value":2569},{"type":31,"value":2574}," (依赖漏洞扫描)",{"type":25,"tag":60,"props":2576,"children":2577},{},[2578,2583,2584,2590],{"type":25,"tag":38,"props":2579,"children":2580},{},[2581],{"type":31,"value":2582},"SonarQube",{"type":31,"value":2468},{"type":25,"tag":2470,"props":2585,"children":2588},{"href":2586,"rel":2587},"https://www.sonarqube.org/",[2474],[2589],{"type":31,"value":2586},{"type":31,"value":2591}," (代码质量与安全)",{"type":25,"tag":223,"props":2593,"children":2595},{"id":2594},"_93-本系列其他文章",[2596],{"type":31,"value":2597},"9.3 本系列其他文章",{"type":25,"tag":56,"props":2599,"children":2600},{},[2601,2610,2619,2628],{"type":25,"tag":60,"props":2602,"children":2603},{},[2604],{"type":25,"tag":2470,"props":2605,"children":2607},{"href":2606},"./ai-agent-credential-vault-design",[2608],{"type":31,"value":2609},"AS01: AI Agent Credential Vault Design",{"type":25,"tag":60,"props":2611,"children":2612},{},[2613],{"type":25,"tag":2470,"props":2614,"children":2616},{"href":2615},"./ai-agent-secret-rotation-policy-cadence",[2617],{"type":31,"value":2618},"AS02: AI Agent Secret Rotation Policy",{"type":25,"tag":60,"props":2620,"children":2621},{},[2622],{"type":25,"tag":2470,"props":2623,"children":2625},{"href":2624},"./ai-agent-operation-audit-trail-immutability",[2626],{"type":31,"value":2627},"AS03: AI Agent Operation Audit Trail",{"type":25,"tag":60,"props":2629,"children":2630},{},[2631],{"type":25,"tag":2470,"props":2632,"children":2634},{"href":2633},"./ai-agent-compliance-reporting-automation-evidence",[2635],{"type":31,"value":2636},"AS04: AI Agent Compliance Reporting Automation",{"type":25,"tag":213,"props":2638,"children":2639},{},[],{"type":25,"tag":26,"props":2641,"children":2643},{"id":2642},"_10-总结",[2644],{"type":31,"value":2645},"10. 总结",{"type":25,"tag":34,"props":2647,"children":2648},{},[2649],{"type":31,"value":2650},"在 CI/CD 流程中集成 AI agent 安全测试是构建可靠系统的必要条件。通过三层防御体系（Pre-commit、PR Check、Deployment Gate），结合 TruffleHog（凭证扫描）、OPA（权限审计）和自定义规则（日志脱敏），可以在代码合并前自动检测并阻断大部分安全问题。",{"type":25,"tag":34,"props":2652,"children":2653},{},[2654,2659],{"type":25,"tag":38,"props":2655,"children":2656},{},[2657],{"type":31,"value":2658},"核心要点",{"type":31,"value":54},{"type":25,"tag":2661,"props":2662,"children":2663},"ol",{},[2664,2674,2684,2694],{"type":25,"tag":60,"props":2665,"children":2666},{},[2667,2672],{"type":25,"tag":38,"props":2668,"children":2669},{},[2670],{"type":31,"value":2671},"安全左移",{"type":31,"value":2673},"：越早发现问题，修复成本越低",{"type":25,"tag":60,"props":2675,"children":2676},{},[2677,2682],{"type":25,"tag":38,"props":2678,"children":2679},{},[2680],{"type":31,"value":2681},"自动化优先",{"type":31,"value":2683},"：减少人工干预，提高一致性和覆盖率",{"type":25,"tag":60,"props":2685,"children":2686},{},[2687,2692],{"type":25,"tag":38,"props":2688,"children":2689},{},[2690],{"type":31,"value":2691},"平衡误报",{"type":31,"value":2693},"：建立白名单和反馈机制，持续优化规则",{"type":25,"tag":60,"props":2695,"children":2696},{},[2697,2701],{"type":25,"tag":38,"props":2698,"children":2699},{},[2700],{"type":31,"value":339},{"type":31,"value":2702},"：让安全成为开发流程的自然部分，而非额外负担",{"type":25,"tag":34,"props":2704,"children":2705},{},[2706],{"type":31,"value":2707},"通过本文提供的方案和工具，你可以为自己的 AI agent 项目构建一套完整的安全测试流水线，显著降低凭证泄露、权限过宽和日志污染的风险。",{"title":7,"searchDepth":2709,"depth":2709,"links":2710},3,[2711,2713,2718,2728,2747,2762,2774,2782,2787,2793,2798],{"id":28,"depth":2712,"text":32},2,{"id":218,"depth":2712,"text":221,"children":2714},[2715,2716,2717],{"id":225,"depth":2709,"text":228},{"id":288,"depth":2709,"text":291},{"id":344,"depth":2709,"text":347},{"id":611,"depth":2712,"text":614,"children":2719},[2720,2721,2727],{"id":617,"depth":2709,"text":620},{"id":801,"depth":2709,"text":804,"children":2722},[2723,2725,2726],{"id":808,"depth":2724,"text":808},4,{"id":1005,"depth":2724,"text":1005},{"id":1128,"depth":2724,"text":1128},{"id":1248,"depth":2709,"text":1251},{"id":1268,"depth":2712,"text":1271,"children":2729},[2730,2736,2742,2746],{"id":1274,"depth":2709,"text":1277,"children":2731},[2732,2733,2734],{"id":1280,"depth":2724,"text":1280},{"id":1296,"depth":2724,"text":1296},{"id":1327,"depth":2724,"text":2735},"配置文件（.trufflehog.yaml）",{"id":1350,"depth":2709,"text":1353,"children":2737},[2738,2739,2741],{"id":1356,"depth":2724,"text":1359},{"id":1371,"depth":2724,"text":2740},"配置 .pre-commit-config.yaml",{"id":1392,"depth":2724,"text":1395},{"id":1425,"depth":2709,"text":1428,"children":2743},[2744,2745],{"id":1431,"depth":2724,"text":1434},{"id":1457,"depth":2724,"text":1460},{"id":1502,"depth":2709,"text":1505},{"id":1525,"depth":2712,"text":1528,"children":2748},[2749,2753,2757,2758],{"id":1531,"depth":2709,"text":1534,"children":2750},[2751],{"id":1537,"depth":2724,"text":2752},"权限声明文件（agent-permissions.json）",{"id":1561,"depth":2709,"text":1564,"children":2754},[2755],{"id":1567,"depth":2724,"text":2756},"策略文件（policies/agent-permissions.rego）",{"id":1591,"depth":2709,"text":1594},{"id":1623,"depth":2709,"text":1626,"children":2759},[2760,2761],{"id":1629,"depth":2724,"text":1629},{"id":1643,"depth":2724,"text":1643},{"id":1660,"depth":2712,"text":1663,"children":2763},[2764,2768,2773],{"id":1666,"depth":2709,"text":1669,"children":2765},[2766],{"id":1672,"depth":2724,"text":2767},"规则配置文件（config/log-rules.json）",{"id":1694,"depth":2709,"text":1697,"children":2769},[2770,2772],{"id":1700,"depth":2724,"text":2771},"Python 实现（scripts/check_log_sanitization.py）",{"id":1724,"depth":2724,"text":1724},{"id":1738,"depth":2709,"text":1741},{"id":1761,"depth":2712,"text":1764,"children":2775},[2776,2777,2781],{"id":1767,"depth":2709,"text":1770},{"id":1911,"depth":2709,"text":1914,"children":2778},[2779,2780],{"id":1917,"depth":2724,"text":1920},{"id":1932,"depth":2724,"text":1935},{"id":1947,"depth":2709,"text":1950},{"id":1990,"depth":2712,"text":1993,"children":2783},[2784,2785,2786],{"id":1996,"depth":2709,"text":1999},{"id":2011,"depth":2709,"text":2014},{"id":2030,"depth":2709,"text":2033},{"id":2048,"depth":2712,"text":2051,"children":2788},[2789,2790,2791,2792],{"id":2054,"depth":2709,"text":2057},{"id":2174,"depth":2709,"text":2177},{"id":2274,"depth":2709,"text":2277},{"id":2359,"depth":2709,"text":2362},{"id":2447,"depth":2712,"text":2450,"children":2794},[2795,2796,2797],{"id":2453,"depth":2709,"text":2456},{"id":2523,"depth":2709,"text":2526},{"id":2594,"depth":2709,"text":2597},{"id":2642,"depth":2712,"text":2645},"content:topics:ai:ai-agent-security-testing-ci-credential-scan.md","content","topics/ai/ai-agent-security-testing-ci-credential-scan.md","topics/ai/ai-agent-security-testing-ci-credential-scan","md",[2805,3955,4901],{"_path":2806,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":2807,"description":2808,"date":2809,"topic":5,"author":2810,"tags":2811,"image":2817,"imageAlt":2818,"pexelsPhotoId":2819,"pexelsUrl":2820,"readingTime":2821,"body":2822,"_type":1473,"_id":3952,"_source":2800,"_file":3953,"_stem":3954,"_extension":2803},"/topics/ai/cursor-keyboard-shortcuts-cheatsheet","Cursor 快捷键速查表（macOS/Windows）：从“会用”到“能提效”的 10 个工作流","把 Cursor 常用快捷键按任务分组（查代码、改代码、多文件、对话、审查与回滚），给出可直接照抄的工作流与最小回归清单，避免“快捷键背了也没变快”。","2026-03-02","HTMLPAGE 团队",[2812,2813,2814,2815,2816],"Cursor","快捷键","AI IDE","VS Code","开发效率","/images/topics/ai/cursor-keyboard-shortcuts-cheatsheet.jpg","彩色机械键盘与鼠标的工作台面",34563105,"https://www.pexels.com/photo/colorful-mechanical-keyboard-and-mouse-setup-34563105/",12,{"type":22,"children":2823,"toc":3926},[2824,2829,2847,2852,2879,2884,2920,2923,2929,2934,2967,2972,2995,2998,3004,3009,3227,3235,3238,3244,3250,3269,3277,3298,3303,3309,3324,3355,3360,3373,3379,3398,3416,3424,3429,3435,3440,3461,3469,3475,3480,3503,3508,3514,3527,3533,3550,3568,3574,3585,3603,3609,3620,3626,3631,3674,3677,3683,3691,3744,3747,3753,3759,3764,3769,3792,3810,3815,3840,3843,3849,3855,3860,3866,3871,3877,3882,3885,3891],{"type":25,"tag":34,"props":2825,"children":2826},{},[2827],{"type":31,"value":2828},"如果你在搜“Cursor 快捷键”，你大概率不是想背一张表，而是想解决这类问题：",{"type":25,"tag":56,"props":2830,"children":2831},{},[2832,2837,2842],{"type":25,"tag":60,"props":2833,"children":2834},{},[2835],{"type":31,"value":2836},"为什么我用了 AI，还是很慢？（对话来回太多、改动不可控）",{"type":25,"tag":60,"props":2838,"children":2839},{},[2840],{"type":31,"value":2841},"为什么它“看起来懂了”，却改错文件/改出回归？（上下文与范围没锁住）",{"type":25,"tag":60,"props":2843,"children":2844},{},[2845],{"type":31,"value":2846},"多文件改动怎么做得安全？（验收、回滚、最小回归集）",{"type":25,"tag":34,"props":2848,"children":2849},{},[2850],{"type":31,"value":2851},"这篇文章给你两份东西：",{"type":25,"tag":2661,"props":2853,"children":2854},{},[2855,2867],{"type":25,"tag":60,"props":2856,"children":2857},{},[2858,2860,2865],{"type":31,"value":2859},"一张",{"type":25,"tag":38,"props":2861,"children":2862},{},[2863],{"type":31,"value":2864},"按任务分组",{"type":31,"value":2866},"的快捷键表（不是按功能堆在一起）",{"type":25,"tag":60,"props":2868,"children":2869},{},[2870,2872,2877],{"type":31,"value":2871},"一套“从需求到落地”的",{"type":25,"tag":38,"props":2873,"children":2874},{},[2875],{"type":31,"value":2876},"最小闭环工作流",{"type":31,"value":2878},"（每一步都有快捷键）",{"type":25,"tag":34,"props":2880,"children":2881},{},[2882],{"type":31,"value":2883},"想看系统玩法：",{"type":25,"tag":56,"props":2885,"children":2886},{},[2887,2898,2909],{"type":25,"tag":60,"props":2888,"children":2889},{},[2890,2892],{"type":31,"value":2891},"入门教程看：",{"type":25,"tag":2470,"props":2893,"children":2895},{"href":2894},"/topics/ai/cursor-tutorial",[2896],{"type":31,"value":2897},"Cursor 使用教程（2026）",{"type":25,"tag":60,"props":2899,"children":2900},{},[2901,2903],{"type":31,"value":2902},"进阶玩法看：",{"type":25,"tag":2470,"props":2904,"children":2906},{"href":2905},"/topics/ai/cursor-editor-guide",[2907],{"type":31,"value":2908},"Cursor 编辑器深度玩法",{"type":25,"tag":60,"props":2910,"children":2911},{},[2912,2914],{"type":31,"value":2913},"规则与忽略看：",{"type":25,"tag":2470,"props":2915,"children":2917},{"href":2916},"/topics/ai/cursor-rules-cursorrules",[2918],{"type":31,"value":2919},"Cursor Rules 与 .cursorrules",{"type":25,"tag":213,"props":2921,"children":2922},{},[],{"type":25,"tag":26,"props":2924,"children":2926},{"id":2925},"先给结论提效不是按得快而是闭环更短",[2927],{"type":31,"value":2928},"先给结论：提效不是“按得快”，而是“闭环更短”",{"type":25,"tag":34,"props":2930,"children":2931},{},[2932],{"type":31,"value":2933},"你可以把 Cursor 的快捷键理解为 3 条流水线：",{"type":25,"tag":56,"props":2935,"children":2936},{},[2937,2947,2957],{"type":25,"tag":60,"props":2938,"children":2939},{},[2940,2945],{"type":25,"tag":38,"props":2941,"children":2942},{},[2943],{"type":31,"value":2944},"改一小段",{"type":31,"value":2946},"（内联编辑）：把改动限制在一个函数/一段样式",{"type":25,"tag":60,"props":2948,"children":2949},{},[2950,2955],{"type":25,"tag":38,"props":2951,"children":2952},{},[2953],{"type":31,"value":2954},"改一组文件",{"type":31,"value":2956},"（Composer）：把改动限制在一组明确文件，并要求输出 diff + 验收点",{"type":25,"tag":60,"props":2958,"children":2959},{},[2960,2965],{"type":25,"tag":38,"props":2961,"children":2962},{},[2963],{"type":31,"value":2964},"聊清楚再动手",{"type":31,"value":2966},"（侧边对话）：先对齐目标、范围、验收、回滚",{"type":25,"tag":34,"props":2968,"children":2969},{},[2970],{"type":31,"value":2971},"当你觉得“它乱改/改太大”时，往往不是快捷键没记住，而是缺了两件事：",{"type":25,"tag":56,"props":2973,"children":2974},{},[2975,2985],{"type":25,"tag":60,"props":2976,"children":2977},{},[2978,2980],{"type":31,"value":2979},"没有在动手前锁定",{"type":25,"tag":38,"props":2981,"children":2982},{},[2983],{"type":31,"value":2984},"范围",{"type":25,"tag":60,"props":2986,"children":2987},{},[2988,2990],{"type":31,"value":2989},"没有在接受改动前准备",{"type":25,"tag":38,"props":2991,"children":2992},{},[2993],{"type":31,"value":2994},"验收/回滚",{"type":25,"tag":213,"props":2996,"children":2997},{},[],{"type":25,"tag":26,"props":2999,"children":3001},{"id":3000},"快捷键速查表按任务分组",[3002],{"type":31,"value":3003},"快捷键速查表（按任务分组）",{"type":25,"tag":34,"props":3005,"children":3006},{},[3007],{"type":31,"value":3008},"说明：下表按“你正在做什么”组织，而不是按“功能名字”组织。不同版本快捷键可能略有差异，但核心逻辑一致。",{"type":25,"tag":110,"props":3010,"children":3011},{},[3012,3038],{"type":25,"tag":114,"props":3013,"children":3014},{},[3015],{"type":25,"tag":118,"props":3016,"children":3017},{},[3018,3023,3028,3033],{"type":25,"tag":122,"props":3019,"children":3020},{},[3021],{"type":31,"value":3022},"任务",{"type":25,"tag":122,"props":3024,"children":3025},{},[3026],{"type":31,"value":3027},"macOS",{"type":25,"tag":122,"props":3029,"children":3030},{},[3031],{"type":31,"value":3032},"Windows",{"type":25,"tag":122,"props":3034,"children":3035},{},[3036],{"type":31,"value":3037},"你该在什么时候用",{"type":25,"tag":138,"props":3039,"children":3040},{},[3041,3072,3103,3134,3165,3196],{"type":25,"tag":118,"props":3042,"children":3043},{},[3044,3049,3058,3067],{"type":25,"tag":145,"props":3045,"children":3046},{},[3047],{"type":31,"value":3048},"改一小段（最安全）",{"type":25,"tag":145,"props":3050,"children":3051},{},[3052],{"type":25,"tag":240,"props":3053,"children":3055},{"className":3054},[],[3056],{"type":31,"value":3057},"Cmd + K",{"type":25,"tag":145,"props":3059,"children":3060},{},[3061],{"type":25,"tag":240,"props":3062,"children":3064},{"className":3063},[],[3065],{"type":31,"value":3066},"Ctrl + K",{"type":25,"tag":145,"props":3068,"children":3069},{},[3070],{"type":31,"value":3071},"只想改一个函数/一段 CSS，不想动别的",{"type":25,"tag":118,"props":3073,"children":3074},{},[3075,3080,3089,3098],{"type":25,"tag":145,"props":3076,"children":3077},{},[3078],{"type":31,"value":3079},"打开 AI 对话（先对齐再动手）",{"type":25,"tag":145,"props":3081,"children":3082},{},[3083],{"type":25,"tag":240,"props":3084,"children":3086},{"className":3085},[],[3087],{"type":31,"value":3088},"Cmd + L",{"type":25,"tag":145,"props":3090,"children":3091},{},[3092],{"type":25,"tag":240,"props":3093,"children":3095},{"className":3094},[],[3096],{"type":31,"value":3097},"Ctrl + L",{"type":25,"tag":145,"props":3099,"children":3100},{},[3101],{"type":31,"value":3102},"需要澄清目标、制定步骤、给验收点",{"type":25,"tag":118,"props":3104,"children":3105},{},[3106,3111,3120,3129],{"type":25,"tag":145,"props":3107,"children":3108},{},[3109],{"type":31,"value":3110},"多文件编辑（有组织地改一组文件）",{"type":25,"tag":145,"props":3112,"children":3113},{},[3114],{"type":25,"tag":240,"props":3115,"children":3117},{"className":3116},[],[3118],{"type":31,"value":3119},"Cmd + I",{"type":25,"tag":145,"props":3121,"children":3122},{},[3123],{"type":25,"tag":240,"props":3124,"children":3126},{"className":3125},[],[3127],{"type":31,"value":3128},"Ctrl + I",{"type":25,"tag":145,"props":3130,"children":3131},{},[3132],{"type":31,"value":3133},"改动涉及多个文件：组件+样式+测试",{"type":25,"tag":118,"props":3135,"children":3136},{},[3137,3142,3151,3160],{"type":25,"tag":145,"props":3138,"children":3139},{},[3140],{"type":31,"value":3141},"把选中代码加入对话上下文",{"type":25,"tag":145,"props":3143,"children":3144},{},[3145],{"type":25,"tag":240,"props":3146,"children":3148},{"className":3147},[],[3149],{"type":31,"value":3150},"Cmd + Shift + L",{"type":25,"tag":145,"props":3152,"children":3153},{},[3154],{"type":25,"tag":240,"props":3155,"children":3157},{"className":3156},[],[3158],{"type":31,"value":3159},"Ctrl + Shift + L",{"type":25,"tag":145,"props":3161,"children":3162},{},[3163],{"type":31,"value":3164},"让 AI 只看你选的片段（降低噪音）",{"type":25,"tag":118,"props":3166,"children":3167},{},[3168,3173,3182,3191],{"type":25,"tag":145,"props":3169,"children":3170},{},[3171],{"type":31,"value":3172},"接受当前建议",{"type":25,"tag":145,"props":3174,"children":3175},{},[3176],{"type":25,"tag":240,"props":3177,"children":3179},{"className":3178},[],[3180],{"type":31,"value":3181},"Cmd + Y",{"type":25,"tag":145,"props":3183,"children":3184},{},[3185],{"type":25,"tag":240,"props":3186,"children":3188},{"className":3187},[],[3189],{"type":31,"value":3190},"Ctrl + Y",{"type":25,"tag":145,"props":3192,"children":3193},{},[3194],{"type":31,"value":3195},"你已经准备好验收/回滚，并确认改动范围",{"type":25,"tag":118,"props":3197,"children":3198},{},[3199,3204,3213,3222],{"type":25,"tag":145,"props":3200,"children":3201},{},[3202],{"type":31,"value":3203},"拒绝当前建议",{"type":25,"tag":145,"props":3205,"children":3206},{},[3207],{"type":25,"tag":240,"props":3208,"children":3210},{"className":3209},[],[3211],{"type":31,"value":3212},"Cmd + N",{"type":25,"tag":145,"props":3214,"children":3215},{},[3216],{"type":25,"tag":240,"props":3217,"children":3219},{"className":3218},[],[3220],{"type":31,"value":3221},"Ctrl + N",{"type":25,"tag":145,"props":3223,"children":3224},{},[3225],{"type":31,"value":3226},"改得太大、改错方向，立刻收手",{"type":25,"tag":487,"props":3228,"children":3229},{},[3230],{"type":25,"tag":34,"props":3231,"children":3232},{},[3233],{"type":31,"value":3234},"小技巧：把“改一小段”当默认路径。只有当你能清晰写出“会改哪几类文件、怎么验收”时再进入多文件。",{"type":25,"tag":213,"props":3236,"children":3237},{},[],{"type":25,"tag":26,"props":3239,"children":3241},{"id":3240},"_10-个可直接照抄的提效工作流每个都能闭环",[3242],{"type":31,"value":3243},"10 个可直接照抄的提效工作流（每个都能闭环）",{"type":25,"tag":223,"props":3245,"children":3247},{"id":3246},"工作流-1需求计划小步改新手最稳",[3248],{"type":31,"value":3249},"工作流 1：需求→计划→小步改（新手最稳）",{"type":25,"tag":2661,"props":3251,"children":3252},{},[3253,3264],{"type":25,"tag":60,"props":3254,"children":3255},{},[3256,3262],{"type":25,"tag":240,"props":3257,"children":3259},{"className":3258},[],[3260],{"type":31,"value":3261},"Cmd/Ctrl + L",{"type":31,"value":3263}," 打开对话",{"type":25,"tag":60,"props":3265,"children":3266},{},[3267],{"type":31,"value":3268},"先发这段（可复制）：",{"type":25,"tag":487,"props":3270,"children":3271},{},[3272],{"type":25,"tag":34,"props":3273,"children":3274},{},[3275],{"type":31,"value":3276},"目标：……\n范围：只修改以下文件/模块：……\n非目标：……（明确不做）\n验收：……（可测试/可手动检查）\n输出格式：先给计划，再逐步执行；每一步写出 diff 摘要。",{"type":25,"tag":2661,"props":3278,"children":3279},{"start":2709},[3280,3285],{"type":25,"tag":60,"props":3281,"children":3282},{},[3283],{"type":31,"value":3284},"让 AI 先给“计划（3~6 步）”，你确认后再执行",{"type":25,"tag":60,"props":3286,"children":3287},{},[3288,3290,3296],{"type":31,"value":3289},"任何一步涉及改代码：优先回到编辑区，选中片段用 ",{"type":25,"tag":240,"props":3291,"children":3293},{"className":3292},[],[3294],{"type":31,"value":3295},"Cmd/Ctrl + K",{"type":31,"value":3297}," 小步改",{"type":25,"tag":34,"props":3299,"children":3300},{},[3301],{"type":31,"value":3302},"为什么有效：你把“想法”变成了“可执行约束”，这就是 GEO（面向 AI/模型的可理解结构）。",{"type":25,"tag":223,"props":3304,"children":3306},{"id":3305},"工作流-2只改一个函数高频低风险",[3307],{"type":31,"value":3308},"工作流 2：只改一个函数（高频、低风险）",{"type":25,"tag":56,"props":3310,"children":3311},{},[3312],{"type":25,"tag":60,"props":3313,"children":3314},{},[3315,3317,3322],{"type":31,"value":3316},"选中函数 → ",{"type":25,"tag":240,"props":3318,"children":3320},{"className":3319},[],[3321],{"type":31,"value":3295},{"type":31,"value":3323}," → 输入指令：",{"type":25,"tag":487,"props":3325,"children":3326},{},[3327,3332],{"type":25,"tag":34,"props":3328,"children":3329},{},[3330],{"type":31,"value":3331},"把这段改成更可读：",{"type":25,"tag":56,"props":3333,"children":3334},{},[3335,3340,3345,3350],{"type":25,"tag":60,"props":3336,"children":3337},{},[3338],{"type":31,"value":3339},"用 async/await",{"type":25,"tag":60,"props":3341,"children":3342},{},[3343],{"type":31,"value":3344},"错误处理不要吞掉",{"type":25,"tag":60,"props":3346,"children":3347},{},[3348],{"type":31,"value":3349},"添加类型（若可推断）",{"type":25,"tag":60,"props":3351,"children":3352},{},[3353],{"type":31,"value":3354},"不要改函数签名",{"type":25,"tag":34,"props":3356,"children":3357},{},[3358],{"type":31,"value":3359},"验收方式（强制）：",{"type":25,"tag":56,"props":3361,"children":3362},{},[3363,3368],{"type":25,"tag":60,"props":3364,"children":3365},{},[3366],{"type":31,"value":3367},"输出前后函数行为一致（输入/输出）",{"type":25,"tag":60,"props":3369,"children":3370},{},[3371],{"type":31,"value":3372},"失败分支有可观测日志（不要悄悄 return null）",{"type":25,"tag":223,"props":3374,"children":3376},{"id":3375},"工作流-3多文件改动先定文件清单",[3377],{"type":31,"value":3378},"工作流 3：多文件改动（先定“文件清单”）",{"type":25,"tag":2661,"props":3380,"children":3381},{},[3382,3393],{"type":25,"tag":60,"props":3383,"children":3384},{},[3385,3391],{"type":25,"tag":240,"props":3386,"children":3388},{"className":3387},[],[3389],{"type":31,"value":3390},"Cmd/Ctrl + I",{"type":31,"value":3392}," 进入多文件",{"type":25,"tag":60,"props":3394,"children":3395},{},[3396],{"type":31,"value":3397},"先让 AI 输出：",{"type":25,"tag":56,"props":3399,"children":3400},{},[3401,3406,3411],{"type":25,"tag":60,"props":3402,"children":3403},{},[3404],{"type":31,"value":3405},"预计会改哪些文件（最多 5 个）",{"type":25,"tag":60,"props":3407,"children":3408},{},[3409],{"type":31,"value":3410},"每个文件改什么",{"type":25,"tag":60,"props":3412,"children":3413},{},[3414],{"type":31,"value":3415},"每一步怎么验收",{"type":25,"tag":2661,"props":3417,"children":3418},{"start":2709},[3419],{"type":25,"tag":60,"props":3420,"children":3421},{},[3422],{"type":31,"value":3423},"你确认文件清单后再开始生成改动",{"type":25,"tag":34,"props":3425,"children":3426},{},[3427],{"type":31,"value":3428},"关键点：多文件最容易翻车的是“它把你没想到的文件也改了”。所以文件清单是第一道闸门。",{"type":25,"tag":223,"props":3430,"children":3432},{"id":3431},"工作流-4把上下文噪音砍掉防跑偏",[3433],{"type":31,"value":3434},"工作流 4：把“上下文噪音”砍掉（防跑偏）",{"type":25,"tag":34,"props":3436,"children":3437},{},[3438],{"type":31,"value":3439},"当你怀疑它在胡说/乱改时：",{"type":25,"tag":56,"props":3441,"children":3442},{},[3443,3456],{"type":25,"tag":60,"props":3444,"children":3445},{},[3446,3448,3454],{"type":31,"value":3447},"只选择关键代码片段 → ",{"type":25,"tag":240,"props":3449,"children":3451},{"className":3450},[],[3452],{"type":31,"value":3453},"Cmd/Ctrl + Shift + L",{"type":31,"value":3455}," 加入对话",{"type":25,"tag":60,"props":3457,"children":3458},{},[3459],{"type":31,"value":3460},"然后在对话里要求：",{"type":25,"tag":487,"props":3462,"children":3463},{},[3464],{"type":25,"tag":34,"props":3465,"children":3466},{},[3467],{"type":31,"value":3468},"只基于我提供的代码片段回答，不要假设其它文件存在。",{"type":25,"tag":223,"props":3470,"children":3472},{"id":3471},"工作流-5生成变更说明让-code-review-变快",[3473],{"type":31,"value":3474},"工作流 5：生成变更说明（让 code review 变快）",{"type":25,"tag":34,"props":3476,"children":3477},{},[3478],{"type":31,"value":3479},"改完后在对话里让它输出：",{"type":25,"tag":56,"props":3481,"children":3482},{},[3483,3488,3493,3498],{"type":25,"tag":60,"props":3484,"children":3485},{},[3486],{"type":31,"value":3487},"改动摘要（3~7 条）",{"type":25,"tag":60,"props":3489,"children":3490},{},[3491],{"type":31,"value":3492},"风险点（依赖/边界条件）",{"type":25,"tag":60,"props":3494,"children":3495},{},[3496],{"type":31,"value":3497},"回滚方式",{"type":25,"tag":60,"props":3499,"children":3500},{},[3501],{"type":31,"value":3502},"验收步骤",{"type":25,"tag":34,"props":3504,"children":3505},{},[3506],{"type":31,"value":3507},"这套结构能直接贴进 PR 描述。",{"type":25,"tag":223,"props":3509,"children":3511},{"id":3510},"工作流-6写最小回归集不写回归-等事故",[3512],{"type":31,"value":3513},"工作流 6：写“最小回归集”（不写回归 = 等事故）",{"type":25,"tag":34,"props":3515,"children":3516},{},[3517,3519,3525],{"type":31,"value":3518},"每次改动都至少做 10 条最小回归（见下文清单）。你可以把它写在 ",{"type":25,"tag":240,"props":3520,"children":3522},{"className":3521},[],[3523],{"type":31,"value":3524},"README",{"type":31,"value":3526}," 或团队 wiki。",{"type":25,"tag":223,"props":3528,"children":3530},{"id":3529},"工作流-7把接受建议变成最后一步",[3531],{"type":31,"value":3532},"工作流 7：把“接受建议”变成最后一步",{"type":25,"tag":34,"props":3534,"children":3535},{},[3536,3542,3544,3549],{"type":25,"tag":240,"props":3537,"children":3539},{"className":3538},[],[3540],{"type":31,"value":3541},"Cmd/Ctrl + Y",{"type":31,"value":3543}," 应该是",{"type":25,"tag":38,"props":3545,"children":3546},{},[3547],{"type":31,"value":3548},"最后一步",{"type":31,"value":54},{"type":25,"tag":56,"props":3551,"children":3552},{},[3553,3558,3563],{"type":25,"tag":60,"props":3554,"children":3555},{},[3556],{"type":31,"value":3557},"你已经看过 diff",{"type":25,"tag":60,"props":3559,"children":3560},{},[3561],{"type":31,"value":3562},"你能说清楚“怎么验收”",{"type":25,"tag":60,"props":3564,"children":3565},{},[3566],{"type":31,"value":3567},"你知道“怎么回滚”",{"type":25,"tag":223,"props":3569,"children":3571},{"id":3570},"工作流-8拒绝建议不是失败是风控动作",[3572],{"type":31,"value":3573},"工作流 8：拒绝建议不是失败，是风控动作",{"type":25,"tag":34,"props":3575,"children":3576},{},[3577,3583],{"type":25,"tag":240,"props":3578,"children":3580},{"className":3579},[],[3581],{"type":31,"value":3582},"Cmd/Ctrl + N",{"type":31,"value":3584}," 的使用时机：",{"type":25,"tag":56,"props":3586,"children":3587},{},[3588,3593,3598],{"type":25,"tag":60,"props":3589,"children":3590},{},[3591],{"type":31,"value":3592},"它开始改你没提过的东西（范围漂移）",{"type":25,"tag":60,"props":3594,"children":3595},{},[3596],{"type":31,"value":3597},"它改了 10 个文件但你只想改 1 个",{"type":25,"tag":60,"props":3599,"children":3600},{},[3601],{"type":31,"value":3602},"它为了“更优雅”引入新依赖/新抽象",{"type":25,"tag":223,"props":3604,"children":3606},{"id":3605},"工作流-9重复任务做成模板提示词不是一次性",[3607],{"type":31,"value":3608},"工作流 9：重复任务做成模板（提示词不是一次性）",{"type":25,"tag":34,"props":3610,"children":3611},{},[3612,3614,3618],{"type":31,"value":3613},"把高频任务（比如“写组件+样式+验收”）固化成模板，放进 Rules（见：",{"type":25,"tag":2470,"props":3615,"children":3616},{"href":2916},[3617],{"type":31,"value":2919},{"type":31,"value":3619},"）。",{"type":25,"tag":223,"props":3621,"children":3623},{"id":3622},"工作流-10把快捷键表做成你自己的任务表",[3624],{"type":31,"value":3625},"工作流 10：把“快捷键表”做成你自己的任务表",{"type":25,"tag":34,"props":3627,"children":3628},{},[3629],{"type":31,"value":3630},"你不需要记住所有快捷键，只需要记住：",{"type":25,"tag":56,"props":3632,"children":3633},{},[3634,3644,3654,3664],{"type":25,"tag":60,"props":3635,"children":3636},{},[3637,3639],{"type":31,"value":3638},"小步改：",{"type":25,"tag":240,"props":3640,"children":3642},{"className":3641},[],[3643],{"type":31,"value":3295},{"type":25,"tag":60,"props":3645,"children":3646},{},[3647,3649],{"type":31,"value":3648},"先对齐：",{"type":25,"tag":240,"props":3650,"children":3652},{"className":3651},[],[3653],{"type":31,"value":3261},{"type":25,"tag":60,"props":3655,"children":3656},{},[3657,3659],{"type":31,"value":3658},"多文件：",{"type":25,"tag":240,"props":3660,"children":3662},{"className":3661},[],[3663],{"type":31,"value":3390},{"type":25,"tag":60,"props":3665,"children":3666},{},[3667,3669],{"type":31,"value":3668},"上下文聚焦：",{"type":25,"tag":240,"props":3670,"children":3672},{"className":3671},[],[3673],{"type":31,"value":3453},{"type":25,"tag":213,"props":3675,"children":3676},{},[],{"type":25,"tag":26,"props":3678,"children":3680},{"id":3679},"必交付物-1最小回归任务清单10-条通用",[3681],{"type":31,"value":3682},"必交付物 1：最小回归任务清单（10 条，通用）",{"type":25,"tag":487,"props":3684,"children":3685},{},[3686],{"type":25,"tag":34,"props":3687,"children":3688},{},[3689],{"type":31,"value":3690},"这份清单的意义：让每次 AI 改动都能“被验证”。否则你只是把不可控变成了更快的不可控。",{"type":25,"tag":2661,"props":3692,"children":3693},{},[3694,3699,3704,3709,3714,3719,3724,3729,3734,3739],{"type":25,"tag":60,"props":3695,"children":3696},{},[3697],{"type":31,"value":3698},"关键路径能跑通（手动点击/请求一次）",{"type":25,"tag":60,"props":3700,"children":3701},{},[3702],{"type":31,"value":3703},"错误路径能触发（模拟一次失败输入）",{"type":25,"tag":60,"props":3705,"children":3706},{},[3707],{"type":31,"value":3708},"控制台无新增错误（至少关注 1 次真实操作）",{"type":25,"tag":60,"props":3710,"children":3711},{},[3712],{"type":31,"value":3713},"关键 UI 未错位（移动端/桌面端各看一眼）",{"type":25,"tag":60,"props":3715,"children":3716},{},[3717],{"type":31,"value":3718},"刷新后状态正确（尤其是表单/列表）",{"type":25,"tag":60,"props":3720,"children":3721},{},[3722],{"type":31,"value":3723},"路由跳转没断（从入口到目标页）",{"type":25,"tag":60,"props":3725,"children":3726},{},[3727],{"type":31,"value":3728},"相关接口未改变契约（字段名/类型）",{"type":25,"tag":60,"props":3730,"children":3731},{},[3732],{"type":31,"value":3733},"性能没有明显退化（首屏、交互卡顿）",{"type":25,"tag":60,"props":3735,"children":3736},{},[3737],{"type":31,"value":3738},"回滚方案可执行（知道回滚哪几个文件/commit）",{"type":25,"tag":60,"props":3740,"children":3741},{},[3742],{"type":31,"value":3743},"写下“这次改动解决了什么、风险是什么”（可贴 PR）",{"type":25,"tag":213,"props":3745,"children":3746},{},[],{"type":25,"tag":26,"props":3748,"children":3750},{"id":3749},"必交付物-2失败案例复盘真实会发生",[3751],{"type":31,"value":3752},"必交付物 2：失败案例复盘（真实会发生）",{"type":25,"tag":223,"props":3754,"children":3756},{"id":3755},"现象快捷键用得很熟但交付还是慢",[3757],{"type":31,"value":3758},"现象：快捷键用得很熟，但交付还是慢",{"type":25,"tag":34,"props":3760,"children":3761},{},[3762],{"type":31,"value":3763},"典型原因：你把 Cursor 当成“更聪明的搜索框”，不断对话，直到它给出你想要的答案。",{"type":25,"tag":34,"props":3765,"children":3766},{},[3767],{"type":31,"value":3768},"复现路径：",{"type":25,"tag":56,"props":3770,"children":3771},{},[3772,3777,3782,3787],{"type":25,"tag":60,"props":3773,"children":3774},{},[3775],{"type":31,"value":3776},"你直接说“把页面做得更好看、更高级”",{"type":25,"tag":60,"props":3778,"children":3779},{},[3780],{"type":31,"value":3781},"AI 开始大改样式、抽象组件、甚至引入新依赖",{"type":25,"tag":60,"props":3783,"children":3784},{},[3785],{"type":31,"value":3786},"你为了省事按了“接受建议”",{"type":25,"tag":60,"props":3788,"children":3789},{},[3790],{"type":31,"value":3791},"最后发现：设计没统一、移动端崩、甚至埋了性能问题",{"type":25,"tag":34,"props":3793,"children":3794},{},[3795,3797,3801,3803,3808],{"type":31,"value":3796},"根因：缺少",{"type":25,"tag":38,"props":3798,"children":3799},{},[3800],{"type":31,"value":2984},{"type":31,"value":3802},"与",{"type":25,"tag":38,"props":3804,"children":3805},{},[3806],{"type":31,"value":3807},"验收",{"type":31,"value":3809},"。",{"type":25,"tag":34,"props":3811,"children":3812},{},[3813],{"type":31,"value":3814},"修复方式（可照抄）：",{"type":25,"tag":56,"props":3816,"children":3817},{},[3818,3823,3835],{"type":25,"tag":60,"props":3819,"children":3820},{},[3821],{"type":31,"value":3822},"把需求拆成 3 个可验证目标：例如“按钮样式统一”“首屏 CTA 更明显”“移动端间距不挤”",{"type":25,"tag":60,"props":3824,"children":3825},{},[3826,3828,3833],{"type":31,"value":3827},"每个目标只用 ",{"type":25,"tag":240,"props":3829,"children":3831},{"className":3830},[],[3832],{"type":31,"value":3295},{"type":31,"value":3834}," 改一个局部",{"type":25,"tag":60,"props":3836,"children":3837},{},[3838],{"type":31,"value":3839},"每次接受建议前跑一遍“最小回归集”",{"type":25,"tag":213,"props":3841,"children":3842},{},[],{"type":25,"tag":26,"props":3844,"children":3846},{"id":3845},"faq高频问题",[3847],{"type":31,"value":3848},"FAQ（高频问题）",{"type":25,"tag":223,"props":3850,"children":3852},{"id":3851},"q1我应该先记快捷键还是先学工作流",[3853],{"type":31,"value":3854},"Q1：我应该先记快捷键还是先学工作流？",{"type":25,"tag":34,"props":3856,"children":3857},{},[3858],{"type":31,"value":3859},"先学工作流。快捷键只是把工作流的步骤变短。",{"type":25,"tag":223,"props":3861,"children":3863},{"id":3862},"q2为什么我一用多文件就容易翻车",[3864],{"type":31,"value":3865},"Q2：为什么我一用多文件就容易翻车？",{"type":25,"tag":34,"props":3867,"children":3868},{},[3869],{"type":31,"value":3870},"因为多文件意味着范围更大、依赖更多、验收更难。先锁定“文件清单 + 每步验收”，再让它动手。",{"type":25,"tag":223,"props":3872,"children":3874},{"id":3873},"q3有没有万能提示词",[3875],{"type":31,"value":3876},"Q3：有没有“万能提示词”？",{"type":25,"tag":34,"props":3878,"children":3879},{},[3880],{"type":31,"value":3881},"没有，但有“万能结构”：目标、范围、非目标、验收、输出格式。",{"type":25,"tag":213,"props":3883,"children":3884},{},[],{"type":25,"tag":26,"props":3886,"children":3888},{"id":3887},"延伸阅读建议按顺序",[3889],{"type":31,"value":3890},"延伸阅读（建议按顺序）",{"type":25,"tag":56,"props":3892,"children":3893},{},[3894,3901,3908,3915],{"type":25,"tag":60,"props":3895,"children":3896},{},[3897],{"type":25,"tag":2470,"props":3898,"children":3899},{"href":2894},[3900],{"type":31,"value":2897},{"type":25,"tag":60,"props":3902,"children":3903},{},[3904],{"type":25,"tag":2470,"props":3905,"children":3906},{"href":2905},[3907],{"type":31,"value":2908},{"type":25,"tag":60,"props":3909,"children":3910},{},[3911],{"type":25,"tag":2470,"props":3912,"children":3913},{"href":2916},[3914],{"type":31,"value":2919},{"type":25,"tag":60,"props":3916,"children":3917},{},[3918,3920],{"type":31,"value":3919},"如果你更关心“网页制作落地”：看这篇 ",{"type":25,"tag":2470,"props":3921,"children":3923},{"href":3922},"/topics/practical-tips/htmlpage-quick-landing-page",[3924],{"type":31,"value":3925},"3 分钟用 HTMLPAGE 做落地页",{"title":7,"searchDepth":2709,"depth":2709,"links":3927},[3928,3929,3930,3942,3943,3946,3951],{"id":2925,"depth":2712,"text":2928},{"id":3000,"depth":2712,"text":3003},{"id":3240,"depth":2712,"text":3243,"children":3931},[3932,3933,3934,3935,3936,3937,3938,3939,3940,3941],{"id":3246,"depth":2709,"text":3249},{"id":3305,"depth":2709,"text":3308},{"id":3375,"depth":2709,"text":3378},{"id":3431,"depth":2709,"text":3434},{"id":3471,"depth":2709,"text":3474},{"id":3510,"depth":2709,"text":3513},{"id":3529,"depth":2709,"text":3532},{"id":3570,"depth":2709,"text":3573},{"id":3605,"depth":2709,"text":3608},{"id":3622,"depth":2709,"text":3625},{"id":3679,"depth":2712,"text":3682},{"id":3749,"depth":2712,"text":3752,"children":3944},[3945],{"id":3755,"depth":2709,"text":3758},{"id":3845,"depth":2712,"text":3848,"children":3947},[3948,3949,3950],{"id":3851,"depth":2709,"text":3854},{"id":3862,"depth":2709,"text":3865},{"id":3873,"depth":2709,"text":3876},{"id":3887,"depth":2712,"text":3890},"content:topics:ai:cursor-keyboard-shortcuts-cheatsheet.md","topics/ai/cursor-keyboard-shortcuts-cheatsheet.md","topics/ai/cursor-keyboard-shortcuts-cheatsheet",{"_path":3956,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":3957,"description":3958,"date":3959,"topic":5,"author":2810,"tags":3960,"image":3964,"imageAlt":3965,"pexelsPhotoId":3966,"pexelsUrl":3967,"readingTime":3968,"body":3969,"_type":1473,"_id":4898,"_source":2800,"_file":4899,"_stem":4900,"_extension":2803},"/topics/ai/cursor-vs-copilot-vscode-workflow","Cursor vs GitHub Copilot vs VS Code：怎么选、怎么搭配、怎么把风险关在笼子里","用“任务类型×风险×验收成本”的选择矩阵解释 Cursor/Copilot/VS Code 的差异，并给出一套可落地的协作工作流（范围闸门、最小回归集、回滚策略）。","2026-03-01",[2812,3961,2815,3962,3963],"GitHub Copilot","AI 编程","工作流","/images/topics/ai/cursor-vs-copilot-vscode-workflow.jpg","团队在电脑前进行协作讨论",1181371,"https://www.pexels.com/photo/man-wearing-blue-dress-shirt-1181371/",15,{"type":22,"children":3970,"toc":4876},[3971,3976,3981,3999,4004,4022,4025,4031,4036,4067,4072,4075,4081,4089,4289,4297,4310,4313,4319,4325,4338,4343,4356,4362,4367,4400,4406,4411,4429,4432,4438,4443,4449,4454,4487,4493,4506,4511,4524,4530,4542,4548,4553,4566,4571,4574,4580,4585,4706,4709,4715,4725,4734,4752,4761,4769,4778,4796,4799,4805,4811,4816,4822,4827,4830,4835],{"type":25,"tag":34,"props":3972,"children":3973},{},[3974],{"type":31,"value":3975},"“Cursor 和 Copilot 到底有什么区别？”",{"type":25,"tag":34,"props":3977,"children":3978},{},[3979],{"type":31,"value":3980},"这个问题问得越早越好，因为你一旦把工具选错，后面所有痛苦都不是“提示词不够好”，而是：",{"type":25,"tag":56,"props":3982,"children":3983},{},[3984,3989,3994],{"type":25,"tag":60,"props":3985,"children":3986},{},[3987],{"type":31,"value":3988},"改动不可控（范围漂移、改错文件）",{"type":25,"tag":60,"props":3990,"children":3991},{},[3992],{"type":31,"value":3993},"验收成本爆炸（不知道要测什么）",{"type":25,"tag":60,"props":3995,"children":3996},{},[3997],{"type":31,"value":3998},"团队协作崩盘（没有闸门、没有回滚）",{"type":25,"tag":34,"props":4000,"children":4001},{},[4002],{"type":31,"value":4003},"这篇文章用一张选择矩阵 + 一套可执行工作流，帮你做到两件事：",{"type":25,"tag":2661,"props":4005,"children":4006},{},[4007,4012],{"type":25,"tag":60,"props":4008,"children":4009},{},[4010],{"type":31,"value":4011},"知道什么时候用 Cursor、什么时候用 Copilot、什么时候“纯 VS Code 更快”",{"type":25,"tag":60,"props":4013,"children":4014},{},[4015,4017],{"type":31,"value":4016},"就算用 AI，也能把风险关在笼子里：",{"type":25,"tag":38,"props":4018,"children":4019},{},[4020],{"type":31,"value":4021},"可审查、可验证、可回滚",{"type":25,"tag":213,"props":4023,"children":4024},{},[],{"type":25,"tag":26,"props":4026,"children":4028},{"id":4027},"结论先说三者不是互斥而是分工",[4029],{"type":31,"value":4030},"结论先说：三者不是互斥，而是分工",{"type":25,"tag":34,"props":4032,"children":4033},{},[4034],{"type":31,"value":4035},"你可以把它们看成三层能力：",{"type":25,"tag":56,"props":4037,"children":4038},{},[4039,4048,4058],{"type":25,"tag":60,"props":4040,"children":4041},{},[4042,4046],{"type":25,"tag":38,"props":4043,"children":4044},{},[4045],{"type":31,"value":2815},{"type":31,"value":4047},"：编辑器与生态（调试、插件、任务、终端、语言服务）",{"type":25,"tag":60,"props":4049,"children":4050},{},[4051,4056],{"type":25,"tag":38,"props":4052,"children":4053},{},[4054],{"type":31,"value":4055},"Copilot",{"type":31,"value":4057},"：代码补全与局部建议（“我正在写这一行/这一段”）",{"type":25,"tag":60,"props":4059,"children":4060},{},[4061,4065],{"type":25,"tag":38,"props":4062,"children":4063},{},[4064],{"type":31,"value":2812},{"type":31,"value":4066},"：以项目为单位的 AI 协作（对话、索引、多文件编辑、规则）",{"type":25,"tag":34,"props":4068,"children":4069},{},[4070],{"type":31,"value":4071},"最常见的误区是：把“局部补全能力”当作“能做架构与多文件落地”。",{"type":25,"tag":213,"props":4073,"children":4074},{},[],{"type":25,"tag":26,"props":4076,"children":4078},{"id":4077},"选择矩阵按任务类型选工具不是按偏好",[4079],{"type":31,"value":4080},"选择矩阵：按任务类型选工具（不是按偏好）",{"type":25,"tag":487,"props":4082,"children":4083},{},[4084],{"type":25,"tag":34,"props":4085,"children":4086},{},[4087],{"type":31,"value":4088},"你只要把自己的任务放进表格，就能得到推荐路径。",{"type":25,"tag":110,"props":4090,"children":4091},{},[4092,4123],{"type":25,"tag":114,"props":4093,"children":4094},{},[4095],{"type":25,"tag":118,"props":4096,"children":4097},{},[4098,4103,4108,4113,4118],{"type":25,"tag":122,"props":4099,"children":4100},{},[4101],{"type":31,"value":4102},"任务类型",{"type":25,"tag":122,"props":4104,"children":4106},{"align":4105},"right",[4107],{"type":31,"value":584},{"type":25,"tag":122,"props":4109,"children":4110},{"align":4105},[4111],{"type":31,"value":4112},"验收成本",{"type":25,"tag":122,"props":4114,"children":4115},{},[4116],{"type":31,"value":4117},"更推荐",{"type":25,"tag":122,"props":4119,"children":4120},{},[4121],{"type":31,"value":4122},"为什么",{"type":25,"tag":138,"props":4124,"children":4125},{},[4126,4152,4184,4210,4236,4263],{"type":25,"tag":118,"props":4127,"children":4128},{},[4129,4134,4138,4142,4147],{"type":25,"tag":145,"props":4130,"children":4131},{},[4132],{"type":31,"value":4133},"写一段代码/补一个 if",{"type":25,"tag":145,"props":4135,"children":4136},{"align":4105},[4137],{"type":31,"value":883},{"type":25,"tag":145,"props":4139,"children":4140},{"align":4105},[4141],{"type":31,"value":883},{"type":25,"tag":145,"props":4143,"children":4144},{},[4145],{"type":31,"value":4146},"Copilot / Cursor 内联编辑",{"type":25,"tag":145,"props":4148,"children":4149},{},[4150],{"type":31,"value":4151},"局部建议足够，成本最低",{"type":25,"tag":118,"props":4153,"children":4154},{},[4155,4160,4164,4168,4179],{"type":25,"tag":145,"props":4156,"children":4157},{},[4158],{"type":31,"value":4159},"重构一个函数",{"type":25,"tag":145,"props":4161,"children":4162},{"align":4105},[4163],{"type":31,"value":918},{"type":25,"tag":145,"props":4165,"children":4166},{"align":4105},[4167],{"type":31,"value":918},{"type":25,"tag":145,"props":4169,"children":4170},{},[4171,4173],{"type":31,"value":4172},"Cursor ",{"type":25,"tag":240,"props":4174,"children":4176},{"className":4175},[],[4177],{"type":31,"value":4178},"内联编辑",{"type":25,"tag":145,"props":4180,"children":4181},{},[4182],{"type":31,"value":4183},"需要解释、需要约束输出",{"type":25,"tag":118,"props":4185,"children":4186},{},[4187,4192,4196,4200,4205],{"type":25,"tag":145,"props":4188,"children":4189},{},[4190],{"type":31,"value":4191},"改一个组件 + 样式",{"type":25,"tag":145,"props":4193,"children":4194},{"align":4105},[4195],{"type":31,"value":918},{"type":25,"tag":145,"props":4197,"children":4198},{"align":4105},[4199],{"type":31,"value":918},{"type":25,"tag":145,"props":4201,"children":4202},{},[4203],{"type":31,"value":4204},"Cursor（小范围多文件）",{"type":25,"tag":145,"props":4206,"children":4207},{},[4208],{"type":31,"value":4209},"需要同时改模板与样式",{"type":25,"tag":118,"props":4211,"children":4212},{},[4213,4218,4222,4226,4231],{"type":25,"tag":145,"props":4214,"children":4215},{},[4216],{"type":31,"value":4217},"改 3~5 个文件（组件+api+测试）",{"type":25,"tag":145,"props":4219,"children":4220},{"align":4105},[4221],{"type":31,"value":1207},{"type":25,"tag":145,"props":4223,"children":4224},{"align":4105},[4225],{"type":31,"value":1207},{"type":25,"tag":145,"props":4227,"children":4228},{},[4229],{"type":31,"value":4230},"Cursor Composer + 闸门",{"type":25,"tag":145,"props":4232,"children":4233},{},[4234],{"type":31,"value":4235},"需要计划、验收、回滚",{"type":25,"tag":118,"props":4237,"children":4238},{},[4239,4244,4249,4253,4258],{"type":25,"tag":145,"props":4240,"children":4241},{},[4242],{"type":31,"value":4243},"重写一段架构/引入新依赖",{"type":25,"tag":145,"props":4245,"children":4246},{"align":4105},[4247],{"type":31,"value":4248},"很高",{"type":25,"tag":145,"props":4250,"children":4251},{"align":4105},[4252],{"type":31,"value":4248},{"type":25,"tag":145,"props":4254,"children":4255},{},[4256],{"type":31,"value":4257},"先人脑设计 + VS Code 实现",{"type":25,"tag":145,"props":4259,"children":4260},{},[4261],{"type":31,"value":4262},"AI 易发散，最好先设计再执行",{"type":25,"tag":118,"props":4264,"children":4265},{},[4266,4271,4275,4279,4284],{"type":25,"tag":145,"props":4267,"children":4268},{},[4269],{"type":31,"value":4270},"排查线上问题/性能抖动",{"type":25,"tag":145,"props":4272,"children":4273},{"align":4105},[4274],{"type":31,"value":1207},{"type":25,"tag":145,"props":4276,"children":4277},{"align":4105},[4278],{"type":31,"value":4248},{"type":25,"tag":145,"props":4280,"children":4281},{},[4282],{"type":31,"value":4283},"VS Code + 工具链优先，AI 辅助归纳",{"type":25,"tag":145,"props":4285,"children":4286},{},[4287],{"type":31,"value":4288},"需要证据，不要“猜”",{"type":25,"tag":34,"props":4290,"children":4291},{},[4292],{"type":25,"tag":38,"props":4293,"children":4294},{},[4295],{"type":31,"value":4296},"一句话规则：",{"type":25,"tag":56,"props":4298,"children":4299},{},[4300,4305],{"type":25,"tag":60,"props":4301,"children":4302},{},[4303],{"type":31,"value":4304},"当你的改动可以用“10 条最小回归集”覆盖时，用 Cursor。",{"type":25,"tag":60,"props":4306,"children":4307},{},[4308],{"type":31,"value":4309},"当你的改动无法验证时，先别让 AI 动手。",{"type":25,"tag":213,"props":4311,"children":4312},{},[],{"type":25,"tag":26,"props":4314,"children":4316},{"id":4315},"差异拆解到底差在哪里",[4317],{"type":31,"value":4318},"差异拆解：到底差在哪里？",{"type":25,"tag":223,"props":4320,"children":4322},{"id":4321},"_1-上下文来源补全-vs-项目索引",[4323],{"type":31,"value":4324},"1) 上下文来源：补全 vs 项目索引",{"type":25,"tag":56,"props":4326,"children":4327},{},[4328,4333],{"type":25,"tag":60,"props":4329,"children":4330},{},[4331],{"type":31,"value":4332},"Copilot 更擅长：你正在写的这几行、当前文件的局部上下文",{"type":25,"tag":60,"props":4334,"children":4335},{},[4336],{"type":31,"value":4337},"Cursor 更擅长：项目级索引 + 多文件关联理解",{"type":25,"tag":34,"props":4339,"children":4340},{},[4341],{"type":31,"value":4342},"因此：",{"type":25,"tag":56,"props":4344,"children":4345},{},[4346,4351],{"type":25,"tag":60,"props":4347,"children":4348},{},[4349],{"type":31,"value":4350},"写代码片段：Copilot 速度更快",{"type":25,"tag":60,"props":4352,"children":4353},{},[4354],{"type":31,"value":4355},"改一坨工程：Cursor 更有胜算（但更需要闸门）",{"type":25,"tag":223,"props":4357,"children":4359},{"id":4358},"_2-交互方式你能不能控制范围",[4360],{"type":31,"value":4361},"2) 交互方式：你能不能控制范围",{"type":25,"tag":34,"props":4363,"children":4364},{},[4365],{"type":31,"value":4366},"范围控制的三个层级：",{"type":25,"tag":2661,"props":4368,"children":4369},{},[4370,4380,4390],{"type":25,"tag":60,"props":4371,"children":4372},{},[4373,4375],{"type":31,"value":4374},"内联编辑（选中一段）→ ",{"type":25,"tag":38,"props":4376,"children":4377},{},[4378],{"type":31,"value":4379},"最强范围控制",{"type":25,"tag":60,"props":4381,"children":4382},{},[4383,4385],{"type":31,"value":4384},"Composer 多文件（先列文件清单）→ ",{"type":25,"tag":38,"props":4386,"children":4387},{},[4388],{"type":31,"value":4389},"可控但要闸门",{"type":25,"tag":60,"props":4391,"children":4392},{},[4393,4395],{"type":31,"value":4394},"大对话（泛目标）→ ",{"type":25,"tag":38,"props":4396,"children":4397},{},[4398],{"type":31,"value":4399},"最容易跑偏",{"type":25,"tag":223,"props":4401,"children":4403},{"id":4402},"_3-输出形态建议-vs-可审查的变更",[4404],{"type":31,"value":4405},"3) 输出形态：建议 vs 可审查的变更",{"type":25,"tag":34,"props":4407,"children":4408},{},[4409],{"type":31,"value":4410},"最好的 AI 输出不是“给我一段代码”，而是：",{"type":25,"tag":56,"props":4412,"children":4413},{},[4414,4419,4424],{"type":25,"tag":60,"props":4415,"children":4416},{},[4417],{"type":31,"value":4418},"改动摘要（做了什么）",{"type":25,"tag":60,"props":4420,"children":4421},{},[4422],{"type":31,"value":4423},"diff 级别的可审查变更",{"type":25,"tag":60,"props":4425,"children":4426},{},[4427],{"type":31,"value":4428},"验收步骤与回滚方案",{"type":25,"tag":213,"props":4430,"children":4431},{},[],{"type":25,"tag":26,"props":4433,"children":4435},{"id":4434},"一套可落地的团队工作流把风险关住",[4436],{"type":31,"value":4437},"一套可落地的团队工作流（把风险关住）",{"type":25,"tag":34,"props":4439,"children":4440},{},[4441],{"type":31,"value":4442},"下面这套流程，你可以直接写进团队规范：",{"type":25,"tag":223,"props":4444,"children":4446},{"id":4445},"step-1先写任务单geo-友好结构",[4447],{"type":31,"value":4448},"Step 1：先写任务单（GEO 友好结构）",{"type":25,"tag":34,"props":4450,"children":4451},{},[4452],{"type":31,"value":4453},"模板：",{"type":25,"tag":56,"props":4455,"children":4456},{},[4457,4462,4467,4472,4477,4482],{"type":25,"tag":60,"props":4458,"children":4459},{},[4460],{"type":31,"value":4461},"目标：……",{"type":25,"tag":60,"props":4463,"children":4464},{},[4465],{"type":31,"value":4466},"背景：……",{"type":25,"tag":60,"props":4468,"children":4469},{},[4470],{"type":31,"value":4471},"范围：只改这些文件/模块：……",{"type":25,"tag":60,"props":4473,"children":4474},{},[4475],{"type":31,"value":4476},"非目标：不做哪些事情：……",{"type":25,"tag":60,"props":4478,"children":4479},{},[4480],{"type":31,"value":4481},"验收：如何判断完成（可测试/可观察）：……",{"type":25,"tag":60,"props":4483,"children":4484},{},[4485],{"type":31,"value":4486},"回滚：如果失败怎么撤回：……",{"type":25,"tag":223,"props":4488,"children":4490},{"id":4489},"step-2用范围闸门限制-ai",[4491],{"type":31,"value":4492},"Step 2：用“范围闸门”限制 AI",{"type":25,"tag":56,"props":4494,"children":4495},{},[4496,4501],{"type":25,"tag":60,"props":4497,"children":4498},{},[4499],{"type":31,"value":4500},"单文件改动：优先 Cursor 内联编辑",{"type":25,"tag":60,"props":4502,"children":4503},{},[4504],{"type":31,"value":4505},"多文件改动：必须先让 AI 输出“文件清单（≤5）+ 每步验收”",{"type":25,"tag":34,"props":4507,"children":4508},{},[4509],{"type":31,"value":4510},"如果 AI 输出的文件清单超过 5 个：",{"type":25,"tag":56,"props":4512,"children":4513},{},[4514,4519],{"type":25,"tag":60,"props":4515,"children":4516},{},[4517],{"type":31,"value":4518},"不是它太强，是任务太大",{"type":25,"tag":60,"props":4520,"children":4521},{},[4522],{"type":31,"value":4523},"你需要拆任务，而不是继续推进",{"type":25,"tag":223,"props":4525,"children":4527},{"id":4526},"step-3最小回归集10-条",[4528],{"type":31,"value":4529},"Step 3：最小回归集（10 条）",{"type":25,"tag":34,"props":4531,"children":4532},{},[4533,4535,4540],{"type":31,"value":4534},"每次接受改动前必须跑（可参考：",{"type":25,"tag":2470,"props":4536,"children":4537},{"href":2806},[4538],{"type":31,"value":4539},"Cursor 快捷键速查表",{"type":31,"value":4541}," 里的清单）。",{"type":25,"tag":223,"props":4543,"children":4545},{"id":4544},"step-4回滚策略不用等事故才想",[4546],{"type":31,"value":4547},"Step 4：回滚策略（不用等事故才想）",{"type":25,"tag":34,"props":4549,"children":4550},{},[4551],{"type":31,"value":4552},"回滚最常见的两条路：",{"type":25,"tag":56,"props":4554,"children":4555},{},[4556,4561],{"type":25,"tag":60,"props":4557,"children":4558},{},[4559],{"type":31,"value":4560},"git 回滚 commit",{"type":25,"tag":60,"props":4562,"children":4563},{},[4564],{"type":31,"value":4565},"对关键文件保留前版本（至少能快速恢复）",{"type":25,"tag":34,"props":4567,"children":4568},{},[4569],{"type":31,"value":4570},"你需要做到：任何一轮 AI 改动都能在 5 分钟内撤回。",{"type":25,"tag":213,"props":4572,"children":4573},{},[],{"type":25,"tag":26,"props":4575,"children":4577},{"id":4576},"必交付物对比矩阵可复制",[4578],{"type":31,"value":4579},"必交付物：对比矩阵（可复制）",{"type":25,"tag":34,"props":4581,"children":4582},{},[4583],{"type":31,"value":4584},"下面这张表可以直接贴到你的团队 wiki：",{"type":25,"tag":110,"props":4586,"children":4587},{},[4588,4611],{"type":25,"tag":114,"props":4589,"children":4590},{},[4591],{"type":25,"tag":118,"props":4592,"children":4593},{},[4594,4599,4603,4607],{"type":25,"tag":122,"props":4595,"children":4596},{},[4597],{"type":31,"value":4598},"维度",{"type":25,"tag":122,"props":4600,"children":4601},{},[4602],{"type":31,"value":2815},{"type":25,"tag":122,"props":4604,"children":4605},{},[4606],{"type":31,"value":4055},{"type":25,"tag":122,"props":4608,"children":4609},{},[4610],{"type":31,"value":2812},{"type":25,"tag":138,"props":4612,"children":4613},{},[4614,4637,4660,4683],{"type":25,"tag":118,"props":4615,"children":4616},{},[4617,4622,4627,4632],{"type":25,"tag":145,"props":4618,"children":4619},{},[4620],{"type":31,"value":4621},"强项",{"type":25,"tag":145,"props":4623,"children":4624},{},[4625],{"type":31,"value":4626},"工具链、调试、生态",{"type":25,"tag":145,"props":4628,"children":4629},{},[4630],{"type":31,"value":4631},"补全与局部建议",{"type":25,"tag":145,"props":4633,"children":4634},{},[4635],{"type":31,"value":4636},"项目上下文、多文件落地",{"type":25,"tag":118,"props":4638,"children":4639},{},[4640,4645,4650,4655],{"type":25,"tag":145,"props":4641,"children":4642},{},[4643],{"type":31,"value":4644},"适合任务",{"type":25,"tag":145,"props":4646,"children":4647},{},[4648],{"type":31,"value":4649},"排查、调试、验证",{"type":25,"tag":145,"props":4651,"children":4652},{},[4653],{"type":31,"value":4654},"写一段、补一段",{"type":25,"tag":145,"props":4656,"children":4657},{},[4658],{"type":31,"value":4659},"改一段、改一组文件",{"type":25,"tag":118,"props":4661,"children":4662},{},[4663,4668,4673,4678],{"type":25,"tag":145,"props":4664,"children":4665},{},[4666],{"type":31,"value":4667},"最大风险",{"type":25,"tag":145,"props":4669,"children":4670},{},[4671],{"type":31,"value":4672},"无",{"type":25,"tag":145,"props":4674,"children":4675},{},[4676],{"type":31,"value":4677},"过度依赖建议",{"type":25,"tag":145,"props":4679,"children":4680},{},[4681],{"type":31,"value":4682},"范围漂移、多文件回归",{"type":25,"tag":118,"props":4684,"children":4685},{},[4686,4691,4696,4701],{"type":25,"tag":145,"props":4687,"children":4688},{},[4689],{"type":31,"value":4690},"必须搭配",{"type":25,"tag":145,"props":4692,"children":4693},{},[4694],{"type":31,"value":4695},"规范与检查",{"type":25,"tag":145,"props":4697,"children":4698},{},[4699],{"type":31,"value":4700},"代码评审",{"type":25,"tag":145,"props":4702,"children":4703},{},[4704],{"type":31,"value":4705},"闸门 + 最小回归集",{"type":25,"tag":213,"props":4707,"children":4708},{},[],{"type":25,"tag":26,"props":4710,"children":4712},{"id":4711},"失败案例多文件看似成功实际埋雷",[4713],{"type":31,"value":4714},"失败案例：多文件“看似成功”，实际埋雷",{"type":25,"tag":34,"props":4716,"children":4717},{},[4718,4723],{"type":25,"tag":38,"props":4719,"children":4720},{},[4721],{"type":31,"value":4722},"现象",{"type":31,"value":4724},"：AI 说“我已经把所有地方都改了”，你也接受了，结果上线后 404 或样式错位。",{"type":25,"tag":34,"props":4726,"children":4727},{},[4728,4733],{"type":25,"tag":38,"props":4729,"children":4730},{},[4731],{"type":31,"value":4732},"复现条件",{"type":31,"value":54},{"type":25,"tag":56,"props":4735,"children":4736},{},[4737,4742,4747],{"type":25,"tag":60,"props":4738,"children":4739},{},[4740],{"type":31,"value":4741},"你给了一个大目标（例如“把所有按钮统一成主题色”）",{"type":25,"tag":60,"props":4743,"children":4744},{},[4745],{"type":31,"value":4746},"它改了组件、样式、甚至主题配置",{"type":25,"tag":60,"props":4748,"children":4749},{},[4750],{"type":31,"value":4751},"你没有按页面模块走一遍，直接合并",{"type":25,"tag":34,"props":4753,"children":4754},{},[4755,4760],{"type":25,"tag":38,"props":4756,"children":4757},{},[4758],{"type":31,"value":4759},"根因",{"type":31,"value":54},{"type":25,"tag":56,"props":4762,"children":4763},{},[4764],{"type":25,"tag":60,"props":4765,"children":4766},{},[4767],{"type":31,"value":4768},"改动范围大，但验收仍按“小改动”的方式做（只看一处）",{"type":25,"tag":34,"props":4770,"children":4771},{},[4772,4777],{"type":25,"tag":38,"props":4773,"children":4774},{},[4775],{"type":31,"value":4776},"修复",{"type":31,"value":54},{"type":25,"tag":56,"props":4779,"children":4780},{},[4781,4786,4791],{"type":25,"tag":60,"props":4782,"children":4783},{},[4784],{"type":31,"value":4785},"强制把任务拆成“模块级目标”：Hero、Feature、Pricing、Form",{"type":25,"tag":60,"props":4787,"children":4788},{},[4789],{"type":31,"value":4790},"每个模块改完就验收一次",{"type":25,"tag":60,"props":4792,"children":4793},{},[4794],{"type":31,"value":4795},"验收通过再进入下一个模块",{"type":25,"tag":213,"props":4797,"children":4798},{},[],{"type":25,"tag":26,"props":4800,"children":4802},{"id":4801},"faq",[4803],{"type":31,"value":4804},"FAQ",{"type":25,"tag":223,"props":4806,"children":4808},{"id":4807},"q1我已经用了-cursor为什么还要用-copilot",[4809],{"type":31,"value":4810},"Q1：我已经用了 Cursor，为什么还要用 Copilot？",{"type":25,"tag":34,"props":4812,"children":4813},{},[4814],{"type":31,"value":4815},"因为“补全”这种高频低风险任务，Copilot 的交互成本更低；Cursor 更适合需要解释与约束的改动。",{"type":25,"tag":223,"props":4817,"children":4819},{"id":4818},"q2什么时候应该完全不用-ai",[4820],{"type":31,"value":4821},"Q2：什么时候应该完全不用 AI？",{"type":25,"tag":34,"props":4823,"children":4824},{},[4825],{"type":31,"value":4826},"当你无法定义验收标准时。比如“更高级”“更好看”这种目标，先做信息结构与设计规则，再让 AI 帮你落地局部。",{"type":25,"tag":213,"props":4828,"children":4829},{},[],{"type":25,"tag":26,"props":4831,"children":4833},{"id":4832},"延伸阅读",[4834],{"type":31,"value":4832},{"type":25,"tag":56,"props":4836,"children":4837},{},[4838,4847,4856,4865],{"type":25,"tag":60,"props":4839,"children":4840},{},[4841,4843],{"type":31,"value":4842},"Cursor 入门：",{"type":25,"tag":2470,"props":4844,"children":4845},{"href":2894},[4846],{"type":31,"value":2897},{"type":25,"tag":60,"props":4848,"children":4849},{},[4850,4852],{"type":31,"value":4851},"Cursor 进阶：",{"type":25,"tag":2470,"props":4853,"children":4854},{"href":2905},[4855],{"type":31,"value":2908},{"type":25,"tag":60,"props":4857,"children":4858},{},[4859,4861],{"type":31,"value":4860},"规则配置：",{"type":25,"tag":2470,"props":4862,"children":4863},{"href":2916},[4864],{"type":31,"value":2919},{"type":25,"tag":60,"props":4866,"children":4867},{},[4868,4870],{"type":31,"value":4869},"Copilot 实战：",{"type":25,"tag":2470,"props":4871,"children":4873},{"href":4872},"/topics/ai/github-copilot-tips",[4874],{"type":31,"value":4875},"GitHub Copilot 实用技巧",{"title":7,"searchDepth":2709,"depth":2709,"links":4877},[4878,4879,4880,4885,4891,4892,4893,4897],{"id":4027,"depth":2712,"text":4030},{"id":4077,"depth":2712,"text":4080},{"id":4315,"depth":2712,"text":4318,"children":4881},[4882,4883,4884],{"id":4321,"depth":2709,"text":4324},{"id":4358,"depth":2709,"text":4361},{"id":4402,"depth":2709,"text":4405},{"id":4434,"depth":2712,"text":4437,"children":4886},[4887,4888,4889,4890],{"id":4445,"depth":2709,"text":4448},{"id":4489,"depth":2709,"text":4492},{"id":4526,"depth":2709,"text":4529},{"id":4544,"depth":2709,"text":4547},{"id":4576,"depth":2712,"text":4579},{"id":4711,"depth":2712,"text":4714},{"id":4801,"depth":2712,"text":4804,"children":4894},[4895,4896],{"id":4807,"depth":2709,"text":4810},{"id":4818,"depth":2709,"text":4821},{"id":4832,"depth":2712,"text":4832},"content:topics:ai:cursor-vs-copilot-vscode-workflow.md","topics/ai/cursor-vs-copilot-vscode-workflow.md","topics/ai/cursor-vs-copilot-vscode-workflow",{"_path":4902,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":4903,"description":4904,"date":4905,"topic":5,"author":2810,"tags":4906,"image":4911,"featured":2071,"readingTime":3968,"body":4912,"_type":1473,"_id":5557,"_source":2800,"_file":5558,"_stem":5559,"_extension":2803},"/topics/ai/ai-debugging-troubleshooting-guide","AI 辅助调试与问题排查：让 AI 成为你的调试搭档","深入探讨如何利用 AI 工具提升调试效率，包括错误信息分析、日志解读、性能问题定位、复杂 bug 排查等实战场景，构建 AI 驱动的调试工作流。","2026-01-18",[4907,4908,4909,2816,4910],"AI 调试","问题排查","Debug","错误处理","/images/topics/ai/ai-debugging-guide.jpg",{"type":22,"children":4913,"toc":5528},[4914,4920,4926,4931,4936,4941,4947,4953,4958,4966,4994,5002,5025,5031,5040,5049,5057,5065,5098,5106,5136,5149,5157,5162,5170,5178,5187,5193,5201,5212,5220,5229,5235,5241,5246,5255,5261,5266,5275,5281,5287,5296,5302,5311,5317,5328,5334,5340,5349,5355,5364,5370,5376,5384,5390,5399,5407,5415,5418,5424,5429,5448,5460,5463,5469,5474,5483,5488,5491,5497,5502,5520],{"type":25,"tag":26,"props":4915,"children":4917},{"id":4916},"ai-辅助调试与问题排查",[4918],{"type":31,"value":4919},"AI 辅助调试与问题排查",{"type":25,"tag":26,"props":4921,"children":4923},{"id":4922},"引言调试的痛与-ai-的解药",[4924],{"type":31,"value":4925},"引言：调试的痛与 AI 的解药",{"type":25,"tag":34,"props":4927,"children":4928},{},[4929],{"type":31,"value":4930},"调试是每个程序员的日常，也是最消耗时间和精力的工作之一。我们都有过这样的经历：盯着一个莫名其妙的错误信息，翻遍 Stack Overflow，尝试各种方案，几个小时后才发现是一个愚蠢的拼写错误。",{"type":25,"tag":34,"props":4932,"children":4933},{},[4934],{"type":31,"value":4935},"AI 工具的出现，正在改变调试的方式。不是替代你的思考，而是加速你的分析过程——帮你快速理解错误、缩小排查范围、验证假设。",{"type":25,"tag":34,"props":4937,"children":4938},{},[4939],{"type":31,"value":4940},"这篇文章分享我在实际项目中使用 AI 辅助调试的经验和方法论。",{"type":25,"tag":26,"props":4942,"children":4944},{"id":4943},"第一部分建立-ai-调试的思维模型",[4945],{"type":31,"value":4946},"第一部分：建立 AI 调试的思维模型",{"type":25,"tag":223,"props":4948,"children":4950},{"id":4949},"_11-ai-在调试中的角色",[4951],{"type":31,"value":4952},"1.1 AI 在调试中的角色",{"type":25,"tag":34,"props":4954,"children":4955},{},[4956],{"type":31,"value":4957},"把 AI 想象成一个经验丰富但不了解你项目的高级工程师。它：",{"type":25,"tag":34,"props":4959,"children":4960},{},[4961],{"type":25,"tag":38,"props":4962,"children":4963},{},[4964],{"type":31,"value":4965},"擅长的事情：",{"type":25,"tag":56,"props":4967,"children":4968},{},[4969,4974,4979,4984,4989],{"type":25,"tag":60,"props":4970,"children":4971},{},[4972],{"type":31,"value":4973},"解读错误信息的含义",{"type":25,"tag":60,"props":4975,"children":4976},{},[4977],{"type":31,"value":4978},"提供可能的原因列表",{"type":25,"tag":60,"props":4980,"children":4981},{},[4982],{"type":31,"value":4983},"给出排查方向建议",{"type":25,"tag":60,"props":4985,"children":4986},{},[4987],{"type":31,"value":4988},"解释复杂的技术概念",{"type":25,"tag":60,"props":4990,"children":4991},{},[4992],{"type":31,"value":4993},"生成调试代码片段",{"type":25,"tag":34,"props":4995,"children":4996},{},[4997],{"type":25,"tag":38,"props":4998,"children":4999},{},[5000],{"type":31,"value":5001},"不擅长的事情：",{"type":25,"tag":56,"props":5003,"children":5004},{},[5005,5010,5015,5020],{"type":25,"tag":60,"props":5006,"children":5007},{},[5008],{"type":31,"value":5009},"了解你的业务逻辑",{"type":25,"tag":60,"props":5011,"children":5012},{},[5013],{"type":31,"value":5014},"知道你的代码历史",{"type":25,"tag":60,"props":5016,"children":5017},{},[5018],{"type":31,"value":5019},"理解项目特定的约定",{"type":25,"tag":60,"props":5021,"children":5022},{},[5023],{"type":31,"value":5024},"做出架构级判断",{"type":25,"tag":223,"props":5026,"children":5028},{"id":5027},"_12-有效提问的结构",[5029],{"type":31,"value":5030},"1.2 有效提问的结构",{"type":25,"tag":235,"props":5032,"children":5035},{"code":5033,"language":1473,"meta":7,"className":5034},"## 高效的调试提问模板\n\n**问题描述**\n[简洁描述遇到的问题]\n\n**错误信息**\n",[1475],[5036],{"type":25,"tag":240,"props":5037,"children":5038},{"__ignoreMap":7},[5039],{"type":31,"value":5033},{"type":25,"tag":34,"props":5041,"children":5042},{},[5043],{"type":25,"tag":5044,"props":5045,"children":5046},"span",{},[5047],{"type":31,"value":5048},"完整的错误信息，不要截断",{"type":25,"tag":235,"props":5050,"children":5052},{"code":5051},"\n**相关代码**\n```javascript\n[精简但完整的相关代码]\n",[5053],{"type":25,"tag":240,"props":5054,"children":5055},{"__ignoreMap":7},[5056],{"type":31,"value":5051},{"type":25,"tag":34,"props":5058,"children":5059},{},[5060],{"type":25,"tag":38,"props":5061,"children":5062},{},[5063],{"type":31,"value":5064},"环境信息",{"type":25,"tag":56,"props":5066,"children":5067},{},[5068,5078,5088],{"type":25,"tag":60,"props":5069,"children":5070},{},[5071,5073],{"type":31,"value":5072},"运行环境：",{"type":25,"tag":5044,"props":5074,"children":5075},{},[5076],{"type":31,"value":5077},"Node 版本/浏览器版本",{"type":25,"tag":60,"props":5079,"children":5080},{},[5081,5083],{"type":31,"value":5082},"框架版本：",{"type":25,"tag":5044,"props":5084,"children":5085},{},[5086],{"type":31,"value":5087},"相关框架版本",{"type":25,"tag":60,"props":5089,"children":5090},{},[5091,5093],{"type":31,"value":5092},"操作系统：",{"type":25,"tag":5044,"props":5094,"children":5095},{},[5096],{"type":31,"value":5097},"如果相关",{"type":25,"tag":34,"props":5099,"children":5100},{},[5101],{"type":25,"tag":38,"props":5102,"children":5103},{},[5104],{"type":31,"value":5105},"已尝试的方案",{"type":25,"tag":56,"props":5107,"children":5108},{},[5109,5123],{"type":25,"tag":60,"props":5110,"children":5111},{},[5112,5117,5118],{"type":25,"tag":5044,"props":5113,"children":5114},{},[5115],{"type":31,"value":5116},"方案1",{"type":31,"value":54},{"type":25,"tag":5044,"props":5119,"children":5120},{},[5121],{"type":31,"value":5122},"结果",{"type":25,"tag":60,"props":5124,"children":5125},{},[5126,5131,5132],{"type":25,"tag":5044,"props":5127,"children":5128},{},[5129],{"type":31,"value":5130},"方案2",{"type":31,"value":54},{"type":25,"tag":5044,"props":5133,"children":5134},{},[5135],{"type":31,"value":5122},{"type":25,"tag":34,"props":5137,"children":5138},{},[5139,5144],{"type":25,"tag":38,"props":5140,"children":5141},{},[5142],{"type":31,"value":5143},"期望的结果",{"type":25,"tag":5044,"props":5145,"children":5146},{},[5147],{"type":31,"value":5148},"描述期望的行为",{"type":25,"tag":235,"props":5150,"children":5152},{"code":5151},"\n### 1.3 分级调试策略\n\n",[5153],{"type":25,"tag":240,"props":5154,"children":5155},{"__ignoreMap":7},[5156],{"type":31,"value":5151},{"type":25,"tag":34,"props":5158,"children":5159},{},[5160],{"type":31,"value":5161},"┌───────────────────────────────────────────────────────────┐\n│                    AI 辅助调试决策树                        │\n├───────────────────────────────────────────────────────────┤\n│                                                           │\n│  Level 1：简单错误（5分钟内解决）                           │\n│  ├── 语法错误、拼写错误                                    │\n│  ├── 方法：直接复制错误信息给 AI                           │\n│  └── 工具：Copilot Chat / ChatGPT                        │\n│                                                           │\n│  Level 2：中等复杂度（30分钟内解决）                        │\n│  ├── 类型错误、逻辑错误、API 使用错误                      │\n│  ├── 方法：提供错误信息 + 相关代码 + 上下文                 │\n│  └── 工具：Cursor Chat / Claude                          │\n│                                                           │\n│  Level 3：复杂问题（需要深入分析）                          │\n│  ├── 竞态条件、内存泄漏、性能问题                          │\n│  ├── 方法：详细描述场景 + 提供多个文件 + 讨论               │\n│  └── 工具：Cursor Composer / 专门的 AI 会话                │\n│                                                           │\n│  Level 4：架构级问题                                       │\n│  ├── 设计缺陷、技术债务                                    │\n│  ├── 方法：AI 辅助分析 + 人工判断                          │\n│  └── 工具：与团队讨论 + AI 作为顾问                        │\n│                                                           │\n└───────────────────────────────────────────────────────────┘",{"type":25,"tag":235,"props":5163,"children":5165},{"code":5164},"\n## 第二部分：错误信息分析\n\n### 2.1 前端错误分析\n\n**场景 1：React 错误边界触发**\n\n```typescript\n// 错误信息：\n// Error: Hydration failed because the initial UI does not match \n// what was rendered on the server.\n\n// 提问方式：\n/**\n * 我在 Next.js 14 App Router 项目中遇到这个错误：\n * \n * Error: Hydration failed because the initial UI does not match \n * what was rendered on the server.\n * \n * 相关代码：\n */\nfunction UserStatus() {\n  const [isLoggedIn, setIsLoggedIn] = useState(false);\n  \n  useEffect(() => {\n    setIsLoggedIn(localStorage.getItem('token') !== null);\n  }, []);\n  \n  return \u003Cdiv>{isLoggedIn ? '已登录' : '未登录'}\u003C/div>;\n}\n\n// AI 会分析出：\n// 1. 服务端渲染时 localStorage 不可用，默认 false\n// 2. 客户端 hydration 时可能是 true\n// 3. 导致服务端和客户端渲染结果不一致\n\n// AI 建议的解决方案：\nfunction UserStatus() {\n  const [isLoggedIn, setIsLoggedIn] = useState\u003Cboolean | null>(null);\n  \n  useEffect(() => {\n    setIsLoggedIn(localStorage.getItem('token') !== null);\n  }, []);\n  \n  // 初始状态显示加载中，避免 hydration 不匹配\n  if (isLoggedIn === null) {\n    return \u003Cdiv>加载中...\u003C/div>;\n  }\n  \n  return \u003Cdiv>{isLoggedIn ? '已登录' : '未登录'}\u003C/div>;\n}\n",[5166],{"type":25,"tag":240,"props":5167,"children":5168},{"__ignoreMap":7},[5169],{"type":31,"value":5164},{"type":25,"tag":34,"props":5171,"children":5172},{},[5173],{"type":25,"tag":38,"props":5174,"children":5175},{},[5176],{"type":31,"value":5177},"场景 2：Vue 响应式警告",{"type":25,"tag":235,"props":5179,"children":5182},{"code":5180,"language":1447,"meta":7,"className":5181},"// 警告信息：\n// [Vue warn]: Property \"xxx\" was accessed during render but is not \n// defined on instance.\n\n// 提问方式：\n/**\n * Vue 3 项目中出现这个警告：\n * [Vue warn]: Property \"userInfo\" was accessed during render \n * but is not defined on instance.\n * \n * 组件代码：\n */\n\u003Ctemplate>\n  \u003Cdiv>{{ userInfo.name }}\u003C/div>\n\u003C/template>\n\n\u003Cscript setup>\nconst { data: userInfo } = await useFetch('/api/user');\n\u003C/script>\n\n// AI 分析：\n// 1. useFetch 是异步的，初始渲染时 userInfo 可能是 undefined\n// 2. 直接访问 userInfo.name 会报错\n\n// AI 建议：\n\u003Ctemplate>\n  \u003Cdiv v-if=\"userInfo\">{{ userInfo.name }}\u003C/div>\n  \u003Cdiv v-else>加载中...\u003C/div>\n\u003C/template>\n\n\u003Cscript setup>\nconst { data: userInfo, pending } = await useFetch('/api/user');\n\u003C/script>\n",[1449],[5183],{"type":25,"tag":240,"props":5184,"children":5185},{"__ignoreMap":7},[5186],{"type":31,"value":5180},{"type":25,"tag":223,"props":5188,"children":5190},{"id":5189},"_22-后端错误分析",[5191],{"type":31,"value":5192},"2.2 后端错误分析",{"type":25,"tag":34,"props":5194,"children":5195},{},[5196],{"type":25,"tag":38,"props":5197,"children":5198},{},[5199],{"type":31,"value":5200},"场景 1：Node.js 内存问题",{"type":25,"tag":235,"props":5202,"children":5207},{"code":5203,"language":5204,"meta":7,"className":5205},"// 错误信息：\n// FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - \n// JavaScript heap out of memory\n\n// 提问方式（包含上下文）：\n/**\n * Node.js 服务运行几小时后崩溃，错误信息：\n * FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - \n * JavaScript heap out of memory\n * \n * 服务功能：处理 CSV 文件上传，每次约 100MB\n * \n * 处理代码：\n */\nasync function processCSV(filePath) {\n  const content = fs.readFileSync(filePath, 'utf-8');\n  const rows = content.split('\\n');\n  const results = [];\n  \n  for (const row of rows) {\n    const processed = await processRow(row);\n    results.push(processed);\n  }\n  \n  return results;\n}\n\n// AI 分析会指出：\n// 1. 一次性读取整个文件到内存\n// 2. 所有处理结果累积在 results 数组\n// 3. 建议使用流式处理\n\n// AI 提供的优化方案：\nconst { createReadStream } = require('fs');\nconst { createInterface } = require('readline');\n\nasync function processCSVStream(filePath, onRow) {\n  const fileStream = createReadStream(filePath);\n  const rl = createInterface({\n    input: fileStream,\n    crlfDelay: Infinity\n  });\n  \n  let count = 0;\n  for await (const line of rl) {\n    await onRow(line);\n    count++;\n    \n    // 每处理 1000 行，给 GC 机会运行\n    if (count % 1000 === 0) {\n      await new Promise(r => setImmediate(r));\n    }\n  }\n}\n","javascript",[5206],"language-javascript",[5208],{"type":25,"tag":240,"props":5209,"children":5210},{"__ignoreMap":7},[5211],{"type":31,"value":5203},{"type":25,"tag":34,"props":5213,"children":5214},{},[5215],{"type":25,"tag":38,"props":5216,"children":5217},{},[5218],{"type":31,"value":5219},"场景 2：数据库连接问题",{"type":25,"tag":235,"props":5221,"children":5224},{"code":5222,"language":1447,"meta":7,"className":5223},"// 错误信息：\n// Error: Connection pool exhausted - \n// max connections (10) already in use\n\n// 提问方式：\n/**\n * PostgreSQL 连接池耗尽错误，高并发时出现：\n * Error: Connection pool exhausted\n * \n * 当前配置：\n * - max connections: 10\n * - 并发请求: 约 100/秒\n * \n * 数据库调用代码：\n */\nasync function getUserData(userId: string) {\n  const client = await pool.connect();\n  try {\n    const user = await client.query('SELECT * FROM users WHERE id = $1', [userId]);\n    const orders = await client.query('SELECT * FROM orders WHERE user_id = $1', [userId]);\n    const payments = await client.query('SELECT * FROM payments WHERE user_id = $1', [userId]);\n    return { user: user.rows[0], orders: orders.rows, payments: payments.rows };\n  } finally {\n    client.release();\n  }\n}\n\n// AI 会分析出多个可能原因并给出综合方案\n",[1449],[5225],{"type":25,"tag":240,"props":5226,"children":5227},{"__ignoreMap":7},[5228],{"type":31,"value":5222},{"type":25,"tag":26,"props":5230,"children":5232},{"id":5231},"第三部分日志分析与问题定位",[5233],{"type":31,"value":5234},"第三部分：日志分析与问题定位",{"type":25,"tag":223,"props":5236,"children":5238},{"id":5237},"_31-结构化日志分析",[5239],{"type":31,"value":5240},"3.1 结构化日志分析",{"type":25,"tag":34,"props":5242,"children":5243},{},[5244],{"type":31,"value":5245},"当面对大量日志时，让 AI 帮你快速定位问题：",{"type":25,"tag":235,"props":5247,"children":5250},{"code":5248,"language":5204,"meta":7,"className":5249},"// 提问示例：\n/**\n * 分析以下日志，找出导致请求失败的原因：\n * \n * 日志片段：\n */\nconst logs = `\n2024-01-15 10:23:45.123 INFO  [req-abc123] 收到请求 POST /api/order\n2024-01-15 10:23:45.125 DEBUG [req-abc123] 用户认证通过 userId=u001\n2024-01-15 10:23:45.130 DEBUG [req-abc123] 开始库存检查 productId=p001\n2024-01-15 10:23:45.145 DEBUG [req-abc123] 库存检查通过 available=50\n2024-01-15 10:23:45.150 DEBUG [req-abc123] 开始创建订单\n2024-01-15 10:23:45.200 DEBUG [req-abc123] 数据库连接获取成功\n2024-01-15 10:23:45.250 ERROR [req-abc123] 订单创建失败 error=\"deadlock detected\"\n2024-01-15 10:23:45.251 WARN  [req-abc123] 事务回滚\n2024-01-15 10:23:45.255 INFO  [req-abc123] 响应 500 耗时 132ms\n`;\n\n// AI 分析结果会包括：\n// 1. 问题定位：数据库死锁\n// 2. 可能原因：并发订单创建导致锁竞争\n// 3. 排查建议：检查事务隔离级别、锁顺序\n",[5206],[5251],{"type":25,"tag":240,"props":5252,"children":5253},{"__ignoreMap":7},[5254],{"type":31,"value":5248},{"type":25,"tag":223,"props":5256,"children":5258},{"id":5257},"_32-创建调试日志",[5259],{"type":31,"value":5260},"3.2 创建调试日志",{"type":25,"tag":34,"props":5262,"children":5263},{},[5264],{"type":31,"value":5265},"让 AI 帮你生成调试用的日志代码：",{"type":25,"tag":235,"props":5267,"children":5270},{"code":5268,"language":1447,"meta":7,"className":5269},"// 请求：\n// \"为这个函数添加详细的调试日志，包括入参、关键步骤、耗时和结果\"\n\n// 原代码：\nasync function processOrder(order: Order): Promise\u003COrderResult> {\n  const inventory = await checkInventory(order.items);\n  const payment = await processPayment(order.userId, order.total);\n  const result = await createOrder(order, payment.transactionId);\n  return result;\n}\n\n// AI 生成的带日志版本：\nasync function processOrder(order: Order): Promise\u003COrderResult> {\n  const requestId = generateRequestId();\n  const startTime = performance.now();\n  \n  logger.info({\n    requestId,\n    event: 'order_processing_start',\n    orderId: order.id,\n    userId: order.userId,\n    itemCount: order.items.length,\n    total: order.total\n  });\n  \n  try {\n    // 库存检查\n    const inventoryStart = performance.now();\n    const inventory = await checkInventory(order.items);\n    logger.debug({\n      requestId,\n      event: 'inventory_check_complete',\n      duration: performance.now() - inventoryStart,\n      available: inventory.allAvailable\n    });\n    \n    // 支付处理\n    const paymentStart = performance.now();\n    const payment = await processPayment(order.userId, order.total);\n    logger.debug({\n      requestId,\n      event: 'payment_complete',\n      duration: performance.now() - paymentStart,\n      transactionId: payment.transactionId\n    });\n    \n    // 创建订单\n    const createStart = performance.now();\n    const result = await createOrder(order, payment.transactionId);\n    logger.debug({\n      requestId,\n      event: 'order_created',\n      duration: performance.now() - createStart,\n      resultOrderId: result.orderId\n    });\n    \n    logger.info({\n      requestId,\n      event: 'order_processing_complete',\n      duration: performance.now() - startTime,\n      success: true\n    });\n    \n    return result;\n  } catch (error) {\n    logger.error({\n      requestId,\n      event: 'order_processing_failed',\n      duration: performance.now() - startTime,\n      error: error.message,\n      stack: error.stack\n    });\n    throw error;\n  }\n}\n",[1449],[5271],{"type":25,"tag":240,"props":5272,"children":5273},{"__ignoreMap":7},[5274],{"type":31,"value":5268},{"type":25,"tag":26,"props":5276,"children":5278},{"id":5277},"第四部分性能问题排查",[5279],{"type":31,"value":5280},"第四部分：性能问题排查",{"type":25,"tag":223,"props":5282,"children":5284},{"id":5283},"_41-前端性能分析",[5285],{"type":31,"value":5286},"4.1 前端性能分析",{"type":25,"tag":235,"props":5288,"children":5291},{"code":5289,"language":1447,"meta":7,"className":5290},"// 场景：页面加载慢，需要分析原因\n\n// 提问方式：\n/**\n * 页面首屏加载需要 5 秒，以下是 Performance API 数据，\n * 请分析性能瓶颈：\n */\nconst performanceData = {\n  // Navigation Timing\n  dns: 50,           // DNS 查询\n  tcp: 100,          // TCP 连接\n  ttfb: 800,         // 首字节时间\n  download: 200,     // 文档下载\n  domParsing: 300,   // DOM 解析\n  domContentLoaded: 1500,\n  load: 5000,\n  \n  // Resource Timing (主要资源)\n  resources: [\n    { name: 'main.js', size: '2.5MB', duration: 1200 },\n    { name: 'vendor.js', size: '1.8MB', duration: 900 },\n    { name: 'styles.css', size: '500KB', duration: 300 },\n    { name: 'hero-image.jpg', size: '3MB', duration: 1500 },\n  ],\n  \n  // Long Tasks\n  longTasks: [\n    { startTime: 1600, duration: 800, name: 'script-evaluation' },\n    { startTime: 2500, duration: 400, name: 'layout' }\n  ]\n};\n\n// AI 会分析出：\n// 1. JS bundle 过大（4.3MB），需要代码分割\n// 2. 图片未优化（3MB 的 hero 图片）\n// 3. 存在长任务阻塞主线程\n// 并给出具体优化建议\n",[1449],[5292],{"type":25,"tag":240,"props":5293,"children":5294},{"__ignoreMap":7},[5295],{"type":31,"value":5289},{"type":25,"tag":223,"props":5297,"children":5299},{"id":5298},"_42-内存泄漏排查",[5300],{"type":31,"value":5301},"4.2 内存泄漏排查",{"type":25,"tag":235,"props":5303,"children":5306},{"code":5304,"language":1447,"meta":7,"className":5305},"// 场景：应用运行一段时间后变卡\n\n// 提问方式：\n/**\n * React 应用运行一段时间后内存持续增长，以下是 Heap Snapshot 对比：\n * \n * 初始状态：50MB\n * 运行 1 小时后：150MB\n * 运行 2 小时后：280MB\n * \n * Retained objects 增长最快的：\n * - (closure) - 增长 50MB\n * - HTMLDivElement - 增长 30MB\n * - Array - 增长 20MB\n * \n * 可疑代码：\n */\nfunction DataDashboard() {\n  const [data, setData] = useState([]);\n  const chartRef = useRef(null);\n  \n  useEffect(() => {\n    // 每秒刷新数据\n    const interval = setInterval(async () => {\n      const newData = await fetchLatestData();\n      setData(prev => [...prev, ...newData]);  // 数据不断累积\n    }, 1000);\n    \n    // 初始化图表\n    const chart = new Chart(chartRef.current, {\n      // 配置...\n    });\n    \n    // 没有 cleanup！\n  }, []);\n  \n  return \u003Ccanvas ref={chartRef} />;\n}\n\n// AI 会指出：\n// 1. interval 没有清理\n// 2. Chart 实例没有销毁\n// 3. data 无限增长\n// 并提供修复代码\n",[1449],[5307],{"type":25,"tag":240,"props":5308,"children":5309},{"__ignoreMap":7},[5310],{"type":31,"value":5304},{"type":25,"tag":223,"props":5312,"children":5314},{"id":5313},"_43-数据库查询优化",[5315],{"type":31,"value":5316},"4.3 数据库查询优化",{"type":25,"tag":235,"props":5318,"children":5323},{"code":5319,"language":5320,"meta":7,"className":5321},"-- 场景：查询很慢，让 AI 分析执行计划\n\n-- 提问方式：\n-- 以下查询在数据量大时很慢（orders 表 1000 万行），\n-- 执行计划如下，请分析并优化：\n\nEXPLAIN ANALYZE\nSELECT o.*, u.name, u.email\nFROM orders o\nJOIN users u ON o.user_id = u.id\nWHERE o.status = 'pending'\n  AND o.created_at > '2024-01-01'\nORDER BY o.created_at DESC\nLIMIT 20;\n\n-- 执行计划：\n/*\nSort  (cost=156847.23..157847.23 rows=400000 width=250)\n  Sort Key: o.created_at DESC\n  ->  Hash Join  (cost=1500.00..89847.23 rows=400000 width=250)\n        Hash Cond: (o.user_id = u.id)\n        ->  Seq Scan on orders o  (cost=0.00..85000.00 rows=400000)\n              Filter: ((status = 'pending') AND (created_at > '2024-01-01'))\n        ->  Hash  (cost=1000.00..1000.00 rows=50000 width=100)\n              ->  Seq Scan on users u  (cost=0.00..1000.00 rows=50000)\nPlanning Time: 0.5 ms\nExecution Time: 3500 ms\n*/\n\n-- AI 会分析出问题并建议：\n-- 1. orders 表全表扫描 - 需要复合索引\n-- 2. 建议创建索引：\nCREATE INDEX idx_orders_status_created ON orders(status, created_at DESC);\n\n-- 3. 如果 status 选择性不高，考虑部分索引：\nCREATE INDEX idx_orders_pending ON orders(created_at DESC) \nWHERE status = 'pending';\n","sql",[5322],"language-sql",[5324],{"type":25,"tag":240,"props":5325,"children":5326},{"__ignoreMap":7},[5327],{"type":31,"value":5319},{"type":25,"tag":26,"props":5329,"children":5331},{"id":5330},"第五部分复杂-bug-排查",[5332],{"type":31,"value":5333},"第五部分：复杂 Bug 排查",{"type":25,"tag":223,"props":5335,"children":5337},{"id":5336},"_51-竞态条件",[5338],{"type":31,"value":5339},"5.1 竞态条件",{"type":25,"tag":235,"props":5341,"children":5344},{"code":5342,"language":1447,"meta":7,"className":5343},"// 场景：偶发的数据不一致问题\n\n// 提问方式：\n/**\n * 用户反馈偶尔看到错误的账户余额，但刷新后正常。\n * 怀疑是竞态条件，以下是相关代码：\n */\nasync function updateBalance(userId: string, amount: number) {\n  // 读取当前余额\n  const user = await db.users.findOne({ id: userId });\n  const newBalance = user.balance + amount;\n  \n  // 更新余额\n  await db.users.update({ id: userId }, { balance: newBalance });\n  \n  // 记录交易\n  await db.transactions.create({\n    userId,\n    amount,\n    balanceAfter: newBalance,\n    createdAt: new Date()\n  });\n  \n  return newBalance;\n}\n\n// 并发调用场景：\n// 用户同时发起两笔交易：+100 和 -50\n// 期望结果：原余额 1000 → 1050\n// 实际可能：原余额 1000 → 1100 或 950\n\n// AI 会分析竞态条件并提供解决方案：\nasync function updateBalanceAtomic(userId: string, amount: number) {\n  // 方案 1：使用数据库原子操作\n  const result = await db.users.findOneAndUpdate(\n    { id: userId },\n    { $inc: { balance: amount } },\n    { returnDocument: 'after' }\n  );\n  \n  await db.transactions.create({\n    userId,\n    amount,\n    balanceAfter: result.balance,\n    createdAt: new Date()\n  });\n  \n  return result.balance;\n}\n\n// 方案 2：使用乐观锁\nasync function updateBalanceOptimistic(userId: string, amount: number) {\n  const maxRetries = 3;\n  \n  for (let i = 0; i \u003C maxRetries; i++) {\n    const user = await db.users.findOne({ id: userId });\n    const newBalance = user.balance + amount;\n    \n    const updated = await db.users.updateOne(\n      { id: userId, version: user.version },\n      { balance: newBalance, version: user.version + 1 }\n    );\n    \n    if (updated.modifiedCount === 1) {\n      await db.transactions.create({...});\n      return newBalance;\n    }\n    \n    // 版本冲突，重试\n    await sleep(10 * (i + 1));\n  }\n  \n  throw new Error('Update failed after retries');\n}\n",[1449],[5345],{"type":25,"tag":240,"props":5346,"children":5347},{"__ignoreMap":7},[5348],{"type":31,"value":5342},{"type":25,"tag":223,"props":5350,"children":5352},{"id":5351},"_52-分布式系统问题",[5353],{"type":31,"value":5354},"5.2 分布式系统问题",{"type":25,"tag":235,"props":5356,"children":5359},{"code":5357,"language":1447,"meta":7,"className":5358},"// 场景：微服务间的数据不一致\n\n// 提问方式：\n/**\n * 订单服务和库存服务偶尔出现数据不一致：\n * - 订单显示已创建\n * - 库存未扣减\n * \n * 当前流程：\n */\n// Order Service\nasync function createOrder(orderData) {\n  // 1. 调用库存服务扣减库存\n  await inventoryService.deduct(orderData.items);\n  \n  // 2. 创建订单\n  const order = await orderRepository.create(orderData);\n  \n  // 3. 发送订单创建事件\n  await eventBus.publish('order.created', order);\n  \n  return order;\n}\n\n// 问题分析：如果步骤 2 或 3 失败，库存已经扣减但订单未创建\n\n// AI 会建议使用 Saga 模式或事务发件箱模式\n",[1449],[5360],{"type":25,"tag":240,"props":5361,"children":5362},{"__ignoreMap":7},[5363],{"type":31,"value":5357},{"type":25,"tag":26,"props":5365,"children":5367},{"id":5366},"第六部分ai-调试工作流",[5368],{"type":31,"value":5369},"第六部分：AI 调试工作流",{"type":25,"tag":223,"props":5371,"children":5373},{"id":5372},"_61-我的调试流程",[5374],{"type":31,"value":5375},"6.1 我的调试流程",{"type":25,"tag":235,"props":5377,"children":5379},{"code":5378},"┌────────────────────────────────────────────────────────────┐\n│                    AI 辅助调试工作流                         │\n├────────────────────────────────────────────────────────────┤\n│                                                            │\n│  Step 1: 问题收集                                          │\n│  ├── 复制完整错误信息                                       │\n│  ├── 截图相关日志                                          │\n│  └── 记录复现步骤                                          │\n│                                                            │\n│  Step 2: 快速分析                                          │\n│  ├── 将错误信息发给 AI                                      │\n│  ├── 获取可能原因列表                                       │\n│  └── 评估哪些最可能                                         │\n│                                                            │\n│  Step 3: 深入调查                                          │\n│  ├── 根据 AI 建议添加日志/断点                              │\n│  ├── 收集更多信息                                          │\n│  └── 再次询问 AI（带新信息）                                │\n│                                                            │\n│  Step 4: 验证修复                                          │\n│  ├── AI 生成修复代码                                        │\n│  ├── 人工审查确认                                          │\n│  └── 测试验证                                               │\n│                                                            │\n│  Step 5: 预防措施                                          │\n│  ├── AI 建议类似问题的预防方法                              │\n│  ├── 添加相关测试用例                                       │\n│  └── 更新文档/知识库                                        │\n│                                                            │\n└────────────────────────────────────────────────────────────┘\n",[5380],{"type":25,"tag":240,"props":5381,"children":5382},{"__ignoreMap":7},[5383],{"type":31,"value":5378},{"type":25,"tag":223,"props":5385,"children":5387},{"id":5386},"_62-调试对话模板",[5388],{"type":31,"value":5389},"6.2 调试对话模板",{"type":25,"tag":235,"props":5391,"children":5394},{"code":5392,"language":1473,"meta":7,"className":5393},"## 第一轮：问题描述\n\n我遇到了一个问题：[简述问题]\n\n错误信息：\n",[1475],[5395],{"type":25,"tag":240,"props":5396,"children":5397},{"__ignoreMap":7},[5398],{"type":31,"value":5392},{"type":25,"tag":34,"props":5400,"children":5401},{},[5402],{"type":25,"tag":5044,"props":5403,"children":5404},{},[5405],{"type":31,"value":5406},"粘贴完整错误",{"type":25,"tag":235,"props":5408,"children":5410},{"code":5409},"\n相关代码：\n```javascript\n[粘贴代码]\n",[5411],{"type":25,"tag":240,"props":5412,"children":5413},{"__ignoreMap":7},[5414],{"type":31,"value":5409},{"type":25,"tag":213,"props":5416,"children":5417},{},[],{"type":25,"tag":26,"props":5419,"children":5421},{"id":5420},"第二轮补充信息",[5422],{"type":31,"value":5423},"第二轮：补充信息",{"type":25,"tag":34,"props":5425,"children":5426},{},[5427],{"type":31,"value":5428},"根据你的建议，我添加了日志，发现：",{"type":25,"tag":56,"props":5430,"children":5431},{},[5432,5440],{"type":25,"tag":60,"props":5433,"children":5434},{},[5435],{"type":25,"tag":5044,"props":5436,"children":5437},{},[5438],{"type":31,"value":5439},"发现 1",{"type":25,"tag":60,"props":5441,"children":5442},{},[5443],{"type":25,"tag":5044,"props":5444,"children":5445},{},[5446],{"type":31,"value":5447},"发现 2",{"type":25,"tag":34,"props":5449,"children":5450},{},[5451,5453,5458],{"type":31,"value":5452},"这是否说明问题出在 ",{"type":25,"tag":5044,"props":5454,"children":5455},{},[5456],{"type":31,"value":5457},"你的猜测",{"type":31,"value":5459},"？",{"type":25,"tag":213,"props":5461,"children":5462},{},[],{"type":25,"tag":26,"props":5464,"children":5466},{"id":5465},"第三轮确认修复",[5467],{"type":31,"value":5468},"第三轮：确认修复",{"type":25,"tag":34,"props":5470,"children":5471},{},[5472],{"type":31,"value":5473},"我按照你的建议修改了代码：",{"type":25,"tag":235,"props":5475,"children":5478},{"code":5476,"language":5204,"meta":7,"className":5477},"[粘贴修改后的代码]\n",[5206],[5479],{"type":25,"tag":240,"props":5480,"children":5481},{"__ignoreMap":7},[5482],{"type":31,"value":5476},{"type":25,"tag":34,"props":5484,"children":5485},{},[5486],{"type":31,"value":5487},"请确认这个修复是否正确，以及是否有其他潜在问题。",{"type":25,"tag":213,"props":5489,"children":5490},{},[],{"type":25,"tag":26,"props":5492,"children":5494},{"id":5493},"第四轮预防",[5495],{"type":31,"value":5496},"第四轮：预防",{"type":25,"tag":34,"props":5498,"children":5499},{},[5500],{"type":31,"value":5501},"这个问题已解决。请建议：",{"type":25,"tag":2661,"props":5503,"children":5504},{},[5505,5510,5515],{"type":25,"tag":60,"props":5506,"children":5507},{},[5508],{"type":31,"value":5509},"如何防止类似问题再次发生？",{"type":25,"tag":60,"props":5511,"children":5512},{},[5513],{"type":31,"value":5514},"应该添加什么测试用例？",{"type":25,"tag":60,"props":5516,"children":5517},{},[5518],{"type":31,"value":5519},"有什么最佳实践可以参考？",{"type":25,"tag":235,"props":5521,"children":5523},{"code":5522},"\n## 结语：AI 是放大器，不是替代品\n\nAI 调试工具能够显著加速问题排查过程，但它不能替代你的思考。最有价值的能力组合是：\n\n- **你的领域知识** + **AI 的广博见识**\n- **你对项目的理解** + **AI 的分析能力**\n- **你的判断力** + **AI 的执行速度**\n\n调试的本质是假设-验证的循环。AI 帮你更快地生成假设、更高效地验证假设，但做出最终判断的还是你。\n\n学会与 AI 高效协作调试，不是依赖 AI 给你答案，而是让 AI 帮你更快地找到自己的答案。\n\n---\n\n## 参考资源\n\n- [Chrome DevTools 官方文档](https://developer.chrome.com/docs/devtools)\n- [Node.js 调试指南](https://nodejs.org/en/docs/guides/debugging-getting-started)\n- [React DevTools 使用指南](https://react.dev/learn/react-developer-tools)\n",[5524],{"type":25,"tag":240,"props":5525,"children":5526},{"__ignoreMap":7},[5527],{"type":31,"value":5522},{"title":7,"searchDepth":2709,"depth":2709,"links":5529},[5530,5531,5532,5537,5541,5546,5550,5554,5555,5556],{"id":4916,"depth":2712,"text":4919},{"id":4922,"depth":2712,"text":4925},{"id":4943,"depth":2712,"text":4946,"children":5533},[5534,5535,5536],{"id":4949,"depth":2709,"text":4952},{"id":5027,"depth":2709,"text":5030},{"id":5189,"depth":2709,"text":5192},{"id":5231,"depth":2712,"text":5234,"children":5538},[5539,5540],{"id":5237,"depth":2709,"text":5240},{"id":5257,"depth":2709,"text":5260},{"id":5277,"depth":2712,"text":5280,"children":5542},[5543,5544,5545],{"id":5283,"depth":2709,"text":5286},{"id":5298,"depth":2709,"text":5301},{"id":5313,"depth":2709,"text":5316},{"id":5330,"depth":2712,"text":5333,"children":5547},[5548,5549],{"id":5336,"depth":2709,"text":5339},{"id":5351,"depth":2709,"text":5354},{"id":5366,"depth":2712,"text":5369,"children":5551},[5552,5553],{"id":5372,"depth":2709,"text":5375},{"id":5386,"depth":2709,"text":5389},{"id":5420,"depth":2712,"text":5423},{"id":5465,"depth":2712,"text":5468},{"id":5493,"depth":2712,"text":5496},"content:topics:ai:ai-debugging-troubleshooting-guide.md","topics/ai/ai-debugging-troubleshooting-guide.md","topics/ai/ai-debugging-troubleshooting-guide",{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"tags":5561,"category":17,"author":18,"status":19,"image":20,"body":5562,"_type":1473,"_id":2799,"_source":2800,"_file":2801,"_stem":2802,"_extension":2803},[12,13,14,15,16],{"type":22,"children":5563,"toc":7773},[5564,5568,5576,5584,5619,5627,5711,5714,5718,5722,5726,5733,5741,5768,5772,5779,5787,5814,5818,5822,5926,5934,5979,6035,6038,6042,6046,6053,6061,6195,6199,6203,6359,6367,6371,6465,6473,6477,6571,6579,6583,6591,6594,6598,6602,6606,6614,6618,6626,6634,6641,6651,6659,6663,6667,6675,6684,6692,6696,6704,6712,6720,6724,6728,6736,6744,6748,6756,6764,6772,6779,6783,6787,6795,6798,6802,6806,6816,6824,6828,6838,6846,6850,6858,6866,6874,6878,6882,6890,6894,6902,6905,6909,6913,6923,6931,6935,6945,6953,6957,6965,6969,6973,6981,6984,6988,6992,7111,7115,7119,7127,7131,7139,7143,7147,7155,7163,7171,7174,7178,7182,7190,7194,7198,7205,7209,7217,7220,7224,7228,7321,7325,7407,7411,7480,7484,7553,7556,7560,7564,7619,7623,7680,7684,7715,7718,7722,7726,7734,7769],{"type":25,"tag":26,"props":5565,"children":5566},{"id":28},[5567],{"type":31,"value":32},{"type":25,"tag":34,"props":5569,"children":5570},{},[5571,5575],{"type":25,"tag":38,"props":5572,"children":5573},{},[5574],{"type":31,"value":42},{"type":31,"value":44},{"type":25,"tag":34,"props":5577,"children":5578},{},[5579,5583],{"type":25,"tag":38,"props":5580,"children":5581},{},[5582],{"type":31,"value":52},{"type":31,"value":54},{"type":25,"tag":56,"props":5585,"children":5586},{},[5587,5595,5603,5611],{"type":25,"tag":60,"props":5588,"children":5589},{},[5590,5594],{"type":25,"tag":38,"props":5591,"children":5592},{},[5593],{"type":31,"value":67},{"type":31,"value":69},{"type":25,"tag":60,"props":5596,"children":5597},{},[5598,5602],{"type":25,"tag":38,"props":5599,"children":5600},{},[5601],{"type":31,"value":77},{"type":31,"value":79},{"type":25,"tag":60,"props":5604,"children":5605},{},[5606,5610],{"type":25,"tag":38,"props":5607,"children":5608},{},[5609],{"type":31,"value":87},{"type":31,"value":89},{"type":25,"tag":60,"props":5612,"children":5613},{},[5614,5618],{"type":25,"tag":38,"props":5615,"children":5616},{},[5617],{"type":31,"value":97},{"type":31,"value":99},{"type":25,"tag":34,"props":5620,"children":5621},{},[5622,5626],{"type":25,"tag":38,"props":5623,"children":5624},{},[5625],{"type":31,"value":107},{"type":31,"value":54},{"type":25,"tag":110,"props":5628,"children":5629},{},[5630,5648],{"type":25,"tag":114,"props":5631,"children":5632},{},[5633],{"type":25,"tag":118,"props":5634,"children":5635},{},[5636,5640,5644],{"type":25,"tag":122,"props":5637,"children":5638},{},[5639],{"type":31,"value":126},{"type":25,"tag":122,"props":5641,"children":5642},{},[5643],{"type":31,"value":131},{"type":25,"tag":122,"props":5645,"children":5646},{},[5647],{"type":31,"value":136},{"type":25,"tag":138,"props":5649,"children":5650},{},[5651,5666,5681,5696],{"type":25,"tag":118,"props":5652,"children":5653},{},[5654,5658,5662],{"type":25,"tag":145,"props":5655,"children":5656},{},[5657],{"type":31,"value":149},{"type":25,"tag":145,"props":5659,"children":5660},{},[5661],{"type":31,"value":154},{"type":25,"tag":145,"props":5663,"children":5664},{},[5665],{"type":31,"value":159},{"type":25,"tag":118,"props":5667,"children":5668},{},[5669,5673,5677],{"type":25,"tag":145,"props":5670,"children":5671},{},[5672],{"type":31,"value":167},{"type":25,"tag":145,"props":5674,"children":5675},{},[5676],{"type":31,"value":172},{"type":25,"tag":145,"props":5678,"children":5679},{},[5680],{"type":31,"value":177},{"type":25,"tag":118,"props":5682,"children":5683},{},[5684,5688,5692],{"type":25,"tag":145,"props":5685,"children":5686},{},[5687],{"type":31,"value":185},{"type":25,"tag":145,"props":5689,"children":5690},{},[5691],{"type":31,"value":190},{"type":25,"tag":145,"props":5693,"children":5694},{},[5695],{"type":31,"value":159},{"type":25,"tag":118,"props":5697,"children":5698},{},[5699,5703,5707],{"type":25,"tag":145,"props":5700,"children":5701},{},[5702],{"type":31,"value":202},{"type":25,"tag":145,"props":5704,"children":5705},{},[5706],{"type":31,"value":207},{"type":25,"tag":145,"props":5708,"children":5709},{},[5710],{"type":31,"value":177},{"type":25,"tag":213,"props":5712,"children":5713},{},[],{"type":25,"tag":26,"props":5715,"children":5716},{"id":218},[5717],{"type":31,"value":221},{"type":25,"tag":223,"props":5719,"children":5720},{"id":225},[5721],{"type":31,"value":228},{"type":25,"tag":34,"props":5723,"children":5724},{},[5725],{"type":31,"value":233},{"type":25,"tag":235,"props":5727,"children":5728},{"code":237},[5729],{"type":25,"tag":240,"props":5730,"children":5731},{"__ignoreMap":7},[5732],{"type":31,"value":237},{"type":25,"tag":34,"props":5734,"children":5735},{},[5736,5740],{"type":25,"tag":38,"props":5737,"children":5738},{},[5739],{"type":31,"value":251},{"type":31,"value":54},{"type":25,"tag":56,"props":5742,"children":5743},{},[5744,5752,5760],{"type":25,"tag":60,"props":5745,"children":5746},{},[5747,5751],{"type":25,"tag":38,"props":5748,"children":5749},{},[5750],{"type":31,"value":263},{"type":31,"value":265},{"type":25,"tag":60,"props":5753,"children":5754},{},[5755,5759],{"type":25,"tag":38,"props":5756,"children":5757},{},[5758],{"type":31,"value":273},{"type":31,"value":275},{"type":25,"tag":60,"props":5761,"children":5762},{},[5763,5767],{"type":25,"tag":38,"props":5764,"children":5765},{},[5766],{"type":31,"value":283},{"type":31,"value":285},{"type":25,"tag":223,"props":5769,"children":5770},{"id":288},[5771],{"type":31,"value":291},{"type":25,"tag":235,"props":5773,"children":5774},{"code":294},[5775],{"type":25,"tag":240,"props":5776,"children":5777},{"__ignoreMap":7},[5778],{"type":31,"value":294},{"type":25,"tag":34,"props":5780,"children":5781},{},[5782,5786],{"type":25,"tag":38,"props":5783,"children":5784},{},[5785],{"type":31,"value":307},{"type":31,"value":54},{"type":25,"tag":56,"props":5788,"children":5789},{},[5790,5798,5806],{"type":25,"tag":60,"props":5791,"children":5792},{},[5793,5797],{"type":25,"tag":38,"props":5794,"children":5795},{},[5796],{"type":31,"value":319},{"type":31,"value":321},{"type":25,"tag":60,"props":5799,"children":5800},{},[5801,5805],{"type":25,"tag":38,"props":5802,"children":5803},{},[5804],{"type":31,"value":329},{"type":31,"value":331},{"type":25,"tag":60,"props":5807,"children":5808},{},[5809,5813],{"type":25,"tag":38,"props":5810,"children":5811},{},[5812],{"type":31,"value":339},{"type":31,"value":341},{"type":25,"tag":223,"props":5815,"children":5816},{"id":344},[5817],{"type":31,"value":347},{"type":25,"tag":34,"props":5819,"children":5820},{},[5821],{"type":31,"value":352},{"type":25,"tag":110,"props":5823,"children":5824},{},[5825,5847],{"type":25,"tag":114,"props":5826,"children":5827},{},[5828],{"type":25,"tag":118,"props":5829,"children":5830},{},[5831,5835,5839,5843],{"type":25,"tag":122,"props":5832,"children":5833},{},[5834],{"type":31,"value":366},{"type":25,"tag":122,"props":5836,"children":5837},{},[5838],{"type":31,"value":371},{"type":25,"tag":122,"props":5840,"children":5841},{},[5842],{"type":31,"value":376},{"type":25,"tag":122,"props":5844,"children":5845},{},[5846],{"type":31,"value":381},{"type":25,"tag":138,"props":5848,"children":5849},{},[5850,5869,5888,5907],{"type":25,"tag":118,"props":5851,"children":5852},{},[5853,5857,5861,5865],{"type":25,"tag":145,"props":5854,"children":5855},{},[5856],{"type":31,"value":392},{"type":25,"tag":145,"props":5858,"children":5859},{},[5860],{"type":31,"value":397},{"type":25,"tag":145,"props":5862,"children":5863},{},[5864],{"type":31,"value":402},{"type":25,"tag":145,"props":5866,"children":5867},{},[5868],{"type":31,"value":407},{"type":25,"tag":118,"props":5870,"children":5871},{},[5872,5876,5880,5884],{"type":25,"tag":145,"props":5873,"children":5874},{},[5875],{"type":31,"value":415},{"type":25,"tag":145,"props":5877,"children":5878},{},[5879],{"type":31,"value":420},{"type":25,"tag":145,"props":5881,"children":5882},{},[5883],{"type":31,"value":425},{"type":25,"tag":145,"props":5885,"children":5886},{},[5887],{"type":31,"value":430},{"type":25,"tag":118,"props":5889,"children":5890},{},[5891,5895,5899,5903],{"type":25,"tag":145,"props":5892,"children":5893},{},[5894],{"type":31,"value":438},{"type":25,"tag":145,"props":5896,"children":5897},{},[5898],{"type":31,"value":443},{"type":25,"tag":145,"props":5900,"children":5901},{},[5902],{"type":31,"value":448},{"type":25,"tag":145,"props":5904,"children":5905},{},[5906],{"type":31,"value":453},{"type":25,"tag":118,"props":5908,"children":5909},{},[5910,5914,5918,5922],{"type":25,"tag":145,"props":5911,"children":5912},{},[5913],{"type":31,"value":461},{"type":25,"tag":145,"props":5915,"children":5916},{},[5917],{"type":31,"value":466},{"type":25,"tag":145,"props":5919,"children":5920},{},[5921],{"type":31,"value":471},{"type":25,"tag":145,"props":5923,"children":5924},{},[5925],{"type":31,"value":476},{"type":25,"tag":34,"props":5927,"children":5928},{},[5929,5933],{"type":25,"tag":38,"props":5930,"children":5931},{},[5932],{"type":31,"value":484},{"type":31,"value":54},{"type":25,"tag":487,"props":5935,"children":5936},{},[5937,5944],{"type":25,"tag":34,"props":5938,"children":5939},{},[5940],{"type":25,"tag":38,"props":5941,"children":5942},{},[5943],{"type":31,"value":497},{"type":25,"tag":56,"props":5945,"children":5946},{},[5947,5955,5963,5971],{"type":25,"tag":60,"props":5948,"children":5949},{},[5950,5954],{"type":25,"tag":38,"props":5951,"children":5952},{},[5953],{"type":31,"value":251},{"type":31,"value":509},{"type":25,"tag":60,"props":5956,"children":5957},{},[5958,5962],{"type":25,"tag":38,"props":5959,"children":5960},{},[5961],{"type":31,"value":517},{"type":31,"value":519},{"type":25,"tag":60,"props":5964,"children":5965},{},[5966,5970],{"type":25,"tag":38,"props":5967,"children":5968},{},[5969],{"type":31,"value":527},{"type":31,"value":529},{"type":25,"tag":60,"props":5972,"children":5973},{},[5974,5978],{"type":25,"tag":38,"props":5975,"children":5976},{},[5977],{"type":31,"value":537},{"type":31,"value":539},{"type":25,"tag":487,"props":5980,"children":5981},{},[5982,5989],{"type":25,"tag":34,"props":5983,"children":5984},{},[5985],{"type":25,"tag":38,"props":5986,"children":5987},{},[5988],{"type":31,"value":550},{"type":25,"tag":56,"props":5990,"children":5991},{},[5992,6011,6019,6027],{"type":25,"tag":60,"props":5993,"children":5994},{},[5995,5999,6000,6005,6006],{"type":25,"tag":38,"props":5996,"children":5997},{},[5998],{"type":31,"value":251},{"type":31,"value":562},{"type":25,"tag":240,"props":6001,"children":6003},{"className":6002},[],[6004],{"type":31,"value":568},{"type":31,"value":570},{"type":25,"tag":240,"props":6007,"children":6009},{"className":6008},[],[6010],{"type":31,"value":576},{"type":25,"tag":60,"props":6012,"children":6013},{},[6014,6018],{"type":25,"tag":38,"props":6015,"children":6016},{},[6017],{"type":31,"value":584},{"type":31,"value":586},{"type":25,"tag":60,"props":6020,"children":6021},{},[6022,6026],{"type":25,"tag":38,"props":6023,"children":6024},{},[6025],{"type":31,"value":594},{"type":31,"value":596},{"type":25,"tag":60,"props":6028,"children":6029},{},[6030,6034],{"type":25,"tag":38,"props":6031,"children":6032},{},[6033],{"type":31,"value":537},{"type":31,"value":605},{"type":25,"tag":213,"props":6036,"children":6037},{},[],{"type":25,"tag":26,"props":6039,"children":6040},{"id":611},[6041],{"type":31,"value":614},{"type":25,"tag":223,"props":6043,"children":6044},{"id":617},[6045],{"type":31,"value":620},{"type":25,"tag":235,"props":6047,"children":6048},{"code":623},[6049],{"type":25,"tag":240,"props":6050,"children":6051},{"__ignoreMap":7},[6052],{"type":31,"value":623},{"type":25,"tag":34,"props":6054,"children":6055},{},[6056,6060],{"type":25,"tag":38,"props":6057,"children":6058},{},[6059],{"type":31,"value":636},{"type":31,"value":54},{"type":25,"tag":110,"props":6062,"children":6063},{},[6064,6090],{"type":25,"tag":114,"props":6065,"children":6066},{},[6067],{"type":25,"tag":118,"props":6068,"children":6069},{},[6070,6074,6078,6082,6086],{"type":25,"tag":122,"props":6071,"children":6072},{},[6073],{"type":31,"value":651},{"type":25,"tag":122,"props":6075,"children":6076},{},[6077],{"type":31,"value":656},{"type":25,"tag":122,"props":6079,"children":6080},{},[6081],{"type":31,"value":661},{"type":25,"tag":122,"props":6083,"children":6084},{},[6085],{"type":31,"value":666},{"type":25,"tag":122,"props":6087,"children":6088},{},[6089],{"type":31,"value":671},{"type":25,"tag":138,"props":6091,"children":6092},{},[6093,6126,6149,6172],{"type":25,"tag":118,"props":6094,"children":6095},{},[6096,6100,6108,6112,6116],{"type":25,"tag":145,"props":6097,"children":6098},{},[6099],{"type":31,"value":682},{"type":25,"tag":145,"props":6101,"children":6102},{},[6103],{"type":25,"tag":240,"props":6104,"children":6106},{"className":6105},[],[6107],{"type":31,"value":691},{"type":25,"tag":145,"props":6109,"children":6110},{},[6111],{"type":31,"value":696},{"type":25,"tag":145,"props":6113,"children":6114},{},[6115],{"type":31,"value":701},{"type":25,"tag":145,"props":6117,"children":6118},{},[6119,6120,6125],{"type":31,"value":706},{"type":25,"tag":240,"props":6121,"children":6123},{"className":6122},[],[6124],{"type":31,"value":712},{"type":31,"value":714},{"type":25,"tag":118,"props":6127,"children":6128},{},[6129,6133,6137,6141,6145],{"type":25,"tag":145,"props":6130,"children":6131},{},[6132],{"type":31,"value":722},{"type":25,"tag":145,"props":6134,"children":6135},{},[6136],{"type":31,"value":727},{"type":25,"tag":145,"props":6138,"children":6139},{},[6140],{"type":31,"value":732},{"type":25,"tag":145,"props":6142,"children":6143},{},[6144],{"type":31,"value":737},{"type":25,"tag":145,"props":6146,"children":6147},{},[6148],{"type":31,"value":742},{"type":25,"tag":118,"props":6150,"children":6151},{},[6152,6156,6160,6164,6168],{"type":25,"tag":145,"props":6153,"children":6154},{},[6155],{"type":31,"value":750},{"type":25,"tag":145,"props":6157,"children":6158},{},[6159],{"type":31,"value":755},{"type":25,"tag":145,"props":6161,"children":6162},{},[6163],{"type":31,"value":760},{"type":25,"tag":145,"props":6165,"children":6166},{},[6167],{"type":31,"value":765},{"type":25,"tag":145,"props":6169,"children":6170},{},[6171],{"type":31,"value":770},{"type":25,"tag":118,"props":6173,"children":6174},{},[6175,6179,6183,6187,6191],{"type":25,"tag":145,"props":6176,"children":6177},{},[6178],{"type":31,"value":778},{"type":25,"tag":145,"props":6180,"children":6181},{},[6182],{"type":31,"value":783},{"type":25,"tag":145,"props":6184,"children":6185},{},[6186],{"type":31,"value":788},{"type":25,"tag":145,"props":6188,"children":6189},{},[6190],{"type":31,"value":793},{"type":25,"tag":145,"props":6192,"children":6193},{},[6194],{"type":31,"value":798},{"type":25,"tag":223,"props":6196,"children":6197},{"id":801},[6198],{"type":31,"value":804},{"type":25,"tag":806,"props":6200,"children":6201},{"id":808},[6202],{"type":31,"value":808},{"type":25,"tag":110,"props":6204,"children":6205},{},[6206,6236],{"type":25,"tag":114,"props":6207,"children":6208},{},[6209],{"type":25,"tag":118,"props":6210,"children":6211},{},[6212,6216,6220,6224,6228,6232],{"type":25,"tag":122,"props":6213,"children":6214},{},[6215],{"type":31,"value":824},{"type":25,"tag":122,"props":6217,"children":6218},{},[6219],{"type":31,"value":829},{"type":25,"tag":122,"props":6221,"children":6222},{},[6223],{"type":31,"value":834},{"type":25,"tag":122,"props":6225,"children":6226},{},[6227],{"type":31,"value":839},{"type":25,"tag":122,"props":6229,"children":6230},{},[6231],{"type":31,"value":844},{"type":25,"tag":122,"props":6233,"children":6234},{},[6235],{"type":31,"value":849},{"type":25,"tag":138,"props":6237,"children":6238},{},[6239,6269,6299,6329],{"type":25,"tag":118,"props":6240,"children":6241},{},[6242,6249,6253,6257,6261,6265],{"type":25,"tag":145,"props":6243,"children":6244},{},[6245],{"type":25,"tag":38,"props":6246,"children":6247},{},[6248],{"type":31,"value":863},{"type":25,"tag":145,"props":6250,"children":6251},{},[6252],{"type":31,"value":868},{"type":25,"tag":145,"props":6254,"children":6255},{},[6256],{"type":31,"value":873},{"type":25,"tag":145,"props":6258,"children":6259},{},[6260],{"type":31,"value":878},{"type":25,"tag":145,"props":6262,"children":6263},{},[6264],{"type":31,"value":883},{"type":25,"tag":145,"props":6266,"children":6267},{},[6268],{"type":31,"value":888},{"type":25,"tag":118,"props":6270,"children":6271},{},[6272,6279,6283,6287,6291,6295],{"type":25,"tag":145,"props":6273,"children":6274},{},[6275],{"type":25,"tag":38,"props":6276,"children":6277},{},[6278],{"type":31,"value":899},{"type":25,"tag":145,"props":6280,"children":6281},{},[6282],{"type":31,"value":868},{"type":25,"tag":145,"props":6284,"children":6285},{},[6286],{"type":31,"value":908},{"type":25,"tag":145,"props":6288,"children":6289},{},[6290],{"type":31,"value":913},{"type":25,"tag":145,"props":6292,"children":6293},{},[6294],{"type":31,"value":918},{"type":25,"tag":145,"props":6296,"children":6297},{},[6298],{"type":31,"value":923},{"type":25,"tag":118,"props":6300,"children":6301},{},[6302,6309,6313,6317,6321,6325],{"type":25,"tag":145,"props":6303,"children":6304},{},[6305],{"type":25,"tag":38,"props":6306,"children":6307},{},[6308],{"type":31,"value":934},{"type":25,"tag":145,"props":6310,"children":6311},{},[6312],{"type":31,"value":939},{"type":25,"tag":145,"props":6314,"children":6315},{},[6316],{"type":31,"value":944},{"type":25,"tag":145,"props":6318,"children":6319},{},[6320],{"type":31,"value":949},{"type":25,"tag":145,"props":6322,"children":6323},{},[6324],{"type":31,"value":883},{"type":25,"tag":145,"props":6326,"children":6327},{},[6328],{"type":31,"value":958},{"type":25,"tag":118,"props":6330,"children":6331},{},[6332,6339,6343,6347,6351,6355],{"type":25,"tag":145,"props":6333,"children":6334},{},[6335],{"type":25,"tag":38,"props":6336,"children":6337},{},[6338],{"type":31,"value":969},{"type":25,"tag":145,"props":6340,"children":6341},{},[6342],{"type":31,"value":974},{"type":25,"tag":145,"props":6344,"children":6345},{},[6346],{"type":31,"value":979},{"type":25,"tag":145,"props":6348,"children":6349},{},[6350],{"type":31,"value":878},{"type":25,"tag":145,"props":6352,"children":6353},{},[6354],{"type":31,"value":883},{"type":25,"tag":145,"props":6356,"children":6357},{},[6358],{"type":31,"value":992},{"type":25,"tag":34,"props":6360,"children":6361},{},[6362,6366],{"type":25,"tag":38,"props":6363,"children":6364},{},[6365],{"type":31,"value":1000},{"type":31,"value":1002},{"type":25,"tag":806,"props":6368,"children":6369},{"id":1005},[6370],{"type":31,"value":1005},{"type":25,"tag":110,"props":6372,"children":6373},{},[6374,6396],{"type":25,"tag":114,"props":6375,"children":6376},{},[6377],{"type":25,"tag":118,"props":6378,"children":6379},{},[6380,6384,6388,6392],{"type":25,"tag":122,"props":6381,"children":6382},{},[6383],{"type":31,"value":824},{"type":25,"tag":122,"props":6385,"children":6386},{},[6387],{"type":31,"value":1025},{"type":25,"tag":122,"props":6389,"children":6390},{},[6391],{"type":31,"value":1030},{"type":25,"tag":122,"props":6393,"children":6394},{},[6395],{"type":31,"value":1035},{"type":25,"tag":138,"props":6397,"children":6398},{},[6399,6421,6443],{"type":25,"tag":118,"props":6400,"children":6401},{},[6402,6409,6413,6417],{"type":25,"tag":145,"props":6403,"children":6404},{},[6405],{"type":25,"tag":38,"props":6406,"children":6407},{},[6408],{"type":31,"value":1049},{"type":25,"tag":145,"props":6410,"children":6411},{},[6412],{"type":31,"value":1054},{"type":25,"tag":145,"props":6414,"children":6415},{},[6416],{"type":31,"value":1059},{"type":25,"tag":145,"props":6418,"children":6419},{},[6420],{"type":31,"value":1064},{"type":25,"tag":118,"props":6422,"children":6423},{},[6424,6431,6435,6439],{"type":25,"tag":145,"props":6425,"children":6426},{},[6427],{"type":25,"tag":38,"props":6428,"children":6429},{},[6430],{"type":31,"value":1075},{"type":25,"tag":145,"props":6432,"children":6433},{},[6434],{"type":31,"value":1080},{"type":25,"tag":145,"props":6436,"children":6437},{},[6438],{"type":31,"value":1085},{"type":25,"tag":145,"props":6440,"children":6441},{},[6442],{"type":31,"value":1090},{"type":25,"tag":118,"props":6444,"children":6445},{},[6446,6453,6457,6461],{"type":25,"tag":145,"props":6447,"children":6448},{},[6449],{"type":25,"tag":38,"props":6450,"children":6451},{},[6452],{"type":31,"value":1101},{"type":25,"tag":145,"props":6454,"children":6455},{},[6456],{"type":31,"value":1106},{"type":25,"tag":145,"props":6458,"children":6459},{},[6460],{"type":31,"value":1111},{"type":25,"tag":145,"props":6462,"children":6463},{},[6464],{"type":31,"value":1116},{"type":25,"tag":34,"props":6466,"children":6467},{},[6468,6472],{"type":25,"tag":38,"props":6469,"children":6470},{},[6471],{"type":31,"value":1000},{"type":31,"value":1125},{"type":25,"tag":806,"props":6474,"children":6475},{"id":1128},[6476],{"type":31,"value":1128},{"type":25,"tag":110,"props":6478,"children":6479},{},[6480,6502],{"type":25,"tag":114,"props":6481,"children":6482},{},[6483],{"type":25,"tag":118,"props":6484,"children":6485},{},[6486,6490,6494,6498],{"type":25,"tag":122,"props":6487,"children":6488},{},[6489],{"type":31,"value":1144},{"type":25,"tag":122,"props":6491,"children":6492},{},[6493],{"type":31,"value":1149},{"type":25,"tag":122,"props":6495,"children":6496},{},[6497],{"type":31,"value":1154},{"type":25,"tag":122,"props":6499,"children":6500},{},[6501],{"type":31,"value":1159},{"type":25,"tag":138,"props":6503,"children":6504},{},[6505,6527,6549],{"type":25,"tag":118,"props":6506,"children":6507},{},[6508,6515,6519,6523],{"type":25,"tag":145,"props":6509,"children":6510},{},[6511],{"type":25,"tag":38,"props":6512,"children":6513},{},[6514],{"type":31,"value":1173},{"type":25,"tag":145,"props":6516,"children":6517},{},[6518],{"type":31,"value":1178},{"type":25,"tag":145,"props":6520,"children":6521},{},[6522],{"type":31,"value":1064},{"type":25,"tag":145,"props":6524,"children":6525},{},[6526],{"type":31,"value":883},{"type":25,"tag":118,"props":6528,"children":6529},{},[6530,6537,6541,6545],{"type":25,"tag":145,"props":6531,"children":6532},{},[6533],{"type":25,"tag":38,"props":6534,"children":6535},{},[6536],{"type":31,"value":1197},{"type":25,"tag":145,"props":6538,"children":6539},{},[6540],{"type":31,"value":1202},{"type":25,"tag":145,"props":6542,"children":6543},{},[6544],{"type":31,"value":1207},{"type":25,"tag":145,"props":6546,"children":6547},{},[6548],{"type":31,"value":918},{"type":25,"tag":118,"props":6550,"children":6551},{},[6552,6559,6563,6567],{"type":25,"tag":145,"props":6553,"children":6554},{},[6555],{"type":25,"tag":38,"props":6556,"children":6557},{},[6558],{"type":31,"value":1222},{"type":25,"tag":145,"props":6560,"children":6561},{},[6562],{"type":31,"value":1227},{"type":25,"tag":145,"props":6564,"children":6565},{},[6566],{"type":31,"value":1232},{"type":25,"tag":145,"props":6568,"children":6569},{},[6570],{"type":31,"value":1207},{"type":25,"tag":34,"props":6572,"children":6573},{},[6574,6578],{"type":25,"tag":38,"props":6575,"children":6576},{},[6577],{"type":31,"value":1000},{"type":31,"value":1245},{"type":25,"tag":223,"props":6580,"children":6581},{"id":1248},[6582],{"type":31,"value":1251},{"type":25,"tag":235,"props":6584,"children":6586},{"code":1254,"language":1255,"meta":7,"className":6585},[1257],[6587],{"type":25,"tag":240,"props":6588,"children":6589},{"__ignoreMap":7},[6590],{"type":31,"value":1254},{"type":25,"tag":213,"props":6592,"children":6593},{},[],{"type":25,"tag":26,"props":6595,"children":6596},{"id":1268},[6597],{"type":31,"value":1271},{"type":25,"tag":223,"props":6599,"children":6600},{"id":1274},[6601],{"type":31,"value":1277},{"type":25,"tag":806,"props":6603,"children":6604},{"id":1280},[6605],{"type":31,"value":1280},{"type":25,"tag":235,"props":6607,"children":6609},{"code":1285,"language":1286,"meta":7,"className":6608},[1288],[6610],{"type":25,"tag":240,"props":6611,"children":6612},{"__ignoreMap":7},[6613],{"type":31,"value":1285},{"type":25,"tag":806,"props":6615,"children":6616},{"id":1296},[6617],{"type":31,"value":1296},{"type":25,"tag":235,"props":6619,"children":6621},{"code":1301,"language":1286,"meta":7,"className":6620},[1288],[6622],{"type":25,"tag":240,"props":6623,"children":6624},{"__ignoreMap":7},[6625],{"type":31,"value":1301},{"type":25,"tag":34,"props":6627,"children":6628},{},[6629,6633],{"type":25,"tag":38,"props":6630,"children":6631},{},[6632],{"type":31,"value":1315},{"type":31,"value":54},{"type":25,"tag":235,"props":6635,"children":6636},{"code":1319},[6637],{"type":25,"tag":240,"props":6638,"children":6639},{"__ignoreMap":7},[6640],{"type":31,"value":1319},{"type":25,"tag":806,"props":6642,"children":6643},{"id":1327},[6644,6645,6650],{"type":31,"value":1330},{"type":25,"tag":240,"props":6646,"children":6648},{"className":6647},[],[6649],{"type":31,"value":1336},{"type":31,"value":1338},{"type":25,"tag":235,"props":6652,"children":6654},{"code":1341,"language":1255,"meta":7,"className":6653},[1257],[6655],{"type":25,"tag":240,"props":6656,"children":6657},{"__ignoreMap":7},[6658],{"type":31,"value":1341},{"type":25,"tag":223,"props":6660,"children":6661},{"id":1350},[6662],{"type":31,"value":1353},{"type":25,"tag":806,"props":6664,"children":6665},{"id":1356},[6666],{"type":31,"value":1359},{"type":25,"tag":235,"props":6668,"children":6670},{"code":1362,"language":1286,"meta":7,"className":6669},[1288],[6671],{"type":25,"tag":240,"props":6672,"children":6673},{"__ignoreMap":7},[6674],{"type":31,"value":1362},{"type":25,"tag":806,"props":6676,"children":6677},{"id":1371},[6678,6679],{"type":31,"value":1374},{"type":25,"tag":240,"props":6680,"children":6682},{"className":6681},[],[6683],{"type":31,"value":1380},{"type":25,"tag":235,"props":6685,"children":6687},{"code":1383,"language":1255,"meta":7,"className":6686},[1257],[6688],{"type":25,"tag":240,"props":6689,"children":6690},{"__ignoreMap":7},[6691],{"type":31,"value":1383},{"type":25,"tag":806,"props":6693,"children":6694},{"id":1392},[6695],{"type":31,"value":1395},{"type":25,"tag":235,"props":6697,"children":6699},{"code":1398,"language":1286,"meta":7,"className":6698},[1288],[6700],{"type":25,"tag":240,"props":6701,"children":6702},{"__ignoreMap":7},[6703],{"type":31,"value":1398},{"type":25,"tag":34,"props":6705,"children":6706},{},[6707,6711],{"type":25,"tag":38,"props":6708,"children":6709},{},[6710],{"type":31,"value":1412},{"type":31,"value":54},{"type":25,"tag":235,"props":6713,"children":6715},{"code":1416,"language":1286,"meta":7,"className":6714},[1288],[6716],{"type":25,"tag":240,"props":6717,"children":6718},{"__ignoreMap":7},[6719],{"type":31,"value":1416},{"type":25,"tag":223,"props":6721,"children":6722},{"id":1425},[6723],{"type":31,"value":1428},{"type":25,"tag":806,"props":6725,"children":6726},{"id":1431},[6727],{"type":31,"value":1434},{"type":25,"tag":34,"props":6729,"children":6730},{},[6731,6735],{"type":25,"tag":38,"props":6732,"children":6733},{},[6734],{"type":31,"value":251},{"type":31,"value":1443},{"type":25,"tag":235,"props":6737,"children":6739},{"code":1446,"language":1447,"meta":7,"className":6738},[1449],[6740],{"type":25,"tag":240,"props":6741,"children":6742},{"__ignoreMap":7},[6743],{"type":31,"value":1446},{"type":25,"tag":806,"props":6745,"children":6746},{"id":1457},[6747],{"type":31,"value":1460},{"type":25,"tag":34,"props":6749,"children":6750},{},[6751,6755],{"type":25,"tag":38,"props":6752,"children":6753},{},[6754],{"type":31,"value":251},{"type":31,"value":1469},{"type":25,"tag":235,"props":6757,"children":6759},{"code":1472,"language":1473,"meta":7,"className":6758},[1475],[6760],{"type":25,"tag":240,"props":6761,"children":6762},{"__ignoreMap":7},[6763],{"type":31,"value":1472},{"type":25,"tag":235,"props":6765,"children":6767},{"code":1483,"language":1484,"meta":7,"className":6766},[1486],[6768],{"type":25,"tag":240,"props":6769,"children":6770},{"__ignoreMap":7},[6771],{"type":31,"value":1483},{"type":25,"tag":235,"props":6773,"children":6774},{"code":1494},[6775],{"type":25,"tag":240,"props":6776,"children":6777},{"__ignoreMap":7},[6778],{"type":31,"value":1494},{"type":25,"tag":223,"props":6780,"children":6781},{"id":1502},[6782],{"type":31,"value":1505},{"type":25,"tag":34,"props":6784,"children":6785},{},[6786],{"type":31,"value":1510},{"type":25,"tag":235,"props":6788,"children":6790},{"code":1513,"language":1286,"meta":7,"className":6789},[1288],[6791],{"type":25,"tag":240,"props":6792,"children":6793},{"__ignoreMap":7},[6794],{"type":31,"value":1513},{"type":25,"tag":213,"props":6796,"children":6797},{},[],{"type":25,"tag":26,"props":6799,"children":6800},{"id":1525},[6801],{"type":31,"value":1528},{"type":25,"tag":223,"props":6803,"children":6804},{"id":1531},[6805],{"type":31,"value":1534},{"type":25,"tag":806,"props":6807,"children":6808},{"id":1537},[6809,6810,6815],{"type":31,"value":1540},{"type":25,"tag":240,"props":6811,"children":6813},{"className":6812},[],[6814],{"type":31,"value":1546},{"type":31,"value":1338},{"type":25,"tag":235,"props":6817,"children":6819},{"code":1550,"language":1551,"meta":7,"className":6818},[1553],[6820],{"type":25,"tag":240,"props":6821,"children":6822},{"__ignoreMap":7},[6823],{"type":31,"value":1550},{"type":25,"tag":223,"props":6825,"children":6826},{"id":1561},[6827],{"type":31,"value":1564},{"type":25,"tag":806,"props":6829,"children":6830},{"id":1567},[6831,6832,6837],{"type":31,"value":1570},{"type":25,"tag":240,"props":6833,"children":6835},{"className":6834},[],[6836],{"type":31,"value":1576},{"type":31,"value":1338},{"type":25,"tag":235,"props":6839,"children":6841},{"code":1580,"language":1581,"meta":7,"className":6840},[1583],[6842],{"type":25,"tag":240,"props":6843,"children":6844},{"__ignoreMap":7},[6845],{"type":31,"value":1580},{"type":25,"tag":223,"props":6847,"children":6848},{"id":1591},[6849],{"type":31,"value":1594},{"type":25,"tag":235,"props":6851,"children":6853},{"code":1597,"language":1286,"meta":7,"className":6852},[1288],[6854],{"type":25,"tag":240,"props":6855,"children":6856},{"__ignoreMap":7},[6857],{"type":31,"value":1597},{"type":25,"tag":34,"props":6859,"children":6860},{},[6861,6865],{"type":25,"tag":38,"props":6862,"children":6863},{},[6864],{"type":31,"value":1315},{"type":31,"value":54},{"type":25,"tag":235,"props":6867,"children":6869},{"code":1614,"language":1551,"meta":7,"className":6868},[1553],[6870],{"type":25,"tag":240,"props":6871,"children":6872},{"__ignoreMap":7},[6873],{"type":31,"value":1614},{"type":25,"tag":223,"props":6875,"children":6876},{"id":1623},[6877],{"type":31,"value":1626},{"type":25,"tag":806,"props":6879,"children":6880},{"id":1629},[6881],{"type":31,"value":1629},{"type":25,"tag":235,"props":6883,"children":6885},{"code":1634,"language":1286,"meta":7,"className":6884},[1288],[6886],{"type":25,"tag":240,"props":6887,"children":6888},{"__ignoreMap":7},[6889],{"type":31,"value":1634},{"type":25,"tag":806,"props":6891,"children":6892},{"id":1643},[6893],{"type":31,"value":1643},{"type":25,"tag":235,"props":6895,"children":6897},{"code":1648,"language":1286,"meta":7,"className":6896},[1288],[6898],{"type":25,"tag":240,"props":6899,"children":6900},{"__ignoreMap":7},[6901],{"type":31,"value":1648},{"type":25,"tag":213,"props":6903,"children":6904},{},[],{"type":25,"tag":26,"props":6906,"children":6907},{"id":1660},[6908],{"type":31,"value":1663},{"type":25,"tag":223,"props":6910,"children":6911},{"id":1666},[6912],{"type":31,"value":1669},{"type":25,"tag":806,"props":6914,"children":6915},{"id":1672},[6916,6917,6922],{"type":31,"value":1675},{"type":25,"tag":240,"props":6918,"children":6920},{"className":6919},[],[6921],{"type":31,"value":1681},{"type":31,"value":1338},{"type":25,"tag":235,"props":6924,"children":6926},{"code":1685,"language":1551,"meta":7,"className":6925},[1553],[6927],{"type":25,"tag":240,"props":6928,"children":6929},{"__ignoreMap":7},[6930],{"type":31,"value":1685},{"type":25,"tag":223,"props":6932,"children":6933},{"id":1694},[6934],{"type":31,"value":1697},{"type":25,"tag":806,"props":6936,"children":6937},{"id":1700},[6938,6939,6944],{"type":31,"value":1703},{"type":25,"tag":240,"props":6940,"children":6942},{"className":6941},[],[6943],{"type":31,"value":1709},{"type":31,"value":1338},{"type":25,"tag":235,"props":6946,"children":6948},{"code":1713,"language":1714,"meta":7,"className":6947},[1716],[6949],{"type":25,"tag":240,"props":6950,"children":6951},{"__ignoreMap":7},[6952],{"type":31,"value":1713},{"type":25,"tag":806,"props":6954,"children":6955},{"id":1724},[6956],{"type":31,"value":1724},{"type":25,"tag":235,"props":6958,"children":6960},{"code":1729,"language":1286,"meta":7,"className":6959},[1288],[6961],{"type":25,"tag":240,"props":6962,"children":6963},{"__ignoreMap":7},[6964],{"type":31,"value":1729},{"type":25,"tag":223,"props":6966,"children":6967},{"id":1738},[6968],{"type":31,"value":1741},{"type":25,"tag":34,"props":6970,"children":6971},{},[6972],{"type":31,"value":1746},{"type":25,"tag":235,"props":6974,"children":6976},{"code":1749,"language":1447,"meta":7,"className":6975},[1449],[6977],{"type":25,"tag":240,"props":6978,"children":6979},{"__ignoreMap":7},[6980],{"type":31,"value":1749},{"type":25,"tag":213,"props":6982,"children":6983},{},[],{"type":25,"tag":26,"props":6985,"children":6986},{"id":1761},[6987],{"type":31,"value":1764},{"type":25,"tag":223,"props":6989,"children":6990},{"id":1767},[6991],{"type":31,"value":1770},{"type":25,"tag":110,"props":6993,"children":6994},{},[6995,7013],{"type":25,"tag":114,"props":6996,"children":6997},{},[6998],{"type":25,"tag":118,"props":6999,"children":7000},{},[7001,7005,7009],{"type":25,"tag":122,"props":7002,"children":7003},{},[7004],{"type":31,"value":1784},{"type":25,"tag":122,"props":7006,"children":7007},{},[7008],{"type":31,"value":1789},{"type":25,"tag":122,"props":7010,"children":7011},{},[7012],{"type":31,"value":1794},{"type":25,"tag":138,"props":7014,"children":7015},{},[7016,7034,7052,7075,7093],{"type":25,"tag":118,"props":7017,"children":7018},{},[7019,7026,7030],{"type":25,"tag":145,"props":7020,"children":7021},{},[7022],{"type":25,"tag":38,"props":7023,"children":7024},{},[7025],{"type":31,"value":1808},{"type":25,"tag":145,"props":7027,"children":7028},{},[7029],{"type":31,"value":1813},{"type":25,"tag":145,"props":7031,"children":7032},{},[7033],{"type":31,"value":1818},{"type":25,"tag":118,"props":7035,"children":7036},{},[7037,7044,7048],{"type":25,"tag":145,"props":7038,"children":7039},{},[7040],{"type":25,"tag":38,"props":7041,"children":7042},{},[7043],{"type":31,"value":1829},{"type":25,"tag":145,"props":7045,"children":7046},{},[7047],{"type":31,"value":1834},{"type":25,"tag":145,"props":7049,"children":7050},{},[7051],{"type":31,"value":1839},{"type":25,"tag":118,"props":7053,"children":7054},{},[7055,7062,7071],{"type":25,"tag":145,"props":7056,"children":7057},{},[7058],{"type":25,"tag":38,"props":7059,"children":7060},{},[7061],{"type":31,"value":1850},{"type":25,"tag":145,"props":7063,"children":7064},{},[7065,7070],{"type":25,"tag":240,"props":7066,"children":7068},{"className":7067},[],[7069],{"type":31,"value":1859},{"type":31,"value":1861},{"type":25,"tag":145,"props":7072,"children":7073},{},[7074],{"type":31,"value":1866},{"type":25,"tag":118,"props":7076,"children":7077},{},[7078,7085,7089],{"type":25,"tag":145,"props":7079,"children":7080},{},[7081],{"type":25,"tag":38,"props":7082,"children":7083},{},[7084],{"type":31,"value":1877},{"type":25,"tag":145,"props":7086,"children":7087},{},[7088],{"type":31,"value":1882},{"type":25,"tag":145,"props":7090,"children":7091},{},[7092],{"type":31,"value":1887},{"type":25,"tag":118,"props":7094,"children":7095},{},[7096,7103,7107],{"type":25,"tag":145,"props":7097,"children":7098},{},[7099],{"type":25,"tag":38,"props":7100,"children":7101},{},[7102],{"type":31,"value":1898},{"type":25,"tag":145,"props":7104,"children":7105},{},[7106],{"type":31,"value":1903},{"type":25,"tag":145,"props":7108,"children":7109},{},[7110],{"type":31,"value":1908},{"type":25,"tag":223,"props":7112,"children":7113},{"id":1911},[7114],{"type":31,"value":1914},{"type":25,"tag":806,"props":7116,"children":7117},{"id":1917},[7118],{"type":31,"value":1920},{"type":25,"tag":235,"props":7120,"children":7122},{"code":1923,"language":1255,"meta":7,"className":7121},[1257],[7123],{"type":25,"tag":240,"props":7124,"children":7125},{"__ignoreMap":7},[7126],{"type":31,"value":1923},{"type":25,"tag":806,"props":7128,"children":7129},{"id":1932},[7130],{"type":31,"value":1935},{"type":25,"tag":235,"props":7132,"children":7134},{"code":1938,"language":1581,"meta":7,"className":7133},[1583],[7135],{"type":25,"tag":240,"props":7136,"children":7137},{"__ignoreMap":7},[7138],{"type":31,"value":1938},{"type":25,"tag":223,"props":7140,"children":7141},{"id":1947},[7142],{"type":31,"value":1950},{"type":25,"tag":34,"props":7144,"children":7145},{},[7146],{"type":31,"value":1955},{"type":25,"tag":235,"props":7148,"children":7150},{"code":1958,"language":1959,"meta":7,"className":7149},[1961],[7151],{"type":25,"tag":240,"props":7152,"children":7153},{"__ignoreMap":7},[7154],{"type":31,"value":1958},{"type":25,"tag":34,"props":7156,"children":7157},{},[7158,7162],{"type":25,"tag":38,"props":7159,"children":7160},{},[7161],{"type":31,"value":1974},{"type":31,"value":54},{"type":25,"tag":235,"props":7164,"children":7166},{"code":1978,"language":1473,"meta":7,"className":7165},[1475],[7167],{"type":25,"tag":240,"props":7168,"children":7169},{"__ignoreMap":7},[7170],{"type":31,"value":1978},{"type":25,"tag":213,"props":7172,"children":7173},{},[],{"type":25,"tag":26,"props":7175,"children":7176},{"id":1990},[7177],{"type":31,"value":1993},{"type":25,"tag":223,"props":7179,"children":7180},{"id":1996},[7181],{"type":31,"value":1999},{"type":25,"tag":235,"props":7183,"children":7185},{"code":2002,"language":1255,"meta":7,"className":7184},[1257],[7186],{"type":25,"tag":240,"props":7187,"children":7188},{"__ignoreMap":7},[7189],{"type":31,"value":2002},{"type":25,"tag":223,"props":7191,"children":7192},{"id":2011},[7193],{"type":31,"value":2014},{"type":25,"tag":34,"props":7195,"children":7196},{},[7197],{"type":31,"value":2019},{"type":25,"tag":235,"props":7199,"children":7200},{"code":2022},[7201],{"type":25,"tag":240,"props":7202,"children":7203},{"__ignoreMap":7},[7204],{"type":31,"value":2022},{"type":25,"tag":223,"props":7206,"children":7207},{"id":2030},[7208],{"type":31,"value":2033},{"type":25,"tag":235,"props":7210,"children":7212},{"code":2036,"language":1255,"meta":7,"className":7211},[1257],[7213],{"type":25,"tag":240,"props":7214,"children":7215},{"__ignoreMap":7},[7216],{"type":31,"value":2036},{"type":25,"tag":213,"props":7218,"children":7219},{},[],{"type":25,"tag":26,"props":7221,"children":7222},{"id":2048},[7223],{"type":31,"value":2051},{"type":25,"tag":223,"props":7225,"children":7226},{"id":2054},[7227],{"type":31,"value":2057},{"type":25,"tag":56,"props":7229,"children":7231},{"className":7230},[2061],[7232,7245,7269,7282,7295,7308],{"type":25,"tag":60,"props":7233,"children":7235},{"className":7234},[2066],[7236,7239,7240,7244],{"type":25,"tag":2069,"props":7237,"children":7238},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":7241,"children":7242},{},[7243],{"type":31,"value":2080},{"type":31,"value":2082},{"type":25,"tag":60,"props":7246,"children":7248},{"className":7247},[2066],[7249,7252,7253,7257,7258,7263,7264],{"type":25,"tag":2069,"props":7250,"children":7251},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":7254,"children":7255},{},[7256],{"type":31,"value":2095},{"type":31,"value":2097},{"type":25,"tag":240,"props":7259,"children":7261},{"className":7260},[],[7262],{"type":31,"value":2103},{"type":31,"value":2105},{"type":25,"tag":240,"props":7265,"children":7267},{"className":7266},[],[7268],{"type":31,"value":2111},{"type":25,"tag":60,"props":7270,"children":7272},{"className":7271},[2066],[7273,7276,7277,7281],{"type":25,"tag":2069,"props":7274,"children":7275},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":7278,"children":7279},{},[7280],{"type":31,"value":2124},{"type":31,"value":2126},{"type":25,"tag":60,"props":7283,"children":7285},{"className":7284},[2066],[7286,7289,7290,7294],{"type":25,"tag":2069,"props":7287,"children":7288},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":7291,"children":7292},{},[7293],{"type":31,"value":2139},{"type":31,"value":2141},{"type":25,"tag":60,"props":7296,"children":7298},{"className":7297},[2066],[7299,7302,7303,7307],{"type":25,"tag":2069,"props":7300,"children":7301},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":7304,"children":7305},{},[7306],{"type":31,"value":2154},{"type":31,"value":2156},{"type":25,"tag":60,"props":7309,"children":7311},{"className":7310},[2066],[7312,7315,7316,7320],{"type":25,"tag":2069,"props":7313,"children":7314},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":7317,"children":7318},{},[7319],{"type":31,"value":2169},{"type":31,"value":2171},{"type":25,"tag":223,"props":7322,"children":7323},{"id":2174},[7324],{"type":31,"value":2177},{"type":25,"tag":56,"props":7326,"children":7328},{"className":7327},[2061],[7329,7342,7355,7368,7381,7394],{"type":25,"tag":60,"props":7330,"children":7332},{"className":7331},[2066],[7333,7336,7337,7341],{"type":25,"tag":2069,"props":7334,"children":7335},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":7338,"children":7339},{},[7340],{"type":31,"value":2194},{"type":31,"value":2196},{"type":25,"tag":60,"props":7343,"children":7345},{"className":7344},[2066],[7346,7349,7350,7354],{"type":25,"tag":2069,"props":7347,"children":7348},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":7351,"children":7352},{},[7353],{"type":31,"value":2209},{"type":31,"value":2211},{"type":25,"tag":60,"props":7356,"children":7358},{"className":7357},[2066],[7359,7362,7363,7367],{"type":25,"tag":2069,"props":7360,"children":7361},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":7364,"children":7365},{},[7366],{"type":31,"value":2224},{"type":31,"value":2226},{"type":25,"tag":60,"props":7369,"children":7371},{"className":7370},[2066],[7372,7375,7376,7380],{"type":25,"tag":2069,"props":7373,"children":7374},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":7377,"children":7378},{},[7379],{"type":31,"value":2239},{"type":31,"value":2241},{"type":25,"tag":60,"props":7382,"children":7384},{"className":7383},[2066],[7385,7388,7389,7393],{"type":25,"tag":2069,"props":7386,"children":7387},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":7390,"children":7391},{},[7392],{"type":31,"value":2254},{"type":31,"value":2256},{"type":25,"tag":60,"props":7395,"children":7397},{"className":7396},[2066],[7398,7401,7402,7406],{"type":25,"tag":2069,"props":7399,"children":7400},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":7403,"children":7404},{},[7405],{"type":31,"value":2269},{"type":31,"value":2271},{"type":25,"tag":223,"props":7408,"children":7409},{"id":2274},[7410],{"type":31,"value":2277},{"type":25,"tag":56,"props":7412,"children":7414},{"className":7413},[2061],[7415,7428,7441,7454,7467],{"type":25,"tag":60,"props":7416,"children":7418},{"className":7417},[2066],[7419,7422,7423,7427],{"type":25,"tag":2069,"props":7420,"children":7421},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":7424,"children":7425},{},[7426],{"type":31,"value":2294},{"type":31,"value":2296},{"type":25,"tag":60,"props":7429,"children":7431},{"className":7430},[2066],[7432,7435,7436,7440],{"type":25,"tag":2069,"props":7433,"children":7434},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":7437,"children":7438},{},[7439],{"type":31,"value":2309},{"type":31,"value":2311},{"type":25,"tag":60,"props":7442,"children":7444},{"className":7443},[2066],[7445,7448,7449,7453],{"type":25,"tag":2069,"props":7446,"children":7447},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":7450,"children":7451},{},[7452],{"type":31,"value":2324},{"type":31,"value":2326},{"type":25,"tag":60,"props":7455,"children":7457},{"className":7456},[2066],[7458,7461,7462,7466],{"type":25,"tag":2069,"props":7459,"children":7460},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":7463,"children":7464},{},[7465],{"type":31,"value":2339},{"type":31,"value":2341},{"type":25,"tag":60,"props":7468,"children":7470},{"className":7469},[2066],[7471,7474,7475,7479],{"type":25,"tag":2069,"props":7472,"children":7473},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":7476,"children":7477},{},[7478],{"type":31,"value":2354},{"type":31,"value":2356},{"type":25,"tag":223,"props":7481,"children":7482},{"id":2359},[7483],{"type":31,"value":2362},{"type":25,"tag":56,"props":7485,"children":7487},{"className":7486},[2061],[7488,7501,7514,7527,7540],{"type":25,"tag":60,"props":7489,"children":7491},{"className":7490},[2066],[7492,7495,7496,7500],{"type":25,"tag":2069,"props":7493,"children":7494},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":7497,"children":7498},{},[7499],{"type":31,"value":2379},{"type":31,"value":2381},{"type":25,"tag":60,"props":7502,"children":7504},{"className":7503},[2066],[7505,7508,7509,7513],{"type":25,"tag":2069,"props":7506,"children":7507},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":7510,"children":7511},{},[7512],{"type":31,"value":2394},{"type":31,"value":2396},{"type":25,"tag":60,"props":7515,"children":7517},{"className":7516},[2066],[7518,7521,7522,7526],{"type":25,"tag":2069,"props":7519,"children":7520},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":7523,"children":7524},{},[7525],{"type":31,"value":2409},{"type":31,"value":2411},{"type":25,"tag":60,"props":7528,"children":7530},{"className":7529},[2066],[7531,7534,7535,7539],{"type":25,"tag":2069,"props":7532,"children":7533},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":7536,"children":7537},{},[7538],{"type":31,"value":2424},{"type":31,"value":2426},{"type":25,"tag":60,"props":7541,"children":7543},{"className":7542},[2066],[7544,7547,7548,7552],{"type":25,"tag":2069,"props":7545,"children":7546},{"disabled":2071,"type":2072},[],{"type":31,"value":2075},{"type":25,"tag":38,"props":7549,"children":7550},{},[7551],{"type":31,"value":2439},{"type":31,"value":2441},{"type":25,"tag":213,"props":7554,"children":7555},{},[],{"type":25,"tag":26,"props":7557,"children":7558},{"id":2447},[7559],{"type":31,"value":2450},{"type":25,"tag":223,"props":7561,"children":7562},{"id":2453},[7563],{"type":31,"value":2456},{"type":25,"tag":56,"props":7565,"children":7566},{},[7567,7580,7593,7606],{"type":25,"tag":60,"props":7568,"children":7569},{},[7570,7574,7575],{"type":25,"tag":38,"props":7571,"children":7572},{},[7573],{"type":31,"value":863},{"type":31,"value":2468},{"type":25,"tag":2470,"props":7576,"children":7578},{"href":2472,"rel":7577},[2474],[7579],{"type":31,"value":2472},{"type":25,"tag":60,"props":7581,"children":7582},{},[7583,7587,7588],{"type":25,"tag":38,"props":7584,"children":7585},{},[7586],{"type":31,"value":1049},{"type":31,"value":2468},{"type":25,"tag":2470,"props":7589,"children":7591},{"href":2487,"rel":7590},[2474],[7592],{"type":31,"value":2487},{"type":25,"tag":60,"props":7594,"children":7595},{},[7596,7600,7601],{"type":25,"tag":38,"props":7597,"children":7598},{},[7599],{"type":31,"value":2498},{"type":31,"value":2468},{"type":25,"tag":2470,"props":7602,"children":7604},{"href":2502,"rel":7603},[2474],[7605],{"type":31,"value":2502},{"type":25,"tag":60,"props":7607,"children":7608},{},[7609,7613,7614],{"type":25,"tag":38,"props":7610,"children":7611},{},[7612],{"type":31,"value":2513},{"type":31,"value":2468},{"type":25,"tag":2470,"props":7615,"children":7617},{"href":2517,"rel":7616},[2474],[7618],{"type":31,"value":2517},{"type":25,"tag":223,"props":7620,"children":7621},{"id":2523},[7622],{"type":31,"value":2526},{"type":25,"tag":56,"props":7624,"children":7625},{},[7626,7639,7652,7666],{"type":25,"tag":60,"props":7627,"children":7628},{},[7629,7633,7634],{"type":25,"tag":38,"props":7630,"children":7631},{},[7632],{"type":31,"value":899},{"type":31,"value":2468},{"type":25,"tag":2470,"props":7635,"children":7637},{"href":2540,"rel":7636},[2474],[7638],{"type":31,"value":2540},{"type":25,"tag":60,"props":7640,"children":7641},{},[7642,7646,7647],{"type":25,"tag":38,"props":7643,"children":7644},{},[7645],{"type":31,"value":934},{"type":31,"value":2468},{"type":25,"tag":2470,"props":7648,"children":7650},{"href":2554,"rel":7649},[2474],[7651],{"type":31,"value":2554},{"type":25,"tag":60,"props":7653,"children":7654},{},[7655,7659,7660,7665],{"type":25,"tag":38,"props":7656,"children":7657},{},[7658],{"type":31,"value":2565},{"type":31,"value":2468},{"type":25,"tag":2470,"props":7661,"children":7663},{"href":2569,"rel":7662},[2474],[7664],{"type":31,"value":2569},{"type":31,"value":2574},{"type":25,"tag":60,"props":7667,"children":7668},{},[7669,7673,7674,7679],{"type":25,"tag":38,"props":7670,"children":7671},{},[7672],{"type":31,"value":2582},{"type":31,"value":2468},{"type":25,"tag":2470,"props":7675,"children":7677},{"href":2586,"rel":7676},[2474],[7678],{"type":31,"value":2586},{"type":31,"value":2591},{"type":25,"tag":223,"props":7681,"children":7682},{"id":2594},[7683],{"type":31,"value":2597},{"type":25,"tag":56,"props":7685,"children":7686},{},[7687,7694,7701,7708],{"type":25,"tag":60,"props":7688,"children":7689},{},[7690],{"type":25,"tag":2470,"props":7691,"children":7692},{"href":2606},[7693],{"type":31,"value":2609},{"type":25,"tag":60,"props":7695,"children":7696},{},[7697],{"type":25,"tag":2470,"props":7698,"children":7699},{"href":2615},[7700],{"type":31,"value":2618},{"type":25,"tag":60,"props":7702,"children":7703},{},[7704],{"type":25,"tag":2470,"props":7705,"children":7706},{"href":2624},[7707],{"type":31,"value":2627},{"type":25,"tag":60,"props":7709,"children":7710},{},[7711],{"type":25,"tag":2470,"props":7712,"children":7713},{"href":2633},[7714],{"type":31,"value":2636},{"type":25,"tag":213,"props":7716,"children":7717},{},[],{"type":25,"tag":26,"props":7719,"children":7720},{"id":2642},[7721],{"type":31,"value":2645},{"type":25,"tag":34,"props":7723,"children":7724},{},[7725],{"type":31,"value":2650},{"type":25,"tag":34,"props":7727,"children":7728},{},[7729,7733],{"type":25,"tag":38,"props":7730,"children":7731},{},[7732],{"type":31,"value":2658},{"type":31,"value":54},{"type":25,"tag":2661,"props":7735,"children":7736},{},[7737,7745,7753,7761],{"type":25,"tag":60,"props":7738,"children":7739},{},[7740,7744],{"type":25,"tag":38,"props":7741,"children":7742},{},[7743],{"type":31,"value":2671},{"type":31,"value":2673},{"type":25,"tag":60,"props":7746,"children":7747},{},[7748,7752],{"type":25,"tag":38,"props":7749,"children":7750},{},[7751],{"type":31,"value":2681},{"type":31,"value":2683},{"type":25,"tag":60,"props":7754,"children":7755},{},[7756,7760],{"type":25,"tag":38,"props":7757,"children":7758},{},[7759],{"type":31,"value":2691},{"type":31,"value":2693},{"type":25,"tag":60,"props":7762,"children":7763},{},[7764,7768],{"type":25,"tag":38,"props":7765,"children":7766},{},[7767],{"type":31,"value":339},{"type":31,"value":2702},{"type":25,"tag":34,"props":7770,"children":7771},{},[7772],{"type":31,"value":2707},{"title":7,"searchDepth":2709,"depth":2709,"links":7774},[7775,7776,7781,7790,7807,7820,7830,7838,7843,7849,7854],{"id":28,"depth":2712,"text":32},{"id":218,"depth":2712,"text":221,"children":7777},[7778,7779,7780],{"id":225,"depth":2709,"text":228},{"id":288,"depth":2709,"text":291},{"id":344,"depth":2709,"text":347},{"id":611,"depth":2712,"text":614,"children":7782},[7783,7784,7789],{"id":617,"depth":2709,"text":620},{"id":801,"depth":2709,"text":804,"children":7785},[7786,7787,7788],{"id":808,"depth":2724,"text":808},{"id":1005,"depth":2724,"text":1005},{"id":1128,"depth":2724,"text":1128},{"id":1248,"depth":2709,"text":1251},{"id":1268,"depth":2712,"text":1271,"children":7791},[7792,7797,7802,7806],{"id":1274,"depth":2709,"text":1277,"children":7793},[7794,7795,7796],{"id":1280,"depth":2724,"text":1280},{"id":1296,"depth":2724,"text":1296},{"id":1327,"depth":2724,"text":2735},{"id":1350,"depth":2709,"text":1353,"children":7798},[7799,7800,7801],{"id":1356,"depth":2724,"text":1359},{"id":1371,"depth":2724,"text":2740},{"id":1392,"depth":2724,"text":1395},{"id":1425,"depth":2709,"text":1428,"children":7803},[7804,7805],{"id":1431,"depth":2724,"text":1434},{"id":1457,"depth":2724,"text":1460},{"id":1502,"depth":2709,"text":1505},{"id":1525,"depth":2712,"text":1528,"children":7808},[7809,7812,7815,7816],{"id":1531,"depth":2709,"text":1534,"children":7810},[7811],{"id":1537,"depth":2724,"text":2752},{"id":1561,"depth":2709,"text":1564,"children":7813},[7814],{"id":1567,"depth":2724,"text":2756},{"id":1591,"depth":2709,"text":1594},{"id":1623,"depth":2709,"text":1626,"children":7817},[7818,7819],{"id":1629,"depth":2724,"text":1629},{"id":1643,"depth":2724,"text":1643},{"id":1660,"depth":2712,"text":1663,"children":7821},[7822,7825,7829],{"id":1666,"depth":2709,"text":1669,"children":7823},[7824],{"id":1672,"depth":2724,"text":2767},{"id":1694,"depth":2709,"text":1697,"children":7826},[7827,7828],{"id":1700,"depth":2724,"text":2771},{"id":1724,"depth":2724,"text":1724},{"id":1738,"depth":2709,"text":1741},{"id":1761,"depth":2712,"text":1764,"children":7831},[7832,7833,7837],{"id":1767,"depth":2709,"text":1770},{"id":1911,"depth":2709,"text":1914,"children":7834},[7835,7836],{"id":1917,"depth":2724,"text":1920},{"id":1932,"depth":2724,"text":1935},{"id":1947,"depth":2709,"text":1950},{"id":1990,"depth":2712,"text":1993,"children":7839},[7840,7841,7842],{"id":1996,"depth":2709,"text":1999},{"id":2011,"depth":2709,"text":2014},{"id":2030,"depth":2709,"text":2033},{"id":2048,"depth":2712,"text":2051,"children":7844},[7845,7846,7847,7848],{"id":2054,"depth":2709,"text":2057},{"id":2174,"depth":2709,"text":2177},{"id":2274,"depth":2709,"text":2277},{"id":2359,"depth":2709,"text":2362},{"id":2447,"depth":2712,"text":2450,"children":7850},[7851,7852,7853],{"id":2453,"depth":2709,"text":2456},{"id":2523,"depth":2709,"text":2526},{"id":2594,"depth":2709,"text":2597},{"id":2642,"depth":2712,"text":2645},1782088242404]