FEATURED · 精选文章

Impeccable Live Variant Mode 全解析:在真实浏览器中让 AI Agent 逐元素生成并热替换 HTML+CSS 设计变体

发布时间 / 2026/9/9 15:14:09
来源 / 创域科博编辑部
栏目 / 资讯中心
Impeccable Live Variant Mode 全解析:在真实浏览器中让 AI Agent 逐元素生成并热替换 HTML+CSS 设计变体 Impeccable Live Variant Mode 全解析在真实浏览器中让 AI Agent 逐元素生成并热替换 HTMLCSS 设计变体【免费下载链接】impeccableThe design language that makes your AI harness better at design.项目地址: https://gitcode.com/GitHub_Trending/im/impeccableImpeccable 是一套教 AI 编码 Agent 做前端设计的技能skill而 Live Variant Mode实时变体模式是它面向「迭代已有界面」场景的核心能力用户在真实浏览器中选中一个元素选择一个设计动作bolder、quieter、polish、typeset……Agent 便基于该元素当前的真实 HTML/CSS 生成 3 个完整的设计变体经开发服务器的 HMR 或源码直读能力热替换到页面中用户循环预览后接受或丢弃。本文以.vibe/skills/impeccable/reference/live.md为骨架结合仓库内架构决策、浏览器运行时与端到端测试完整还原这套协议从引导、轮询主循环、事件分发到身份识别、三变体规划、参数旋钮、carbonize 收尾与故障恢复读完即可照此驱动任意支持 shell 的 AI harness 跑起一个 live 会话。一、Live 模式解决什么问题从「改代码—刷新—猜效果」到「看效果再决定」传统上让 Agent 设计一个页面用户需要提出要求 → 等待改码 → 读 diff → 手动刷新 → 判断喜不喜欢 → 不满意再循环。慢且割裂。Live 模式的目标在 架构决策文档 中写得非常明确让用户直接在浏览器中选中元素、挑选设计动作看到 N 个真实的 HTMLCSS 变体被热替换进来视觉上循环切换、接受或丢弃、再继续。Agent 负责「在源码里生成变体」浏览器负责「把它们显示出来」。其三条核心架构决策对应 docs/adr-live-variant-mode.md值得先理解因为它们解释了文档里几乎每一条规则改源码而不是打补丁 DOM。变体被真实写入源文件再借框架自身的 HMR 管道上屏。于是「Accept」只需把胜出变体留下、删除其余即可变体本身就是可被用户在编辑器里检查、diff 与提交的真实代码React/Vue 等框架状态也因由框架渲染管线更新而完整保留。通信用 SSE fetch而非 WebSocket。服务端用零依赖纯 Nodehttp、crypto、fs、net、os实现去掉ws依赖保证脚本随技能一起投递即可在任意项目里运行、无需任何包安装。Agent 侧用 HTTP 长轮询GET /poll阻塞至有浏览器事件不用 WebSocket 也不用 stdin。因为任何 harness 都能执行一条 shell 命令并读取 stdout这让同一套协议无需 harness 定制即可跑在 Claude Code、Cursor、Codex、Gemini CLI 等工具上。仓库中的浏览器端运行时skill/scripts/live-browser.js落实了另一半元素拾取器、动作浮层、全局条、变体循环器依赖MutationObserver监听[data-impeccable-variant]子节点、SSE 连接与 localStorage 会话持久化并且全部 UI 用createElement/textContent构建、不用innerHTML配合 127.0.0.1 绑定、会话 token 校验与/source路径穿越防护构成安全边界。二、先决条件与整体角色模型一个 live 会话把三方桥接在一起docs/adr-live-variant-mode.md 的角色图浏览器用户选元素、挑动作、循环变体本地服务端一个小型 localhost HTTP 服务器SSE 长轮询 源文件读取中继浏览器与 Agent 的消息并在 Agent 缺席时暂存事件Agent真正的生产者通过修改源文件来生成变体。前置条件很轻一个运行中且带 HMR 的开发服务器Vite、Next.js、Bun 等或者浏览器里打开的一个静态 HTML 文件。文档特别提醒如果开发服务器的默认端口已被占用应用极可能已经在运行——先探测默认 URL不要贸然再起一个服务。仓库对这套基础设施的验证是成体系的。浏览器侧行为在skill/scripts/live-browser.js中实现了会话恢复、变体包裹器探测等逻辑例如document.querySelector([data-impeccable-variants...])的整套查询贯穿其中端到端场景沉淀在tests/live-e2e/与tests/live-e2e.test.mjs而tests/live-reference.test.mjs则以断言形式锁死了本文档中「先 boot、后轮询、事件有序处理」等作者契约防止规范与实现漂移。三、协议契约顺序执行、_instructions优先live 模式对 Agent 而言是一个严格定序的协议不是一组零散命令。核心契约打开会话后应熟读一次是按顺序执行一步不跳、一步不换序。live 模式下每个工具输出都可能携带_instructions字段它是针对当前确切情境的权威下一步指令其中已替换好真实 id 与路径当它与你对本文档的回忆冲突时以_instructions为准。八步总览如下后续章节逐一展开live.mjs引导若请求点名或暗示了 monorepo 内的文件/路由/应用推断出具体路径并改以node scripts/live.mjs --target path启动此后整个会话都以返回的projectRoot为工作根。引导过程会依据 dev server 配置文件解析应用根并持久化到.impeccable/live/roots.json所有辅助脚本启动时都会重新锚定到该清单错误的工作目录不会分叉会话状态。PRODUCT.md/DESIGN.md会向上查找到 git 根--file这类相对参数则相对应用根解析。打开应用 URL打开真正服务pageFile的那个 URL可从package.json、文档、终端输出或已有标签页推断。绝不要使用serverPort——那是辅助服务器不是应用。在 Cursor 上必须先browser_navigate再轮询不得跳过其他 harness 使用可用的浏览器工具URL 不确定则询问用户一次。轮询循环使用默认长超时600000 ms。每次事件处理或--reply之后立刻再跑live-poll.mjsCodex 以前台一次性轮询运行。绝不传短的--timeout。全局条上的 Impeccable 标记在没有进程轮询/poll时会变暗并亮起琥珀色脉冲点此时需要重启live-poll.mjs重新接入。generate事件优先复用event.scaffold有截图就读截图加载该动作的参考文档交付变体--reply done继续轮询。生成要留在当前线程里进行你已持有项目的 token 与布局overlay 预览本身就是验证通道在 generate 与 accept 之间不要自行截图、重渲染或做 QA。steer事件读消息与pageUrl干活--reply steer_done继续轮询没有单独的 pickup 确认。accept/discard事件轮询脚本会代为运行live-accept.mjs并确认投递、打印_completionAck。普通 accept/discard 立即终结carbonize 类 accept 在live-complete.mjs --id EVENT_ID运行前保持可恢复。要先完成清理再继续轮询。中断恢复被中断时先跑live-status.mjs或live-resume.mjs再猜测。.impeccable/live/sessions/下的追加式日志是权威状态辅助脚本重启后会重放未确认的工作注入的live.js在页面重开时会自动重挂。仅当live-resume.mjs报告无活动会话时才退回直接编辑循环——绝不要因为「断连次数感觉很多」就绕过。exit事件执行文末的清理流程。tests/live-reference.test.mjs对这些约束做了逐条断言契约必须位于文档前 60 行内、包含「No step skipped, no step reordered」、轮询循环紧随其后、manual_edit_apply处理器必须排在prefetch之后、exit之前并且 provider 专属内容如 Codex 的sandbox_permissions: require_escalated不能泄漏进其他 harness 的编译产物。Harness 轮询策略协议能跨 harness 通用但轮询的托管方式因 harness 而异Claude Code以后台任务跑轮询无短超时harness 在完成时通知你不要阻塞 shell。Cursor在后台终端里做**一次性one-shot**轮询在事件类型type:(steer|generate|accept|discard|manual_edit_apply|variant_mount_failed|prefetch|exit)时通知处理后--reply并重启轮询。不要在 Cursor 上用--stream实测一次性轮询约亚秒级拾取而 stream 模式约 5 秒。Codex默认在让出yielded的前台 exec 会话里做一次性轮询。不用、不用--stream绝不能在没有前台轮询的情况下把 Live 留在那里。启动轮询不够——必须服务它持续读 exec 会话直到返回事件一个没人读的让出轮询就是死会话用户的 Go 会无人应答。其他 harness默认前台一次性轮询除非你确知 shell 退出时 stdout 会可靠返回。投递策略与沟通原则全链路统一采用原子式单次编辑投递除非某 harness 的轮询循环已知不会因额外调用而阻塞否则不要切到渐进式发布。聊天是开销不回顾、不输出教程、不粘贴 PRODUCT/DESIGN 正文把 token 花在工具调用与编辑上失败时只写一两句简短说明。四、引导Start、输出 JSON 与配置错误node .vibe/skills/impeccable/scripts/live.mjs输出 JSON 形如{ ok: true, serverPort: 8400, serverToken: uuid, pageFiles: [...], roots: {...}, hasProduct: true, product: ..., productPath: ..., hasDesign: true, design: ..., designPath: ..., hasSurfaceBrief: true, surfaceBrief: {...} }roots是解析出的根清单projectRoot镜像roots.appRootsurface brief表层设计简报随 boot 一起送达不要再单独 shell out 去跑surface-brief.mjsserverPort/serverToken属于那个小辅助 HTTP 服务器/live.js、SSE、/poll不是你的 dev server页面 URL 是任何「提供某个pageFiles条目」的 origin。优先级规则视觉决策上DESIGN.md 胜出持久的产品与语气决策上PRODUCT.md 胜出该表层surface的策略上surface brief 胜出。当 DESIGN.md 缺失时身份identity并非缺席——应从 CSS 变量、计算样式与同级组件中提取见 Step 4 Phase A。身份保留是默认行为偏离身份必须有用户明确的 redesign 意图。配置错误若输出是{ ok: false, error: config_missing | config_invalid, path }说明项目需要一次性配置去读 live-setup.md 并照做。若输出带有非空configDrift向用户说一次哪些 HTML 文件未被覆盖建议补上或将files换成 glob绝不自动改配置。五、轮询主循环与事件分发文档给出的事件分发循环如下LOOP: node .vibe/skills/impeccable/scripts/live-poll.mjs # default long timeout; no --timeout Read JSON; dispatch on type generate → Handle Generate; reply done; LOOP steer → Handle Steer; reply steer_done; LOOP accept → Handle Accept; complete carbonize cleanup if required; LOOP discard → Handle Discard; LOOP prefetch → Handle Prefetch; LOOP manual_edit_apply → Handle Manual Edit Apply; reply done|partial|error; LOOP variant_mount_failed → Fix the variant files; reply done --file path; LOOP timeout → LOOP exit → break → Cleanup几个容易踩的点variant_mount_failed意味着浏览器没能渲染你发布的内容事件带variant、模块url、error用户看到的是持久错误卡片而不是变体。修复变体文件后执行--reply EVENT_ID done --file manifest 或源码路径浏览器会自行重试。Stream 模式--stream实验性绝不在 Cursor 用单个长生命周期进程、每事件一行 JSON、--reply由独立命令发出只适合能可靠读取增量 stdout 的 harness。恢复命令.impeccable/live/sessions/下的追加式日志append-only journal是权威的持久状态它不是项目源码。当聊天被中断、漏了轮询、辅助脚本重启或浏览器刷新时node .vibe/skills/impeccable/scripts/live-status.mjs # helper 状态、活动会话、排队事件helper 宕机时也可用 node .vibe/skills/impeccable/scripts/live-resume.mjs --id SESSION_ID # 活动快照、待处理事件、下一步安全动作 node .vibe/skills/impeccable/scripts/live-complete.mjs --id SESSION_ID # 清理验证后的权威手动最终确认服务重启规则把live-server.mjs重新拉起来然后开始轮询即可——启动时会重新排队未确认事件所以绝不要让用户再点一次 Go除非live-resume.mjs明确报告没有活动会话。六、处理generate两种模式generate事件有两种形态Replace 模式默认{id, action, freeformPrompt?, count, pageUrl, element, screenshotPath?, comments?, strokes?}。Insert 模式event.mode insert{id, mode: insert, count, pageUrl, insert: { position, anchor }, placeholder: { width, height }, freeformPrompt?, screenshotPath?, comments?, strokes?}。没有action且必须有非空freeformPrompt或标注placeholder只是软性的尺寸提示。速度很重要用户正盯着被选中的元素。要复用 preflight 元数据、把发现性discovery的调用压到最少。Insert 模式分支有截图则先读截图仅看标注。若event.scaffold存在直接用、不要再跑一次 helper否则node .vibe/skills/impeccable/scripts/live-insert.mjs --id EVENT_ID --count EVENT_COUNT --position after \ --element-id ANCHOR_ID --classes class1,class2 --tag section --text ANCHOR_TEXT--position取自event.insert.position锚点标志的映射与 wrap 完全一致。scaffold没有data-impeccable-variantoriginal变体是插入在insertLine的全新 HTMLCSS。在 source-preview 目标上scaffold 携带sourceWritten: false与wrapperBlock且replaceEndLine replaceStartLine表示一次插入要把变体在标记处拼进wrapperBlock再在一次编辑里于replaceStartLine插入。Svelte 目标走与 wrap 相同的组件流程manifest 中mode: insert对非 Svelte 目标accept/discard 会移除 wrapper锚点本身不动。在写全新标记前根据表层决定访客模式visitor mode并先读 craft-floor.md。Replace 模式完整八步1. 读截图若有。event.screenshotPath仅当用户在 Go 之前做了标注才出现它是带标注烘焙在内的元素 PNG。读它在规划之前。缺席时不要自己索要或截屏——没有标注的截图会把你钉在现有设计上跟「三个差异显著的方向」的要求对着干此时依据element.outerHTML、计算样式和 prompt 干活。标注语义comment 的{x, y}是元素局部的它把文本绑定到该点下方的子元素标题旁的 comment 就是在说标题注释与笔画strokes除非明显成对否则互相独立。笔画按形状解读闭环 「这个东西」强调不是裁剪区箭头 方向或运动叉/斜杠 删除涂鸦 强调或删除看语境。若某个笔画意图确实歧义且会影响简报生成前问一个简短问题否则用一句话陈述你的解读。2. 包裹元素wrap。当event.scaffold存在时helper 已找到源并算好 wrapper把它当作成功输出、跳过命令event.scaffoldAttempted带scaffoldError则说明 preflight 未完成用下面的命令node .vibe/skills/impeccable/scripts/live-wrap.mjs --id EVENT_ID --count EVENT_COUNT --element-id ELEMENT_ID --classes class1,class2 --tag div --text TEXT_SNIPPETFlag 映射各自独立绝不并进--query--element-id←event.element.id--classes← 用逗号连接的类名--tag← tagName--text←textContent的前约 80 字符每次调用都要传它用来消歧重复的同级组件不传时 wrap 会落在第一个匹配上。如果event.pageUrl暗示了文件则加--file PATH。若--text仍匹配多个候选wrap 以{ error: element_ambiguous, candidates, fallback: agent-driven }退出从页面上下文挑出正确区间按 fallback 流程手工写 wrapper。成功输出{ file, insertLine, commentSyntax, styleMode, styleTag, cssSelectorPrefixExamples, cssAuthoring }source-preview 目标还会带上述sourceWritten: false字段。直接运行无 preflight scaffold时它自己写 wrapper你在insertLine处拼接变体。styleMode决定预览 CSS 的写法——把它当作探测到的能力模式而非框架猜测scoped指scope ([data-impeccable-variantN])规则astro-global-prefixed指带返回的确切styleTag的显式[data-impeccable-variantN]前缀。以cssAuthoring为当前文件的唯一事实来源styleTag、选择器策略、要求、禁用模式除非它明说否则不套任何框架专属例外。source-preview 目标的关键陷阱event.scaffold携带sourceWritten: false——helper没有写 wrapper而是交给你scaffold.wrapperBlock与被选中元素的源码区间replaceStartLine、replaceEndLine1 起始。你必须在一次编辑里同时写入 wrapper 和所有变体把变体拼进wrapperBlock的「Variants: insert below this line」标记处再用结果替换[replaceStartLine, replaceEndLine]。分开写会在你的变体落地前先触发框架重载让浏览器卡在 0/N。replaceEndLine replaceStartLine即 insert 模式只插入、不删除。Svelte/SvelteKit 目标返回previewMode: svelte-componentfile指向临时node_modules/.impeccable-live/id/manifest.jsoncomponentDir放变体组件sourceFile是真实路由。scaffold 是AST 驱动的控制流块{#each}、{#if}原样存活自由的 each 集合以一个结构化 propkindcollection跨过契约。payload 已含componentStubMarkup已写进每个 stub 的 prop 替换后标记所以不要回读 manifest 或 stub。直接就地编辑v1.svelte、v2.svelte……绝不删除重建保留 stub 的控制流与propContract的 prop 名不要把循环拍平成字面量列表。stub 的style已预置了当前给选中元素设样式的源码规则可随意重写或删除。注意accept 时任何你的变体未重新声明的预置规则都会从源码中移除预览从未应用它用户批准的是没有它的设计。用语义化的 class 选择器不用scope、不用data-impeccable-*。回复时--file指向 manifest 路径浏览器挂载编译后的组件Svelte HMR 不会重置页面状态。accept 会把选中的组件机械地合并回去你在这条路径上没有 accept 后的清理工作。当选区含解耦预览无法支持的构造组件标签、bind:/use:、await 块、内联脚本、展开属性时wrap 退回普通 source-preview wrapper 并给previewFallback: { from: svelte-component, reason }照返回形状走即可。组件预览路径上的参数进 sidecar绝不当属性写Svelte 会把属性值里的{当表达式解析。在componentDir/params.json里按变体编号声明schema 同第七节{ 1: [ {id:density,kind:steps,default:snug,label:Density,options:[ {value:airy,label:Airy},{value:snug,label:Snug} ]} ] }组件style对range/toggle用var(--p-id, default)、对steps用[data-p-id…]并包在:global(...)里让挂载根上来自运行时的旋钮值能抵达你的规则。Fallback 错误wrap 拒绝写入非源码文件生成的、未跟踪的——把变体 accept 进这类文件等于无声的数据丢失。三种形态都带fallback: agent-drivenfile_is_generated--file指向生成文件、element_not_in_sourcegeneratedMatch元素只存在于生成产物、element_not_found多半是运行时注入。分别的处理见「Handle fallback」。3. 加载动作的参考。event.action是impeccable自由形式时依据 SKILL.md 的设计规则加 craft-floor.md 工作并根据表层决定访客模式不加载子命令参考。自由形式不是跳过参数的理由遵循第七节的预算与自由形式偏向。其他任何动作bolder、quieter、distill、polish、typeset、colorize、layout、adapt、animate、delight、overdrive规划前先读reference/action.md其 MUST 参数叠加在第七节预算之上。仓库的 SKILL.md 命令表把这些动作统一归在liveIterate之下并给出每条动作对应的参考文档链接。七、四阶段变体规划先身份、再模式、后轴Live 运行在已存在的表层上——品牌早已选好。工作是身份之内的变奏不是身份之间的挑选。最糟的失败是产出三个用户无法接受的跑题变体。四个阶段按序进行。Phase A提取身份不可跳过按优先级取源DESIGN.md 的视觉系统字段 → CSS 自定义属性事实上的 token→ 被选中元素及其父级的计算样式 → 同级组件的视觉修辞。写一句话记录屏幕上真正有什么主表面色与强调色写真实值不是「暖色」、加载的字型配对、布局拓扑堆叠/并排/网格/不对称/覆盖、表面处理圆角、边框、阴影、装饰密度、从文案读出的语气。要具体宁可跳过某个轴也不要编造不要命名美学家族那是结论不是数据。这句话就是身份锁identity lock每个变体并排时都必须读起来像同一品牌。DESIGN.md 缺失绝不是借口。Phase B选模式默认 vs 偏离**默认Default**保留身份、在身份内变奏表达约覆盖 90% 的会话。**偏离Departure**拒绝身份只有当前请求或 prompt 中用户明确要求「redesign this」「rebuild from scratch」「something completely different」才触发一条过期的 critique 或旧笔记不是授权。不确定就走默认默认错了代价是「三个风格近似但同品牌、可恢复的变体」偏离错了代价是「三个跑题的变体、不可恢复」。Phase C规划三个变体默认模式下每个变体锚定不同的主轴primary axis同时保住身份句。六条轴1层级哪个元素抢眼、2布局拓扑堆叠/并排/网格/不对称/覆盖、3字体系统配对逻辑、缩放比、大小写/字重在可用字体内、4颜色策略让哪个既有调色板角色承载表面克制 / 投入 / 全盘 / 浸染只用既有 token、5密度极简 / 舒适 / 致密、6结构分解合并、拆分、渐进披露。三个变体 三条不同的轴同一品牌的三视角。新字体、新色相、新美学家族信号只属于偏离模式。偏离模式下每个变体锚定一个源自品牌的美学方向——绝不来自固定目录读 PRODUCT.md 的 Brand Personality 词汇推导出能体现它们的物理/空间/材质体验据此推导三个彼此真正不同、且与当前表层也不同的方向拒绝那些理由能套在隔壁产品上的反射式选择。每个方向必须是一句点名真实世界参照物的具体句子「博物馆展览标签系统」而不是「干净极简」。两种模式下规划时就给每个变体定好 2–3 个参数旋钮第七节预算。参数是设计的一部分「什么可调」在规划期决定好好过事后补。Phase D眯眼测试Squint test默认把每个变体与 Phase A 的身份锁对比——调色板、字体语气或修辞漂移意味着它意外越界进了偏离返工。再确认三条主轴互不相同三个「更紧致密度」的变体是失败。偏离两轮先家族后句子。家族轮不可让步给每个变体贴一个你自选的具体家族标签共享或可互换的标签意味着返工。句子轮三个一句话描述并排两句押韵雷同就返工。主轴是颜色或主题时三件套不得共享主题 主导色相要三个色彩世界不是三个色阶。动作专属调用必须沿该动作的维度各不相同bolder每个变体放大不同维度缩放 / 饱和度 / 结构改变quieter各收回不同维度颜色 / 装饰 / 间距distill各移除不同类别的冗余视觉噪音 / 冗余内容 / 嵌套结构polish各走一条不同的精修轴节奏 / 层级 / 微细节typeset各自不同配对且不同缩放比colorize每个变体不同色相家族变化彩度与对比策略layout不同结构排布不是间距微调adapt每个变体不同目标情境移动优先 / 平板 / 桌面 / 打印或低数据animate不同动效词汇级联交错 / 裁剪扫入 / 缩放聚焦 / 形变 / 视差delight不同个性风味微交互 / 字体惊喜 / 插画点缀 / 声音或触觉 / 彩蛋overdrive不同被打破的惯例缩放 / 结构 / 动效 / 输入模型 / 状态转换跳过它的「提议并询问」步骤live 是非交互的。八、应用自由形式 prompt若有event.freeformPrompt是用户对方向的上限所有变体都遵守它同时在其内探索 Phase B 模式内的不同诠释。默认模式prompt 收窄的是轴不是身份「更自信一点」→ 一个变体放大层级、一个落定强调色、一个收紧密度。偏离模式prompt 收窄的是跑道不是家族「报纸头版」→ 大报 vs 小报 vs 行业刊物然后跑家族轮。当 prompt 与既定的品牌承诺或 DESIGN.md 不变量冲突时除非用户明确撤销否则保住不变量。九、交付变体包裹器标记、原子编辑与预览 CSS每个变体都是对原元素的完整 HTML 替换不是纯 CSS 补丁。预览 CSS 以style标签就近放在 wrapper 内。原子默认CSS 全部变体 参数 manifest 在insertLine一次编辑完成!-- Variants: insert below this line -- style>style>div>node .vibe/skills/impeccable/scripts/live-poll.mjs --reply EVENT_ID done --file RELATIVE_PATHRELATIVE_PATH相对项目根当 dev server 没有 HMR 时浏览器直接取源文件。然后立即再轮询。中止进行中的会话若 wrap 或生成在浏览器已翻到 GENERATING 之后失败要告诉浏览器让它的条复位node .vibe/skills/impeccable/scripts/live-poll.mjs --reply EVENT_ID error Short reason。绝不用live-accept --discard做这件事那是纯文件修改器浏览器看不到条会卡在圆点上--discard只用于浏览器自己发起的 discard 的源码侧清理。十、处理 fallbackAgent 亲自找源wrap 返回fallback: agent-driven时由你自己挑源文件目标不变现在三个预览变体、被接受的那个要持久化到下次构建擦不掉的地方。从错误载荷找元素真正在哪element_not_in_sourcegeneratedMatch表示被服务的 HTML 是生成的——去找生成器的模板或 partialelement_not_found表示运行时注入——去找渲染组件或数据源file_is_generated同理解析。纯视觉改动可能该进共享样式表而非模板。在被服务的文件里预览手工写出live-wrap.mjs会产生的同一套 wrapper scaffold!-- impeccable-variants-start ID --div>node .vibe/skills/impeccable/scripts/live-server.mjs stop它会停掉 helper 并运行live-inject.mjs --remove以剥掉注入脚本用stop --keep-inject可保留以快速重启.impeccable/live/config.json作为项目配置持久保留。然后搜索并移除任何残留的impeccable-variants-startwrapper 与impeccable-carbonize-start块。十四、首次配置config、CSP 检测与 consent 流程仅当live.mjs报告config_missing/config_invalid、configDrift需要解释、或配置缺cspChecked时才读 live-setup.md。它负责 config schema、各框架files表、注入适配器、漂移修复与 CSP 检测/consent 流程不属于每次会话的热路径。配置文件默认写在.impeccable/live/config.json{ files: [path-or-glob, path-or-glob, ...], exclude: [optional-glob, ...], insertBefore: /body, commentSyntax: html, cspChecked: true }files是注入目标浏览器真正加载的 HTML 文件不一定是源码此处不区分已跟踪与生成文件wrap 另有自己的生成文件闸门。条目是字面路径或 globexclude可选跳过filesglob 会包含的文件邮件模板、demo fixture。硬排除路径不可覆盖**/node_modules/**与**/.git/**——往那里注入等于给第三方代码插桩。glob 语法**匹配任意段数含零、*匹配段内、?匹配单字符路径相对项目根、用正斜杠。各框架的注入目标速查表完整表格见 live-setup.mdFrameworkfilesinsertBeforecommentSyntaxSPA 单壳Vite / React / Plain HTML[index.html]/bodyhtmlNext.jsApp Router[app/layout.tsx]/bodyjsxNext.jsPages[pages/_document.tsx]/bodyjsxNuxt[app.vue]/bodyhtmlSvelte / SvelteKit[src/app.html]/bodyhtmlTanStack StartSSR[src/routes/__root.tsx]Scriptsjsx多页站点[public/**/*.html]glob/bodyhtml多页站点建议用 glob 让新页面自动被覆盖。对由生成器重建的页面注入只存活到下次再生成每次构建后重跑live.mjsaccept 不受影响它经 fallback 流程写真源。框架适配器在注入时自动检测SvelteKit、Nuxt、TanStack Start 都是服务端渲染文档壳模板里裸script不可靠执行live-inject.mjs会改道到专用适配器SvelteKit从layout.svelte起 dev-only 根组件Nuxtdev-only.client.ts插件TanStack Start在__root生成 dev-onlyImpeccableLiveRoot组件。每次注入都会把所写内容记录进.impeccable/live/inject-journal.json下次注入/移除会修复崩溃或错误目录 stop 留下的产物。Config drift每次 boot 会扫描公共页面根public/、src/、app/、pages/下、解析出的files列表未覆盖的 HTML以configDrift.orphans配提示浮现。每会话告诉用户一次哪些文件未覆盖、建议补上或换成 glob绝不自动改配置。CSP 检测仅首次若config.cspChecked true则整节跳过。否则跑node .vibe/skills/impeccable/scripts/detect-csp.mjs输出{ shape, signals }。shape 命名的是补丁机制一个模板可覆盖很多框架null无 CSP直接写cspChecked: true收工、append-arrays结构化指令数组可自动补丁如additionalScriptSrc/additionalConnectSrc、append-string字面量值字符串可自动补丁如内联next.config.*的headers()、middleware/meta-tag检测到但不自动补丁请用户手工给script-src/connect-src加上http://localhost:8400。自动补丁按框架落点操作并保持幂等Next.js 用app 的next.config.*不是共享 helperSvelteKit 用svelte.config.js的kit.csp.directivesNuxt 用nuxt-security或routeRules。仓库的参考输出在tests/framework-fixtures/nextjs-turborepo/expected-after-patch.ts、tests/framework-fixtures/nextjs-inline-csp/expected-after-patch.js、tests/framework-fixtures/sveltekit-csp/expected-after-patch.js与tests/framework-fixtures/nuxt-csp/expected-after-patch.ts均可对照验证。补丁需向用户征求同意且必须受NODE_ENV development守卫——只出现在 dev、绝不进生产。用户若拒绝可随时删除cspChecked字段并重跑live.mjs让配置流程重新询问。十五、源码证据与延伸阅读会话运行参考本文骨架.vibe/skills/impeccable/reference/live.md多 harness 发布版同文源存于 skill/reference/live.md一次性配置参考live-setup.md架构决策记录docs/adr-live-variant-mode.mdSSEfetch、源码而非 DOM 补丁、display: contents包裹器、无 HMR 回退、消息流、会话持久化与安全模型一应俱全浏览器端运行时skill/scripts/live-browser.js 及其 DOM/会话/忽略辅助 live-browser-dom.js、live-browser-session.js、live-browser-ignores.js端到端测试tests/live-e2e/agent.mjs、session.mjs、ui.mjs、tests/live-e2e.test.mjs以及锁定 live 参考规范作者契约的 tests/live-reference.test.mjs手动编辑应用 subagent 契约skill/agents/impeccable-manual-edit-applier.md。需要留意的是live.mjs、live-poll.mjs、live-wrap.mjs等 Node 辅助脚本随技能以.vibe/skills/impeccable/scripts/布局投递到用户项目SKILL.md 的 allowed-tools 亦按node .vibe/skills/impeccable/scripts/*授予仓库快照内的skill/scripts/主要保存浏览器侧运行时与数据而本参考文档与 ADR 完整描述了 helper 脚本的行为契约并以上述 e2e 与 lint 测试持续校验。对开发者而言这就是一套跨 harness 的通用「浏览器内视觉迭代」协议按本文的顺序执行 boot → 轮询 → 分发就能够在任何带 shell 的 AI 环境里复现 Impeccable 的实时设计迭代体验。【免费下载链接】impeccableThe design language that makes your AI harness better at design.项目地址: https://gitcode.com/GitHub_Trending/im/impeccable创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻