diff --git a/docs/协作/B01-验收-02.md b/docs/协作/B01-验收-02.md new file mode 100644 index 0000000..a1cdd88 --- /dev/null +++ b/docs/协作/B01-验收-02.md @@ -0,0 +1,55 @@ +# B01 验收 02:F01 与模式、确认弹窗 + +日期:2026-10-21(Asia/Shanghai)。对应 [交付 02](B01-交付-02.md),固定受测代码 **`1ed71b63b5af9a98b942ff47c66df5799d4d2c8a`**。 + +**结论:F01 原始反例已通过,A05/A06 本次交付的功能与已确认样式修复通过独立 Windows 检查;原生模式测试入口仍需修复。B01 不全量关闭。** + +本记录补齐前轮已执行但未正式回传的结果。没有使用后来 B02 或测试清理提交替代受测代码。新建本轮专用文档检出,避免复用出现并发推进的旧文档检出;未修改产品、正式测试、依赖或构建配置。 + +## 1. 环境与数据 + +Windows 11 IoT 企业版 LTSC 64 位,10.0.26100;Node 24.21.0、npm 11.19.0、Electron 37.10.3。固定 SHA 的独立检出执行 `npm ci --legacy-peer-deps --no-audit --no-fund`,显式补执行 Electron 安装脚本后构建;没有复用开发机依赖。jsdom 30.1.3 安装于 `.tmp/b01-dom`。 + +所有应用/组件窗口均使用测试 userData、home、workspace。仅使用本地持久化消息或受控回调,不请求模型、SDK query/CLI,不操作用户实际会话,不访问 WorkBuddy 原版。已有真实用户 dev 未被这些测试结束或替换。 + +## 2. 分项结果 + +| 项目 | 独立结果 | 范围 | +| --- | --- | --- | +| F01/AC1.3 原生计划、任务状态 | 通过,关闭本次具体失败 | 原验收 reducer→MessageBubble 反例现在 `retainsUserChoices=true`,两卡均保持 false;新增原生身份回归覆盖插入、重排、外层切换、消息隔离和无 ID 同位置 fallback | +| A05/AC3.1 模式标签 | 本次功能与样式修复通过 | 同一组件真实 Chromium 的透明背景、pill、32px/13px/500/20px、16px 原位槽、hover/focus 替换、禁用与窄窗;95 项通过 | +| A05 宿主草稿/权限 | 通过 | 实际 main/preload/renderer 中,两模式均以原生键盘退出,草稿原样保留,full-access 保存值保持,返回 craft 后权限控件恢复可用 | +| A06/AC3.2~3.3 确认浮层 | 本次已确认参数与行为通过 | 原生应用 71 项菜单/IPC/落库检查;浅深主题主/次/危险按钮、240px 壳、16px 圆角、600 标题、66px 最小宽、19px inset | +| A06 busy/失败/重试 | 通过,组件层 | 同一 TaskPopconfirm 的真实 Chromium 夹具 78 项:运行中“停止并删除”、重复点击锁、busy 不能退出、错误保留及重试。受控回调,不证明真实运行任务终止链路 | +| A01/A04 回归 | 通过指定回归 | alignment、问答真实窗口及浅深/窄窗/长内容壳检查通过 | + +按钮本轮实际几何为高 28px、圆角 6px、字体 12px,按交付的 small Button 规格验证;**并未由此认定原版所有按钮几何或整页像素完成 1:1**。ModeChip 的原版 SVG 仍未替换;没有同版本、同状态原版运行对照,原版完整视觉结论继续未验证。 + +F01 原始结果:[JSON](evidence/B01-review-02/typed-part-result.json)、[反例源码](evidence/B01-review-02/typed-part-repro.mjs)。在固定受测检出中,将脚本复制到 `.tmp/b01-readonly-review/` 后执行 `node .tmp/b01-readonly-review/typed-part-repro.mjs --assert`,本轮退出 0。本文仅引用当前产品模式的执行结果,不将脚本的其他分支视为本轮已运行。 + +## 3. T01:原生模式测试入口在 Windows 超时 + +`node scripts/test-mode-chip-native.mjs` 本轮运行 60 秒后被其超时定时器结束,父进程记录 `exitCode:null`。仅生成 fixture,没有 report 或 failure;因此**该命令没有通过**。[原始结果](evidence/B01-review-02/original-mode-runner.txt)。 + +验收端另用 `.tmp` 下 CJS 异步测试入口加载同一份已生成 fixture,保留原尺寸、主题、布局、禁用与原生输入检查,并补齐原生键盘字符事件;95 项通过。[入口](evidence/B01-review-02/mode-cjs-runner.cjs)、[报告](evidence/B01-review-02/mode-report.json)、[运行结果](evidence/B01-review-02/mode-cjs-runner.txt)。 + +开发端需修正式测试入口的 Windows 可运行性、事件序列及超时诊断。静态线索是原 ESM 入口在顶层等待 fixture 构建与 `app.whenReady()`;这不是本轮已经证明的唯一根因,不能只改扩长 timeout 就宣布修复。CJS 对照说明组件在同一环境可运行,不把入口超时等同于产品模式功能失败。 + +## 4. 其他命令与既有失败 + +- 独立 `npm run build`、带 DOM 环境的 `test:alignment`、`test:conversation`、`test:workbuddy-import`、`test:artifacts` 均退出 0。 +- `check:tokens` 仍退出 1,为既有六项;`test:fold-summary` 仍退出 1,为既存 Windows CRLF 摘要问题。没有刷新 baseline、修改生成物/manifest,不能将这些命令写成通过。 +- 原生菜单 71 项、CJS 模式 95 项、弹窗 Chromium 78 项均为实际执行,不是 `--build-only`。 +- 只有显示并允许 compositor 推进后,才采纳弹窗 busy 动画颜色结果;初次隐藏窗口的未稳定颜色没有列为产品缺陷。 + +证据:[构建](evidence/B01-review-02/build.txt)、[alignment](evidence/B01-review-02/alignment.txt)、[其他命令](evidence/B01-review-02/regressions.json)、[原生菜单](evidence/B01-review-02/menu-report.json)、[弹窗](evidence/B01-review-02/popconfirm-browser-report.json)、[模式宿主](evidence/B01-review-02/mode-host-report.json)、[问答](evidence/B01-review-02/question-report.json)。 + +截图:[归档浅色](evidence/B01-review-02/archive-light.png)、[删除深色](evidence/B01-review-02/delete-dark.png)、[计划聚焦](evidence/B01-review-02/mode-plan-focus.png)、[仅问答深色聚焦](evidence/B01-review-02/mode-ask-dark-focus.png)。已人工查看。 + +复跑模式与弹窗的验收入口时,先在指定 SHA 构建,使用交付脚本的 `--build-only` 生成 fixture,再把对应 CJS 验收入口复制到该检出的 `.tmp/`,传入生成目录;不要提交或复制生成 JS/依赖作为源码交付。宿主探针同样只放 `.tmp/`,自行建立隔离数据。 + +## 5. 后续 + +F01 不再要求重复修复,A05/A06 本次已测行为不推倒重做。后续补 T01 自动化入口、原版 SVG/同状态完整视觉、真实运行中停止链路等未验证边界。YC-002、YC-004、A07/A08没有在本轮交付,不因本记录关闭;保留用户撤回骨架补丁的决定。 + +本记录是验收文档交接,不是产品修复。最终批次状态仍以逐项 AC 为准。 diff --git a/docs/协作/B02-验收-01.md b/docs/协作/B02-验收-01.md new file mode 100644 index 0000000..f3c29e5 --- /dev/null +++ b/docs/协作/B02-验收-01.md @@ -0,0 +1,75 @@ +# B02 验收 01:推荐技能卡片与底部入口 + +日期:2026-10-21(Asia/Shanghai)。对应 [需求](B02-需求.md) 和 [交付 01](B02-交付-01.md),固定受测代码 **`14a1354c95a2081fb32e36917a1b05873b2a662b`**。 + +**结论:本次已安装推荐卡片及底部重复入口的功能修复通过;Windows 受控 UI 62 项、DOM 45 项通过。原仓库 UI 命令在 hover selector 上失败,测试可移植性需补;原版完整像素与真实宿主安装/使用端到端未验证,不将 B02 全量关闭。** + +## 1. 固定版本与隔离 + +在新建 `b02-accept-01` managed worktree 检出指定提交,独立执行 npm ci、Electron 安装脚本和完整构建。起止 Git 受控文件均无修改;未使用正在运行的用户 dev,也未复用上一轮固定验收检出来替换用户窗口。 + +Windows 11 IoT 企业版 LTSC 64 位,10.0.26100;Node 24.21.0、npm 11.19.0、Electron 37.10.3、独立 `.tmp/b02-dom` 的 jsdom 30.1.3。所有 UI 夹具自建 userData,受控 IPC、推荐目录和技能列表,不下载真实技能、不调用模型或修改真实用户技能。 + +本轮之后的 `a839d23` 测试清理、B03 需求及其 merge 没有被混入该 SHA 的产品验收。B03 没有交付,不能据此认定完全访问问题已修。 + +## 2. AC 结果 + +| AC | 结论 | 已验证范围 | +| --- | --- | --- | +| AC5.1 current 动作与卡壳 | 通过 | 安装后 `sm-card--installed`、原动作槽 `sm-use-btn` 出现,Plus/添加按钮不渲染;不再保留卡片下方重复使用动作 | +| AC5.2 已恢复样式 | 通过已测样式;原版完整对照未验证 | 24×24 动作槽、16×16 SVG,默认透明、浅深 hover 颜色变化、可聚焦与尺寸稳定;720px 窄窗无溢出。未证明当前 WorkBuddy 同状态逐像素一致 | +| AC5.3 状态刷新 | 通过受控宿主场景 | 安装、重开、外部安装/卸载/旧 progress 等现有回归通过;不要求重启 | +| AC5.4 身份与异常 | 通过指定 DOM/受控状态矩阵 | 禁用、仅模型调用、损坏、不同来源/版本、修改与 workspace 不冒充 current;没有改身份/安装后端 | +| AC5.5 替换与重复确认 | 通过受控场景 | 安装/更新/替换/修复动作区分;确认、取消及 current 防重复回归通过,后端覆盖保护没有放宽 | +| AC5.6 使用 | 通过组件与 callback;完整宿主端到端未验证 | current 使用回调、禁用先启用/启用失败,以及卡片动作去重通过;成功 toast 使用动作保留。没有实际下载后进入主应用新草稿并验证不发送的完整链路 | +| AC6.1~6.4 footer/导航 | 通过指定场景 | footer DOM/专用 props 与样式移除;顶部已安装计数和切换保留;错误/空目录及重试恢复通过,旧测试不再依赖 footer | + +已人工查看:[安装后浅色](evidence/B02-review-01/installed-light.png)、[深色使用 hover](evidence/B02-review-01/installed-dark-hover.png)、[窄窗](evidence/B02-review-01/installed-narrow.png)。右上顶部“已安装(1)”与安装成功 toast 是保留的导航/瞬时使用动作,不是用户要求移除的底部永久入口。 + +## 3. T02:原 UI 入口的 hover 选择器断言不可用 + +原命令 `npm run test:recommended-skills:ui` 本轮实际退出 **1**,停在: + +```text +light pointer enters use action: false +``` + +不能将原命令记为通过,也不能仅凭这条失败认定使用按钮不可点击。 + +独立诊断发现: + +- 原生鼠标输入后的按钮背景已从透明变为 `rgb(230, 230, 230)`;命中测试返回按钮内部 SVG,pointer-events 为 auto。 +- `button.matches(':hover')` 返回 false,`document.querySelectorAll(':hover')` 为空。 +- 同页添加完全独立的普通 button 对照后,鼠标输入命中该 button,CSS `:hover` 背景准确变化为 `rgb(50, 60, 70)`,但其 `matches(':hover')` 同为 false。这是本环境/事件与 selector 观察边界,不能归为仅 YCode 组件特有问题。 +- 显示/聚焦窗口及独立 CDP Input 鼠标事件也复现相同 selector 结果;没有通过更换产品源码消除。 + +[原始失败](evidence/B02-review-01/original-ui-runner.txt)、[对照结果](evidence/B02-review-01/hover-control.json)、[卡片命中与样式诊断](evidence/B02-review-01/hover-diagnostics.json)。 + +验收端仅在 `.tmp` 的独立探针中,把这条 predicate 换成**原生 `pointerenter` 事件 `isTrusted=true`、`pointerType=mouse`**,保留其他安装、错误/重试、导航、浅深色、实际背景变化、尺寸、焦点和窄窗断言,没有修改产品或正式测试。此入口完整执行 **62 项通过**;浅色 hover 为 `rgb(230, 230, 230)`,深色为 `color(srgb 1 1 1 / 0.08)`。 + +开发端应修正式 UI 入口的可移植性/诊断,不删除真实 hover 验收目标或改为仅检查 class。focus 本轮验证了实际 activeElement 与槽位;未额外证明完整原生键盘导航或屏幕阅读器行为。 + +证据:[独立探针](evidence/B02-review-01/pointer-ui-probe.mjs)、[62 项与计算样式](evidence/B02-review-01/native-report.json)、[运行日志](evidence/B02-review-01/pointer-ui-runner.txt)。重跑时在固定 SHA 安装依赖,将该探针复制成 `.tmp/b02-acceptance/recommended-skills-ui-pointer.mjs` 后执行;它的 Electron 子进程使用该固定路径,自建临时数据。 + +## 4. 全部命令与证明范围 + +| 命令 | 结果 | +| --- | --- | +| `npm ci --legacy-peer-deps --no-audit --no-fund`、Electron 安装、`npm run build` | 独立 Windows 通过,未改依赖/锁文件 | +| `npm run test:recommended-skills:dom`,设置独立 DOM 模块 | 45 项通过,是真实 React DOM/受控宿主,不是布局或真实安装 | +| `npm run test:alignment`,设置 DOM 模块 | 通过;SDK 部分为 mock,不作真实授权结论 | +| `npm run test:recommended-skills` | 退出 0,但 real-package 缺失而 SKIP;紧随的通用 PASS 不能解释为真实发布包验证通过 | +| `npm run test:composer-capabilities` | 退出 0 | +| 原仓库 `test:recommended-skills:ui` | **退出 1**,T02;独立 pointer 入口另行 62 项通过,二者分别记账 | +| `check:tokens` | 退出 1,同六个既有文件;本批 relevant 裸 px 计数下降,没有刷新 baseline | +| `test:fold-summary` | 退出 1,既存 Windows CRLF 摘要问题;未修改生成文件/manifest | + +证据:[构建](evidence/B02-review-01/build.txt)、[DOM 报告](evidence/B02-review-01/dom-report.json)、[alignment](evidence/B02-review-01/alignment.txt)、[其他结果](evidence/B02-review-01/test-results.json)、[后端及真实包 SKIP](evidence/B02-review-01/recommended-backend.txt)、[token](evidence/B02-review-01/token-check.txt)。 + +UI 日志中的“下载失败”“安装取消”“目录不可用”是夹具刻意注入并检查恢复的场景,不是本次真实网络故障;没有发起网络技能安装。 + +## 5. 回传 + +本次用户指出的“已安装仍保留添加按钮”和“底部查看已安装技能”已获得独立修复证据,不要求重复实现。开发端补 T02 正式自动化入口;完整原版对照、宿主安装/使用端到端、键盘/辅助技术边界继续列为未验证,不以组件 62 项冒充全链路通过。 + +本验收只提交文档、日志、截图与独立验收探针,不修改产品/正式测试/依赖/配置。新需求 B03 和后续测试清理按各自记录处理。本文推送成功后,推送窗口交回开发端。 diff --git a/docs/协作/evidence/B01-review-02/alignment.txt b/docs/协作/evidence/B01-review-02/alignment.txt new file mode 100644 index 0000000..ffa37b6 --- /dev/null +++ b/docs/协作/evidence/B01-review-02/alignment.txt @@ -0,0 +1,25 @@ + +> ycode@0.0.7 test:alignment +> node scripts/run-alignment-regression.mjs + +PASS model alignment: fresh/legacy migration, new/edit/default/delete/reload, valid selection (offline host fixtures) +PASS model settings: deferred owner switch, rename mapping, addition selection, empty deletion, immutable history +PASS session factory: first-send preference, mode preservation, invalid permission rejection (isolated ports) +{"historyMessages":10000,"bytes":747781,"parseMs":5.6311999999999784,"storeHydrationMs":0.28300000000001546,"note":"Node parsing/store benchmark only, not browser rendering or Windows IPC performance"} +session-composer-alignment: loading/cache/retry/races/model/permissions/modes/SSR passed +alignment-conversation: local groups, original expanded order, question projection and truthful status passed +A01 native MessageBubble identity aliases, immutable inputs and ordinary raw output passed +A01 imported native card, linked dedup and unknown-position compatibility passed +question-answer-shell: structural and recovered CSS contracts passed +question-answer-shell: DOM hierarchy, controls linkage, click, Enter, Space and inert contracts passed +Runtime progress, session-grant scope and approval lifecycle regressions passed +Permission intercept static rendering passed; interactive keyboard/focus remains UI acceptance +Claude host approval policy unit checks passed (no SDK process/application/matching verification) +Mock SDK replay lifecycle passed: fail closed, retry, session isolation, independent mode guard +task popconfirm DOM regression: 34 checks passed (jsdom, not pixel validation) +question-interaction: 24 DOM behavioral checks passed +question-identity: 30 A01 DOM checks passed (not Electron/pixel/SDK acceptance) +completed-fold-nested: real question/tool/thinking/local-summary remount, event, keyboard and identity contracts passed +completed-fold-native-identity: real reducer done correction, native IDs, insertion/reorder, repeated outer toggles, message isolation and legacy fallback passed +Permission intercept DOM: 14 checks passed (not pixel/SDK verification) +{"checks":37,"passed":true,"scope":"Isolated React DOM and CSS contracts; no native keyboard/layout/pixel acceptance"} diff --git a/docs/协作/evidence/B01-review-02/archive-light.png b/docs/协作/evidence/B01-review-02/archive-light.png new file mode 100644 index 0000000..cc721cd Binary files /dev/null and b/docs/协作/evidence/B01-review-02/archive-light.png differ diff --git a/docs/协作/evidence/B01-review-02/build.txt b/docs/协作/evidence/B01-review-02/build.txt new file mode 100644 index 0000000..aaff724 --- /dev/null +++ b/docs/协作/evidence/B01-review-02/build.txt @@ -0,0 +1,660 @@ + +> ycode@0.0.7 build +> npm run typecheck && electron-vite build + + +> ycode@0.0.7 typecheck +> tsc --noEmit -p tsconfig.node.json && tsc --noEmit -p tsconfig.web.json + +vite v8.3.4 building ssr environment for production... +transforming... +✓ 444 modules transformed. +rendering chunks... +out/main/index.mjs 1,596.10 kB + +✓ built in 400ms +vite v8.3.4 building ssr environment for production... +transforming... +✓ 2 modules transformed. +rendering chunks... +out/preload/index.cjs 15.89 kB + +✓ built in 23ms +vite v8.3.4 building client environment for production... +transforming... +✓ 3039 modules transformed. +rendering chunks... +out/renderer/settings.html 1.57 kB +out/renderer/index.html 1.75 kB +out/renderer/assets/KaTeX_Size3-Regular-CTq5MqoE.woff 4.42 kB +out/renderer/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 4.92 kB +out/renderer/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 5.20 kB +out/renderer/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 5.46 kB +out/renderer/assets/KaTeX_Size4-Regular-BF-4gkZK.woff 5.98 kB +out/renderer/assets/KaTeX_Size2-Regular-oD1tc_U0.woff 6.18 kB +out/renderer/assets/KaTeX_Size1-Regular-C195tn64.woff 6.49 kB +out/renderer/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 6.90 kB +out/renderer/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 6.91 kB +out/renderer/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf 7.58 kB +out/renderer/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff 7.65 kB +out/renderer/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff 7.71 kB +out/renderer/assets/archify-owner-avatar-BdE-HOjX.jpg 9.46 kB +out/renderer/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 9.64 kB +out/renderer/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 10.34 kB +out/renderer/assets/KaTeX_Size4-Regular-DWFBv043.ttf 10.36 kB +out/renderer/assets/KaTeX_Script-Regular-D5yQViql.woff 10.58 kB +out/renderer/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 11.31 kB +out/renderer/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 11.34 kB +out/renderer/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf 11.50 kB +out/renderer/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 12.02 kB +out/renderer/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 12.21 kB +out/renderer/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf 12.22 kB +out/renderer/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff 12.31 kB +out/renderer/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf 12.34 kB +out/renderer/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf 12.36 kB +out/renderer/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff 13.20 kB +out/renderer/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff 13.29 kB +out/renderer/assets/workbuddy-buddy-thumbnail-2713ed5b-CUhW0EYr.png 13.42 kB +out/renderer/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 13.56 kB +out/renderer/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff 14.11 kB +out/renderer/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff 14.40 kB +out/renderer/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff 16.02 kB +out/renderer/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 16.40 kB +out/renderer/assets/KaTeX_Math-Italic-t53AETM-.woff2 16.44 kB +out/renderer/assets/KaTeX_Script-Regular-C5JkGWo-.ttf 16.64 kB +out/renderer/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 16.78 kB +out/renderer/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 16.98 kB +out/renderer/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff 18.66 kB +out/renderer/assets/KaTeX_Math-Italic-DA0__PXp.woff 18.74 kB +out/renderer/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff 19.41 kB +out/renderer/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf 19.43 kB +out/renderer/assets/KaTeX_Fraktur-Regular-CB_wures.ttf 19.57 kB +out/renderer/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf 19.58 kB +out/renderer/assets/KaTeX_Main-Italic-BMLOBm91.woff 19.67 kB +out/renderer/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf 22.36 kB +out/renderer/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf 24.50 kB +out/renderer/assets/KaTeX_Main-Bold-Cx986IdX.woff2 25.32 kB +out/renderer/assets/KaTeX_Main-Regular-B22Nviop.woff2 26.27 kB +out/renderer/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf 27.55 kB +out/renderer/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 28.07 kB +out/renderer/assets/KaTeX_Main-Bold-Jm3AIy58.woff 29.91 kB +out/renderer/assets/KaTeX_Main-Regular-Dr94JaBh.woff 30.77 kB +out/renderer/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf 31.19 kB +out/renderer/assets/KaTeX_Math-Italic-flOr_0UB.ttf 31.30 kB +out/renderer/assets/design-case-3-DaIvrslH.png 32.76 kB +out/renderer/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf 32.96 kB +out/renderer/assets/KaTeX_AMS-Regular-DMm9YOAa.woff 33.51 kB +out/renderer/assets/KaTeX_Main-Italic-3WenGoN9.ttf 33.58 kB +out/renderer/assets/design-case-4-0hVdAJQR.png 45.16 kB +out/renderer/assets/design-case-2-BH_iQ5r3.png 45.56 kB +out/renderer/assets/KaTeX_Main-Bold-waoOVXN0.ttf 51.33 kB +out/renderer/assets/design-case-1-DOYiafVz.png 52.97 kB +out/renderer/assets/KaTeX_Main-Regular-ypZvNtVU.ttf 53.58 kB +out/renderer/assets/KaTeX_AMS-Regular-DRggAlZN.ttf 63.63 kB +out/renderer/assets/workbuddy-appearance-dark-CXQX3TZX.png 109.34 kB +out/renderer/assets/workbuddy-appearance-light-BbpPCukh.png 113.02 kB +out/renderer/assets/codicon-ngg6Pgfi-ngg6Pgfi.ttf 121.97 kB +out/renderer/assets/kimi-DiLyRSiJ.svg 129.22 kB +out/renderer/assets/json.worker-DEWrzUkU-FVRG9O7E.js 438.21 kB +out/renderer/assets/worker-portable-D1lwTqsk-Dg0RNmO0.js 456.22 kB +out/renderer/assets/landing-hero-B6659kdy.png 629.28 kB +out/renderer/assets/html.worker-BC4B-9NY-BDdNc3ca.js 756.63 kB +out/renderer/assets/css.worker-D7wyZb8r-YRw1jg-F.js 1,086.92 kB +out/renderer/assets/ts.worker-BsXRl7a--BbqraoNr.js 8,187.30 kB +out/renderer/assets/ArtifactPierreDiff-CNAfnhAF.css 1.16 kB +out/renderer/assets/GeneralSettingsPanel-CntDyB52.css 1.25 kB +out/renderer/assets/AgentsSettingsPanel-R0teGDyD.css 2.56 kB +out/renderer/assets/AboutHelpSettingsPanel-ksqGLObi.css 5.72 kB +out/renderer/assets/updates-ui-COSnOGKS.css 6.84 kB +out/renderer/assets/AppearanceSettingsPanel-DcaRECSa.css 8.03 kB +out/renderer/assets/ShortcutsSettingsPanel-Bu_5_488.css 18.05 kB +out/renderer/assets/MemorySettingsPanel-C3dtDAif.css 32.49 kB +out/renderer/assets/ModelSettingsPanel-BjNmxQAH.css 88.98 kB +out/renderer/assets/PersonalizationSettingsPanel-DnAyzaM6.css 98.77 kB +out/renderer/assets/app-DH7L1ZF2.css 259.93 kB +out/renderer/assets/index-CvX53u9X.css 2,683.62 kB +out/renderer/assets/pie-WAS4IAKB-1a9lbjhh.js 0.11 kB +out/renderer/assets/info-A6RAGUB7-Dsq8pPGK.js 0.11 kB +out/renderer/assets/radar-RG4KPBEZ-BwNT2qWb.js 0.11 kB +out/renderer/assets/packet-AYTQ26CC-C-iOIVQo.js 0.11 kB +out/renderer/assets/cynefin-OW5HDTMX-CTYbUR58.js 0.11 kB +out/renderer/assets/treemap-WGGIJYW6-CWek0LQD.js 0.11 kB +out/renderer/assets/wardley-WFR3VGLG-BnrEXTnU.js 0.11 kB +out/renderer/assets/gitGraph-4MIJSDKK-NHpEvzKf.js 0.12 kB +out/renderer/assets/railroad-74A4TZTK-CyYHr3KR.js 0.12 kB +out/renderer/assets/treeView-Q6P3EWNA-CzdWA6Mh.js 0.12 kB +out/renderer/assets/railroad-peg-WCYAUIDC-DyA9P8dX.js 0.12 kB +out/renderer/assets/architecture-7GRP2DOG-VyF0wzFW.js 0.12 kB +out/renderer/assets/railroad-abnf-HS5TGJTU-DWOH6PDU.js 0.12 kB +out/renderer/assets/railroad-ebnf-LZEXJU2U-B8jXqV-T.js 0.12 kB +out/renderer/assets/eventmodeling-NTZA5JFV-Dmu4IHsI.js 0.12 kB +out/renderer/assets/array-75Ih5Qg4.js 0.16 kB +out/renderer/assets/channel-Bye_tFRR.js 0.25 kB +out/renderer/assets/init-DHdG6DHP.js 0.27 kB +out/renderer/assets/chunk-Y2CYZVJY-CrOJDJJy.js 0.38 kB +out/renderer/assets/chunk-JWPE2WC7-BWmaSNkB.js 0.42 kB +out/renderer/assets/chunk-2Q5K7J3B-BBOGhvIe.js 0.44 kB +out/renderer/assets/prism-tsx-BJWEHjlk.js 0.48 kB +out/renderer/assets/chunk-5VM5RSS4-D50WUAUX.js 0.52 kB +out/renderer/assets/chunk-XXDRQBXY-BsO966Nz.js 0.58 kB +out/renderer/assets/flowDiagram-HODETNUW-BZrFLTC0.js 0.59 kB +out/renderer/assets/prism-json-DxLGXN1o.js 0.62 kB +out/renderer/assets/codeowners-C7Y3CTAA-BmB2_gvY.js 0.75 kB +out/renderer/assets/prism-clike-BcH_eOfE.js 0.89 kB +out/renderer/assets/tsv-DVa1_Ovr-BeS2kE5e.js 0.94 kB +out/renderer/assets/shellsession-C0HwRpr0-B630Ulnl.js 0.96 kB +out/renderer/assets/javascript-DGySzfUB-CQaVVFGk.js 0.99 kB +out/renderer/assets/settings-CauUETdq.js 1.01 kB +out/renderer/assets/infoDiagram-27XIBGKW-Bulf8uQR.js 1.09 kB +out/renderer/assets/swimlanesDiagram-VR7AAH4N-BSjvAxa9.js 1.09 kB +out/renderer/assets/html-derivative-D3Jld805-D0QQ5MTi.js 1.10 kB +out/renderer/assets/prism-go-Cw8Jg9YT.js 1.11 kB +out/renderer/assets/classDiagram-ZZMXUADV-B5IckmXo.js 1.16 kB +out/renderer/assets/classDiagram-v2-VYDZK3BY-pNfhH-ZZ.js 1.16 kB +out/renderer/assets/stateDiagram-v2-MP3YSRHH-DhZlJKgF.js 1.16 kB +out/renderer/assets/qmldir-DIq06gp2-CFVtueeV.js 1.20 kB +out/renderer/assets/git-rebase-CgwCWTNR-Cpss9r90.js 1.23 kB +out/renderer/assets/chunk-POPQ4Y6H-7RcIGbEp.js 1.23 kB +out/renderer/assets/azcli-Bsxmaz-H-Dgh56k5-.js 1.26 kB +out/renderer/assets/personalization-prefs-DASR3vwn.js 1.28 kB +out/renderer/assets/csv-BRhERoQG-DKrQczXm.js 1.36 kB +out/renderer/assets/prism-latex-CHSuA_Lo.js 1.38 kB +out/renderer/assets/jsx-runtime-C48wkPcG.js 1.41 kB +out/renderer/assets/git-commit-DGtBy1vY-s2uHofP2.js 1.47 kB +out/renderer/assets/AgentsSettingsPanel-CMYBwUKH.js 1.56 kB +out/renderer/assets/xsl-DV28r3Jw-B8bWzO_h.js 1.59 kB +out/renderer/assets/dotenv-DXc2fSbR-CUbEjgJq.js 1.62 kB +out/renderer/assets/general-settings-icons-DOmPIusw.js 1.64 kB +out/renderer/assets/prism-scala-CRTYzCpy.js 1.65 kB +out/renderer/assets/ini-D4-1Iswn-DaNDgFS8.js 1.65 kB +out/renderer/assets/prism-typescript-D-7ZUUQ-.js 1.65 kB +out/renderer/assets/sizeCapture-INFHLROL-CCEMv_MJ.js 1.68 kB +out/renderer/assets/csp-Bsbijh2H-033SDyRW.js 1.69 kB +out/renderer/assets/sparql-Mj-YIaDH-DAUou2oc.js 1.71 kB +out/renderer/assets/prism-css-Cmyw76Xa.js 1.73 kB +out/renderer/assets/ini-DMSv7OY2-xgSkktY4.js 1.74 kB +out/renderer/assets/rolldown-runtime-BJCASTsb-DKQFAHUF.js 1.78 kB +out/renderer/assets/line-D_yBR5ay.js 1.89 kB +out/renderer/assets/fortran-fixed-form-D91DiZLE-NxoUlVkB.js 1.91 kB +out/renderer/assets/docker-B7J3eHK7-C3FNXPS_.js 1.96 kB +out/renderer/assets/hxml-938TheZ7-pE5ojWPT.js 1.97 kB +out/renderer/assets/desktop-BwI-o01e-Da9rFJOd.js 2.03 kB +out/renderer/assets/ordinal-CmpyCcm_.js 2.22 kB +out/renderer/assets/prism-c-B7tsC1jE.js 2.23 kB +out/renderer/assets/rolldown-runtime-EITvVbkG.js 2.32 kB +out/renderer/assets/erb-BgMB3Uiw-CLkRQ9Hf.js 2.40 kB +out/renderer/assets/prism-kotlin-Bc2NQYRR.js 2.43 kB +out/renderer/assets/jssm-CIisorE2-ggX0kbSA.js 2.44 kB +out/renderer/assets/prism-python-CTkfasgb.js 2.48 kB +out/renderer/assets/reg-mzCtpvUf-BHC3bGU6.js 2.54 kB +out/renderer/assets/bat-2PwuskcT-BbFmQdFU.js 2.55 kB +out/renderer/assets/prism-mermaid-DSoNsh6-.js 2.56 kB +out/renderer/assets/pla-HAHcX3CH-DHyEyFew.js 2.57 kB +out/renderer/assets/sb-O6mPt74--_nMcDiF8.js 2.60 kB +out/renderer/assets/chunk-GVQU2GXP-Wi49q5c7.js 2.61 kB +out/renderer/assets/edge-DcEd3r9D-ZJX3cnY_.js 2.62 kB +out/renderer/assets/scheme-C-yCXfo--BHhgh59u.js 2.66 kB +out/renderer/assets/flow9-z3HgHIql-qOic_Sv2.js 2.72 kB +out/renderer/assets/prism-yaml-cmjQ_1eD.js 2.77 kB +out/renderer/assets/gleam-DEEAoY6G-DgJJp7nh.js 2.78 kB +out/renderer/assets/railroadDiagram-O6MQD6OU-DqFNIv2D.js 2.78 kB +out/renderer/assets/diff-lAxbRYdS--5gtlmD4.js 2.79 kB +out/renderer/assets/hy-BKymZdC0-4uNvYh3y.js 2.86 kB +out/renderer/assets/dockerfile-CnkhFuxG-CfXHMZr-.js 3.01 kB +out/renderer/assets/openscad-BRTETpP_-BThzc9qL.js 3.03 kB +out/renderer/assets/pascaligo-DI1dd1Zd-D23AoFdQ.js 3.03 kB +out/renderer/assets/log-Cn1ZE6kb-BE4srnlV.js 3.05 kB +out/renderer/assets/objective-c-gNYZndaF-4hkcNMcE.js 3.06 kB +out/renderer/assets/sparql-DxWbGozt-B7qTmycl.js 3.08 kB +out/renderer/assets/prism-markup-templating-D4pSJIpH.js 3.11 kB +out/renderer/assets/prism-cpp-CEgmwlDT.js 3.11 kB +out/renderer/assets/cameligo-B6LDhzzR-DSNRk43W.js 3.12 kB +out/renderer/assets/wenyan-BVgiL1tD-C7ph_xMt.js 3.12 kB +out/renderer/assets/cairo-D_LzMZ4I-C21twps2.js 3.17 kB +out/renderer/assets/prism-rust-Du0Qa8GC.js 3.18 kB +out/renderer/assets/lua-CJt09SGy-3O0VAMVx.js 3.19 kB +out/renderer/assets/graphql-C0cKWTiE-BQOKksLE.js 3.20 kB +out/renderer/assets/berry-DTcSbIs7-DsDdtWdB.js 3.20 kB +out/renderer/assets/jsonl-Cn_fzNA8-cIG9lf61.js 3.21 kB +out/renderer/assets/json-CKKhFIOr-DuiQFrCF.js 3.29 kB +out/renderer/assets/mips-Df5bwPtM-DJn7b529.js 3.29 kB +out/renderer/assets/jsonc-Bf3Xcgeq-BGBJ2TDY.js 3.31 kB +out/renderer/assets/logo-BxqPaaID-DK9gUnx4.js 3.33 kB +out/renderer/assets/abnfDiagram-VCTEODGH-BcjOgNTo.js 3.36 kB +out/renderer/assets/go-BejFoqvR-BnGoIlsY.js 3.42 kB +out/renderer/assets/po-DI6EG-tz-DIkePE8T.js 3.44 kB +out/renderer/assets/lexon-5NyrCfQ6-B1bdOCGH.js 3.45 kB +out/renderer/assets/prism-sql-BggiY1Ht.js 3.45 kB +out/renderer/assets/json5-BlijqrwT-Ci88mndw.js 3.45 kB +out/renderer/assets/mipsasm-U3SQfJCQ-kat_Vj1M.js 3.46 kB +out/renderer/assets/sophia-foSZ3xPI-DGYIHURw.js 3.47 kB +out/renderer/assets/tasl-C74Cvwdf-se1Ptgso.js 3.49 kB +out/renderer/assets/genie-CjS3m_gh-DHydh9_z.js 3.56 kB +out/renderer/assets/prism-swift-xplGsQ1n.js 3.56 kB +out/renderer/assets/vala-DMgevQbf-ByJQiTkp.js 3.57 kB +out/renderer/assets/pegDiagram-XKGWAZYB-C8lDnYYb.js 3.59 kB +out/renderer/assets/rel-D6dNeDZv-CUAJzmkw.js 3.60 kB +out/renderer/assets/prism-java-6uFEGwWz.js 3.63 kB +out/renderer/assets/fsharp-Ba-cvOiG-BoxQhS9v.js 3.64 kB +out/renderer/assets/chunk-P2QGCYS3-HlyjybPv.js 3.65 kB +out/renderer/assets/ebnfDiagram-PWID7BFC-CcIdRN64.js 3.66 kB +out/renderer/assets/qsharp-78iLGMHs-Dbh3PRIx.js 3.68 kB +out/renderer/assets/m3-Bu81_nWr-4t51Qx0i.js 3.69 kB +out/renderer/assets/chunk-F27PBJKO-CSIxpenx.js 3.70 kB +out/renderer/assets/pascal-DyPgZbsX-Ba58YM7a.js 3.71 kB +out/renderer/assets/path-CSWwviF2.js 3.79 kB +out/renderer/assets/fluent-BSSEgVQa-BCOQigl1.js 3.81 kB +out/renderer/assets/splunk-BdqSfgpd-BtOEh0Mo.js 3.81 kB +out/renderer/assets/jsonnet-Bn71vRY8-QjPNMWdY.js 3.82 kB +out/renderer/assets/ssh-config-BO51LXox-DkFt_ueS.js 3.82 kB +out/renderer/assets/bicep-DujF3y-4-DHww3ZLF.js 3.87 kB +out/renderer/assets/narrat-DdgkgBr0-CSyxDqta.js 3.87 kB +out/renderer/assets/redis-Bo427DT4-DBDF4ZWx.js 3.88 kB +out/renderer/assets/turtle-DAmmiOda-C48PN72o.js 3.92 kB +out/renderer/assets/dist-CE9GMTNb.js 3.97 kB +out/renderer/assets/prism-jsx-BO0yI1A3.js 3.97 kB +out/renderer/assets/xml-BBFzlEmT-CqLnJtYa.js 3.99 kB +out/renderer/assets/java-Z7anYNQ6-DdC7WVZS.js 4.01 kB +out/renderer/assets/r-Xh-gXEK4-DKEPC8dA.js 4.02 kB +out/renderer/assets/ron-CdysqNkW-BG7UwPdX.js 4.11 kB +out/renderer/assets/zenscript-XbBI4c9W-C-aTQo6e.js 4.12 kB +out/renderer/assets/glsl-CZF-bvQV-UaBdSZy0.js 4.14 kB +out/renderer/assets/shell-DGp7WuK3-X00pamiI.js 4.15 kB +out/renderer/assets/gn-DJxfXStl-BD_k0CWf.js 4.20 kB +out/renderer/assets/kotlin-C61BvWgT-B7MkJpdU.js 4.20 kB +out/renderer/assets/typespec-B704GmX3-f1l-QmOw.js 4.26 kB +out/renderer/assets/kdl-YTd72GVl-DLkP_pAB.js 4.27 kB +out/renderer/assets/AppearanceSettingsPanel-B_352Jrg.js 4.28 kB +out/renderer/assets/hurl-CDXCvJNd-Xd5k76nE.js 4.28 kB +out/renderer/assets/cypher-CjfQI0Y9-9gjOyi6P.js 4.33 kB +out/renderer/assets/pascal-CLPA94yO-C11lM2uy.js 4.35 kB +out/renderer/assets/powershell-CaPzBwIT-C9KgMPOP.js 4.50 kB +out/renderer/assets/tcl-D-NiFh9X-CYwv4uzi.js 4.63 kB +out/renderer/assets/apex-BE-040ts-wdfiR7V6.js 4.65 kB +out/renderer/assets/tcl-DowxIvU4-Bbhzqrsw.js 4.65 kB +out/renderer/assets/rosmsg-DDyuMVTo-DSHWRdSZ.js 4.72 kB +out/renderer/assets/nextflow-DVTlkzu9-Cis-JUmb.js 4.75 kB +out/renderer/assets/http-DhxVjYFh-CjwVOaui.js 4.76 kB +out/renderer/assets/hcl-CbjaVS9i-DCS43mBd.js 4.79 kB +out/renderer/assets/rust-Ij2gfGoT-DLzaBWYs.js 4.83 kB +out/renderer/assets/polar-CwTxzzWE-DygHL4ZA.js 4.87 kB +out/renderer/assets/prism-ruby-PgHh3fQm.js 4.91 kB +out/renderer/assets/fennel-COJTUo2O-DYh8-dep.js 4.97 kB +out/renderer/assets/bibtex-yEKRWsaj-xHthw1sC.js 5.00 kB +out/renderer/assets/coffee-CcgZJF1B-DkN4xoBX.js 5.04 kB +out/renderer/assets/llvm-DiFwU398-BQjCVu39.js 5.25 kB +out/renderer/assets/less-CXux59mP-BM7SkPLH.js 5.27 kB +out/renderer/assets/msdax-DEyWhkWP-CwdIr_-P.js 5.29 kB +out/renderer/assets/prism-javascript-B6zosBCV.js 5.31 kB +out/renderer/assets/wgsl-Ds7VVNHP-yP3bMkfO.js 5.34 kB +out/renderer/assets/markdown-CBag5COD-B_1rbk64.js 5.36 kB +out/renderer/assets/dart-DK8_VUW5-Bnb_Tn57.js 5.39 kB +out/renderer/assets/zig-BBWfbOQ5-B8x_JL1P.js 5.54 kB +out/renderer/assets/restructuredtext-D2p7PcFG-DDHAm_JI.js 5.55 kB +out/renderer/assets/dax-CmrIxjmL-CDTyHmZ_.js 5.56 kB +out/renderer/assets/gdresource-4lq4eh4q-CjhvlVte.js 5.56 kB +out/renderer/assets/qml-D6gd64uC-_ykXVPoZ.js 5.57 kB +out/renderer/assets/bicep-wTwvD1CI-C568hcwN.js 5.58 kB +out/renderer/assets/cssMode-Z-o80aSY-Crw7T5pi.js 5.59 kB +out/renderer/assets/awk-DTjcVAOD-BmfaVU4m.js 5.66 kB +out/renderer/assets/liquid-Dv-zz5BA-D9ukCDuL.js 5.71 kB +out/renderer/assets/csharp-DpS7Vfy9-CbQzv1ql.js 5.76 kB +out/renderer/assets/coq-BFytDJOI-C5vNmx0q.js 5.81 kB +out/renderer/assets/swift-C3A42nmX-BBVToPkN.js 5.83 kB +out/renderer/assets/xml-bIkPj5aH-Bx1v5u6-.js 5.89 kB +out/renderer/assets/ecl-CYzojQ6a-C8m0_osY.js 5.91 kB +out/renderer/assets/jinja-Dl-Ji_JA-BBL5sTd0.js 5.92 kB +out/renderer/assets/lean-Cu10prRO-BUTVAAdc.js 6.03 kB +out/renderer/assets/yaml-GEMDST6R-D-0AGe4F.js 6.09 kB +out/renderer/assets/moonbit-B8-g2u5v-CGBFUznC.js 6.10 kB +out/renderer/assets/powerquery-tKWDTKOo-CejxekA_.js 6.11 kB +out/renderer/assets/SourceCodePreview-Czir01Qu.js 6.11 kB +out/renderer/assets/python-CHafhQyI-DmJIfgbV.js 6.14 kB +out/renderer/assets/shaderlab-Df7nOKvI-0G488FSx.js 6.16 kB +out/renderer/assets/css-sG8ozMHf-pZGexMoj.js 6.17 kB +out/renderer/assets/cpp-CipCPBaT-7uQRIwsC.js 6.17 kB +out/renderer/assets/vb-BKV3Sgm5-D5ytx6Ln.js 6.29 kB +out/renderer/assets/htmlMode-BDZbYlMj-2xcr-6-m.js 6.40 kB +out/renderer/assets/red-CYaKK_PD-iiAMl8iL.js 6.45 kB +out/renderer/assets/min-dark-DGPfDRqJ-gZu6HtcU.js 6.48 kB +out/renderer/assets/pug-EKWpNZSi-oQ708bsr.js 6.51 kB +out/renderer/assets/prisma-CdZyz3OC-ChFCtYaa.js 6.53 kB +out/renderer/assets/gdshader-ryZhEIxg-DpcQqwXn.js 6.55 kB +out/renderer/assets/ara-_lrJyEFe-qigo-wGx.js 6.56 kB +out/renderer/assets/clojure-WSq30mUj-Bswhoa1y.js 6.61 kB +out/renderer/assets/toml-DPP887_3-aOuHoLTy.js 6.62 kB +out/renderer/assets/postcss-CcIp2ENG-DpmxBCXW.js 6.64 kB +out/renderer/assets/verilog-bragEGMk-CemzLugw.js 6.64 kB +out/renderer/assets/solarized-light-BIMszn7B-vPMkTTwP.js 6.68 kB +out/renderer/assets/cypher-COYrq2Yy-BtVrfsLp.js 6.75 kB +out/renderer/assets/arc-LpCwTDer.js 6.75 kB +out/renderer/assets/proto-CQIfhs_g-Deqofbl3.js 6.77 kB +out/renderer/assets/smalltalk-BLGdLDJX-BKGgemER.js 6.79 kB +out/renderer/assets/vb-D1Cw85Ss-BSz-V9M4.js 6.86 kB +out/renderer/assets/talonscript-DA9pg7Tj-CPXKQ95R.js 6.96 kB +out/renderer/assets/r-Bb2Mu7Fo-Dq0URONw.js 7.00 kB +out/renderer/assets/solarized-dark-D_I-4EGa-BZbeAUhW.js 7.04 kB +out/renderer/assets/diagram-Z3DM3KII-CRFA9WLO.js 7.08 kB +out/renderer/assets/riscv-CQHqXr1Z-BFlZFId-.js 7.11 kB +out/renderer/assets/soy-DybHqX1A-DOhErZPj.js 7.15 kB +out/renderer/assets/min-light-BF0EjVgr-DvViuJW_.js 7.16 kB +out/renderer/assets/scheme-Dn0tgEWN-BK64z0tZ.js 7.37 kB +out/renderer/assets/prism-bash-B2ETaHUm.js 7.43 kB +out/renderer/assets/typescript-sfPIqb8J-DtIl1kXb.js 7.44 kB +out/renderer/assets/hlsl-CAmjcFpk-B3FZWMVz.js 7.48 kB +out/renderer/assets/mdx-Bdu4uO-C-BrzgNjCw.js 7.58 kB +out/renderer/assets/qss-DkzwWM0J-04JPp7d-.js 7.67 kB +out/renderer/assets/html-DKbmsqz6-Cnkf6ew3.js 7.69 kB +out/renderer/assets/systemd-CS6mVasZ-HbzlQlDs.js 8.07 kB +out/renderer/assets/monokai-CYqILLdj-CEXuJ8HO.js 8.08 kB +out/renderer/assets/twig-r8vgPZrm-D2l24YwI.js 8.18 kB +out/renderer/assets/updates-ui-BoiWSsup.js 8.22 kB +out/renderer/assets/wgsl-D_5Qxf6T-D508aVGZ.js 8.27 kB +out/renderer/assets/sdbl-BXfz6d3_-C4Qk7OPN.js 8.42 kB +out/renderer/assets/regexp-Dv0OUts_-BqK6b4KR.js 8.46 kB +out/renderer/assets/prism-php-dzcOOH50.js 8.49 kB +out/renderer/assets/systemverilog-BreNGkRs-RIXr4hNf.js 8.65 kB +out/renderer/assets/plsql-C-xpsZfV-frBdohcC.js 8.71 kB +out/renderer/assets/vue-html-DvuHo2mm-b7I-opwf.js 8.71 kB +out/renderer/assets/haml-CIYwkycC-3fSMp7m2.js 8.81 kB +out/renderer/assets/scss-CLoW-2dr-BBC_GO_6.js 8.86 kB +out/renderer/assets/dart-CBkkDIWs-ezKLFP5s.js 8.94 kB +out/renderer/assets/horizon-CELVL8Ba-x0NmpRb6.js 8.97 kB +out/renderer/assets/horizon-bright-DBDyMeUQ-Bhh-QDk3.js 8.98 kB +out/renderer/assets/julia-DvNkK6LK-Bi3Rlfah.js 9.04 kB +out/renderer/assets/clojure-886L7m2N-BhGJsUM7.js 9.14 kB +out/renderer/assets/make-CsAfL-jc-DaQVAww0.js 9.18 kB +out/renderer/assets/andromeeda--j5Bq-48-DxyWS_fJ.js 9.21 kB +out/renderer/assets/dark-plus-FAPM6M6c-DKexDF--.js 9.29 kB +out/renderer/assets/sas-BQIEUTPQ-Bwx-ZPYU.js 9.31 kB +out/renderer/assets/slack-dark-nDxLkSCC-C5pzIEPN.js 9.31 kB +out/renderer/assets/perl-Bec3eWyr-CDmSu3_s.js 9.32 kB +out/renderer/assets/plastic-DY_h9Vzh-CZzPFkTC.js 9.49 kB +out/renderer/assets/sass-Ysv8HTNa-CHNQIGaT.js 9.49 kB +out/renderer/assets/st-BrgXZ-Ag-BUs-RRgp.js 9.58 kB +out/renderer/assets/typst-Co5rZla4-COemceoz.js 9.61 kB +out/renderer/assets/slack-ochin-7zJWY-K--C7KFpXik.js 9.63 kB +out/renderer/assets/defaultLocale-QNqK0iCN.js 9.84 kB +out/renderer/assets/handlebars-CIJAyfa9-6toBlNYk.js 9.94 kB +out/renderer/assets/jison-Cbw0l5It-BNek_9Kq.js 9.95 kB +out/renderer/assets/sql-DviNlDJO-CwV6bDIP.js 9.97 kB +out/renderer/assets/kotlin-DIw6ua6F-CdVnL0aF.js 10.01 kB +out/renderer/assets/cmake-CyNDuJo8-2Hk4zQCd.js 10.07 kB +out/renderer/assets/light-plus-DkScKIB5-e8Q5AKjf.js 10.14 kB +out/renderer/assets/hcl-DoJdlYjN-DdpM5wFm.js 10.25 kB +out/renderer/assets/scala-Dj45wWzI-CAMCqIXS.js 10.40 kB +out/renderer/assets/postiats-SaHD9Qcv-FPvOr1pn.js 10.45 kB +out/renderer/assets/beancount-CyZf3Huc-C4n-y8pc.js 10.58 kB +out/renderer/assets/tex-gcnXexI3-BUpeblVA.js 10.60 kB +out/renderer/assets/php-Bn8AF0uj-CBbpr2vs.js 10.62 kB +out/renderer/assets/nextflow-groovy-D4ZyOBoZ-C7jziUwg.js 10.63 kB +out/renderer/assets/dream-maker-5oXa1Z51-CLRrQkBL.js 10.67 kB +out/renderer/assets/ts-tags-xeTAUNHG-CG_gr3En.js 10.70 kB +out/renderer/assets/raku-Bfr41qeN-C7t9XlCj.js 10.72 kB +out/renderer/assets/mysql-CZJtil0v-CP4gK9vT.js 10.73 kB +out/renderer/assets/task-menu-icons-BRdNqJF0.js 10.78 kB +out/renderer/assets/prism-csharp-D9xOwbIN.js 10.91 kB +out/renderer/assets/yaml-CsitfczK-Cu7vbJZs.js 10.97 kB +out/renderer/assets/diagram-UQ7AKVKN-BXObzj4d.js 11.05 kB +out/renderer/assets/elm-Dl1XrIiD-CwXBAFKd.js 11.18 kB +out/renderer/assets/just-He7qscmV-Bkq-0zku.js 11.19 kB +out/renderer/assets/redshift-Djb4PK3z-9Ar4PFWD.js 11.35 kB +out/renderer/assets/github-light-B_J7N1HZ-DWSXFnsf.js 11.38 kB +out/renderer/assets/ruby-CxOCB7_P-BzsjPJ6Z.js 11.48 kB +out/renderer/assets/prolog-DAqMMM08-BFKdnH0S.js 11.56 kB +out/renderer/assets/terraform-BW8B2WXV-zeRjs0zr.js 11.59 kB +out/renderer/assets/github-dark-BgqEY2WG-C9QbkZU3.js 11.60 kB +out/renderer/assets/puppet-CaR8DEdW-Biai9WKX.js 11.65 kB +out/renderer/assets/pkl-DrXR3Dxy-Bno7kqPT.js 11.67 kB +out/renderer/assets/laserwave-Clkc4Pj8-DOjuqF9n.js 11.69 kB +out/renderer/assets/pieDiagram-E7YTZNPT-D3EPLKnW.js 11.95 kB +out/renderer/assets/rst-BJFdabDk-Cv-fSo2B.js 12.04 kB +out/renderer/assets/linear-WS155L0r.js 12.11 kB +out/renderer/assets/wasm-DYwNZ-r4-BrA6oOvM.js 12.21 kB +out/renderer/assets/hjson-CmvCiVhY-BdH9CbZ2.js 12.25 kB +out/renderer/assets/razor-D5kquflS-CWY5AfCS.js 12.39 kB +out/renderer/assets/abap-BJyKdrbp-hWIyERPx.js 12.52 kB +out/renderer/assets/handlebars-B1z64YSt-MC-VEvxc.js 12.52 kB +out/renderer/assets/apache-BUbWdjM2-2Zu7IlVl.js 12.66 kB +out/renderer/assets/vesper-B5lCMuIY-CXGQHRuW.js 12.88 kB +out/renderer/assets/pgsql-BYm17UA1-Cvj1smQI.js 12.93 kB +out/renderer/assets/protobuf-BOGxqb2m-yTWn-oM_.js 12.98 kB +out/renderer/assets/bat-D2y8Uewi-CEJzP2ue.js 13.09 kB +out/renderer/assets/fish-CaZR_ofm-BcO_q5kQ.js 13.24 kB +out/renderer/assets/elixir-Lipcswxh-DnZCznfr.js 13.27 kB +out/renderer/assets/v-wnWoBHkK-CzCOTyIp.js 13.41 kB +out/renderer/assets/AboutHelpSettingsPanel-Ui_VOvh7.js 13.48 kB +out/renderer/assets/vitesse-light-DQXFiRFx-Ct7fN8pJ.js 13.81 kB +out/renderer/assets/aurora-x-9vUYYjHV-CImifmUW.js 13.85 kB +out/renderer/assets/vitesse-black-cwK5rWgD-BGrq81WC.js 13.87 kB +out/renderer/assets/vitesse-dark-CsfgW0oH-Dx8cqxrm.js 13.96 kB +out/renderer/assets/ShortcutsSettingsPanel-KgJeI7QZ.js 14.15 kB +out/renderer/assets/pug-D0UckVoV-BTWU19Nk.js 14.16 kB +out/renderer/assets/synthwave-84-LX1B8mRG-yuUErnSx.js 14.23 kB +out/renderer/assets/github-light-default-BRmIzqWc-B3gMi7zW.js 14.36 kB +out/renderer/assets/clarity-AxkJPY5c-DfVHSVIk.js 14.48 kB +out/renderer/assets/github-light-high-contrast-BUKIZOxn-DL0r2b0z.js 14.49 kB +out/renderer/assets/github-dark-dimmed-DoIdqTey-CDc6YqEM.js 14.64 kB +out/renderer/assets/github-dark-default-CwWjzI40-_0bgyJYv.js 14.64 kB +out/renderer/assets/chunk-PWAF6VOD-DuIRO4kt.js 14.76 kB +out/renderer/assets/github-dark-high-contrast-bFLNMLvK-BUp3HmXY.js 14.80 kB +out/renderer/assets/diagram-S7CK7UJ4-DV_ERwD-.js 14.98 kB +out/renderer/assets/gnuplot-Dw3FRha5-D6o75ylb.js 14.98 kB +out/renderer/assets/rust-C0Ih6nmc-Bm01RMLz.js 15.27 kB +out/renderer/assets/actionscript-3-O8jnLcvn-C7OtofMN.js 15.41 kB +out/renderer/assets/luau-BzxGbjcn-aQpsBeQB.js 15.64 kB +out/renderer/assets/nix-zl191KBb-CxSq6jsB.js 15.85 kB +out/renderer/assets/lua-BwTLfNCK-IuSxl8fO.js 16.04 kB +out/renderer/assets/abap-FvPUHv8B-BVQp86jh.js 16.05 kB +out/renderer/assets/solidity-96fhzG-Q-CZEni-ZB.js 16.28 kB +out/renderer/assets/matlab-8ZQqHKQX-g_ODc8QU.js 16.29 kB +out/renderer/assets/cue-eHSfcyUV-BO0bCEDm.js 16.40 kB +out/renderer/assets/kusto-D8vBBISG-C0y2Wtyy.js 16.45 kB +out/renderer/assets/powerquery-B7BjLMcF-BkVSWPtX.js 16.49 kB +out/renderer/assets/elixir-B1NaQxrO-Ba6X-FuW.js 16.50 kB +out/renderer/assets/react-DrereneL.js 16.50 kB +out/renderer/assets/odin-B-YqhW9I-B-ZI05Ll.js 16.71 kB +out/renderer/assets/solidity-Dpt2BLAA-BD_YSA0r.js 16.98 kB +out/renderer/assets/bird2-BMkLvc4r-CyoW3El7.js 17.17 kB +out/renderer/assets/kanagawa-wave-CM_o6oKV-VzWuxPSA.js 17.32 kB +out/renderer/assets/kanagawa-lotus-Cj3XDpoG-cmeMwVaD.js 17.32 kB +out/renderer/assets/kanagawa-dragon-D_NPnIy_-Cyd8MANv.js 17.33 kB +out/renderer/assets/cynefinDiagram-5FMLGOSQ-4X_-lqaW.js 17.61 kB +out/renderer/assets/stateDiagram-D77RDMKH-B5Qv9-kY.js 18.11 kB +out/renderer/assets/chunk-L3NEJ4N5-MEgGvnk-.js 18.16 kB +out/renderer/assets/liquid-D_7zu7XR-BZ3z6-Mj.js 18.46 kB +out/renderer/assets/svelte-DUGqPubT-CAfIEh4G.js 18.60 kB +out/renderer/assets/graphql-ObxcfEHH-9pUo2yjR.js 18.65 kB +out/renderer/assets/jsonMode-DdQpkp6D-Bsga_9WC.js 18.79 kB +out/renderer/assets/material-theme-q28j4V_0-s4HtqlFv.js 18.81 kB +out/renderer/assets/material-theme-ocean-DAvlEnSm-Cyw7qD-l.js 18.83 kB +out/renderer/assets/material-theme-darker-CHEuMVX9-D-hz3EEt.js 18.83 kB +out/renderer/assets/material-theme-lighter-DY4T1_JG-C0HwKluR.js 18.84 kB +out/renderer/assets/material-theme-palenight-CqDFvQ-v-RoTowTME.js 18.84 kB +out/renderer/assets/gherkin-BcjDDslM-BdnbjalD.js 19.20 kB +out/renderer/assets/gdscript-CekKc1U_-DVmAmHvE.js 19.21 kB +out/renderer/assets/groovy-DH3arekX-StnUgJL0.js 19.38 kB +out/renderer/assets/mdc-D-U85KZE-DPbAVRTg.js 19.85 kB +out/renderer/assets/diagram-VSXAHHWV-BjMahNBE.js 20.01 kB +out/renderer/assets/move-CmExnPjU-DPj_eIaE.js 20.22 kB +out/renderer/assets/ayu-dark-BeByMiYw-CS3MEELg.js 20.27 kB +out/renderer/assets/ayu-mirage-C1jJ6Jfs-CnA8kJ7r.js 20.28 kB +out/renderer/assets/ayu-light-DmTZeN54-CDULCKqM.js 20.35 kB +out/renderer/assets/glimmer-js-D9ZnrcNN-BS431Ogg.js 20.44 kB +out/renderer/assets/glimmer-ts-DuhFj6qR-CsFesiaT.js 20.44 kB +out/renderer/assets/viml-DPVJ_KYe-De3CdqgJ.js 20.56 kB +out/renderer/assets/nushell-Cd8Dwa1M-Dhf9XkYz.js 20.62 kB +out/renderer/assets/snazzy-light-B8znOqT6-B1FX3-IF.js 20.97 kB +out/renderer/assets/dagre-GXQ25YYZ-DHWBBxAd.js 21.01 kB +out/renderer/assets/dracula-DeMffiYO-Bl4juROY.js 21.26 kB +out/renderer/assets/dracula-soft-BnfvpcDv-CYsUeSum.js 21.27 kB +out/renderer/assets/twig-7zjsCqYg-CMujKsZl.js 21.44 kB +out/renderer/assets/freemarker2-enkimFXA-0bWMkoTL.js 21.73 kB +out/renderer/assets/PersonalizationSettingsPanel-B06BA6F_.js 21.87 kB +out/renderer/assets/rose-pine-CEVQiaW0-DaA_4NNK.js 21.94 kB +out/renderer/assets/rose-pine-moon-B9bum7Ik-B6_AhIsD.js 21.96 kB +out/renderer/assets/rose-pine-dawn-2Q5fMoJp-DxMkAwKM.js 21.96 kB +out/renderer/assets/powershell-ycAdP1r9-B7r4Hnhz.js 22.11 kB +out/renderer/assets/common-lisp-DcFHcTKh-CWH5diwh.js 22.81 kB +out/renderer/assets/gruvbox-dark-hard-gOzMLqif-DDlcfu4q.js 22.83 kB +out/renderer/assets/gruvbox-dark-soft-CKvURktN-C6MJezBg.js 22.83 kB +out/renderer/assets/gruvbox-light-hard-CMa_c48J-BUQ67Msp.js 22.84 kB +out/renderer/assets/gruvbox-light-soft-yfAGJYsX-DNM2qqWB.js 22.84 kB +out/renderer/assets/gruvbox-dark-medium-BQSVGwWb-qh8C4DPZ.js 22.84 kB +out/renderer/assets/gruvbox-light-medium-B9S5UNr1-DZxV_o-P.js 22.84 kB +out/renderer/assets/nim-CD961Jl3-CuyTrDpQ.js 22.91 kB +out/renderer/assets/cadence-C2JmJjDr-B-b63Epg.js 23.87 kB +out/renderer/assets/sql-C_oMiPb0-CRnSOxMo.js 23.87 kB +out/renderer/assets/wit-CXpQol8Q-D2NEDOhy.js 24.11 kB +out/renderer/assets/templ-gFcHJbF7-BqIwRUQe.js 24.38 kB +out/renderer/assets/astro-kV3HjkbP-CH6o6jKA.js 24.46 kB +out/renderer/assets/vhdl-Ci4REirV-D-qSzcJD.js 24.46 kB +out/renderer/assets/purescript-DCsDAdnX-DsynrkKe.js 24.97 kB +out/renderer/assets/vue-Cuk7Vimg-CFbFXIr8.js 25.25 kB +out/renderer/assets/surrealql-GFjNBdcm-Vm68TOTE.js 25.34 kB +out/renderer/assets/one-light-CMfGrl_P-B-1jUQM9.js 25.49 kB +out/renderer/assets/night-owl-light-CAEa42tO-TPCLv7z5.js 26.10 kB +out/renderer/assets/system-verilog-D_bVVpLE-C_dvOlr3.js 26.41 kB +out/renderer/assets/angular-html-BrLPO2Fv-DJgz5E5d.js 26.48 kB +out/renderer/assets/typespec-D5WYs8C4-AaOHagqW.js 26.72 kB +out/renderer/assets/nord-DlCAGdjr-Div2jUYm.js 26.91 kB +out/renderer/assets/codeql-DidIlXer-D6RBJOzg.js 27.08 kB +out/renderer/assets/scss-BhK8Ovpn-DfDLQi2C.js 27.52 kB +out/renderer/assets/coffee-DrMWXxy6-BoavQsuh.js 27.68 kB +out/renderer/assets/java-DaupjRFz-zQd9RZAc.js 27.69 kB +out/renderer/assets/razor-B2hRAVmz-Dj7TOgY5.js 27.72 kB +out/renderer/assets/apl-C42PBett-BNW4FTmO.js 27.87 kB +out/renderer/assets/chunk-SVP7TREG-Dxm-4rnd.js 28.38 kB +out/renderer/assets/fsharp-BHFgIxsY-CvR6tsY8.js 28.48 kB +out/renderer/assets/marko-DXKHPFnH-C0z2-ucz.js 28.74 kB +out/renderer/assets/GeneralSettingsPanel-CA6yOnsk.js 29.10 kB +out/renderer/assets/night-owl-DegwdXaM-6ZGfBB7K.js 29.11 kB +out/renderer/assets/c3-BOs4FlGA-BuhFXrRY.js 29.17 kB +out/renderer/assets/MemorySettingsPanel-cqwWfj-O.js 29.75 kB +out/renderer/assets/crystal-DlzoxO28-BWa_t1Io.js 29.84 kB +out/renderer/assets/applescript-ij24h7OO-_xHQcvud.js 29.87 kB +out/renderer/assets/tsMode-SiG-Sp2b-WC-zK_wx.js 30.55 kB +out/renderer/assets/pierre-dark-Daa2n9wr-D7rla9B_.js 30.74 kB +out/renderer/assets/pierre-light-D_hZXvUj-DJnIOKLO.js 30.75 kB +out/renderer/assets/pierre-dark-soft-BhNM3pgh-Dp_VeHWv.js 30.76 kB +out/renderer/assets/pierre-light-soft-BVrSv6ZG-C6Na39F-.js 30.76 kB +out/renderer/assets/ishikawaDiagram-5VMMS53U-BtIQYepA.js 30.78 kB +out/renderer/assets/pierre-dark-tritanopia-CGKuoAZi-C0HpbU3l.js 30.78 kB +out/renderer/assets/pierre-light-tritanopia-BiDEaWaH-wWduIsi3.js 30.78 kB +out/renderer/assets/pierre-dark-protanopia-deuteranopia-Cs1lz9lE-enlgPsHw.js 30.82 kB +out/renderer/assets/pierre-light-protanopia-deuteranopia-BM0RLBB_-Dz5iBHkO.js 30.82 kB +out/renderer/assets/stylus-ZCryC73G-urFW3_yk.js 31.29 kB +out/renderer/assets/diagram-VX7I27RA-CAJ5TuHp.js 31.44 kB +out/renderer/assets/scala-BBsC3Oz3-VCjyobQG.js 31.48 kB +out/renderer/assets/mermaid-D6CQfUGU-C6DHNxVz.js 33.37 kB +out/renderer/assets/poimandres-EIt_jotH-DHKFQj5Q.js 33.69 kB +out/renderer/assets/kanban-definition-UXKFOSKX-BLcNSZUB.js 33.91 kB +out/renderer/assets/one-dark-pro-DR9QpZM3-BA4d4lw2.js 33.98 kB +out/renderer/assets/mermaid-parser.core-CstzWfPU.js 34.66 kB +out/renderer/assets/haxe-BWT5wSyZ-BuUsQb-h.js 35.38 kB +out/renderer/assets/nginx-DhtViCEk-C18zABFg.js 35.58 kB +out/renderer/assets/houston-BdS5A_yD-NUige_z1.js 35.61 kB +out/renderer/assets/tokyo-night-BS1_DFu7-CYsPn2J-.js 35.86 kB +out/renderer/assets/erlang-Dd62d0xZ-DHVWwcKa.js 37.71 kB +out/renderer/assets/rough.esm-BX5QqLti.js 38.33 kB +out/renderer/assets/mindmap-definition-YA3MSWOX-B-zior9K.js 38.59 kB +out/renderer/assets/cobol-D7RZfOK--CEk2iYO9.js 39.37 kB +out/renderer/assets/journeyDiagram-3NMN7TZE-dygzCaXh.js 40.13 kB +out/renderer/assets/julia-ZzkUXm0W-BIm_zTAN.js 40.32 kB +out/renderer/assets/lspLanguageFeatures-DK9zifhE-DeEqLmGO.js 40.76 kB +out/renderer/assets/asm-DYVIzeEk-Byg5xzam.js 40.91 kB +out/renderer/assets/haskell-Ba6HbLj8-D0OYaIy8.js 41.78 kB +out/renderer/assets/sankeyDiagram-P5KCCOFB-D1WB71c9.js 41.83 kB +out/renderer/assets/shellscript-B69gKcss-49Zm6IyC.js 41.97 kB +out/renderer/assets/wardleyDiagram-VM6X3IG4-DCbKgC_S.js 42.40 kB +out/renderer/assets/perl-Dv6Cq_FS-DIORmO5G.js 43.55 kB +out/renderer/assets/pierre-dark-vibrant-BMsyYliQ-84Eeh-Uj.js 44.96 kB +out/renderer/assets/pierre-light-vibrant-CWzM4Pa_-QZvTkTJe.js 44.97 kB +out/renderer/assets/ruby-DWcdJvcx-q0K84ieK.js 46.50 kB +out/renderer/assets/go-BOpYl7fu-BiT4MB-v.js 47.02 kB +out/renderer/assets/apex-B48ZHHzN-BBt8sSNQ.js 47.18 kB +out/renderer/assets/catppuccin-mocha-cPsH7Lup-SVLZehhk.js 47.46 kB +out/renderer/assets/catppuccin-latte-DcEecI7n-jo2cPJyK.js 47.46 kB +out/renderer/assets/catppuccin-frappe-BdOW2tdI-BI0Hc9cS.js 47.46 kB +out/renderer/assets/catppuccin-macchiato-Bvz_yAZY-DWewRa4S.js 47.47 kB +out/renderer/assets/ada-BT0j8ine-CLTLBE8n.js 48.28 kB +out/renderer/assets/d-B1HbH29p-Bi6t8Ck6.js 49.10 kB +out/renderer/assets/css-NFwnoVns-BvwuZkcY.js 49.49 kB +out/renderer/assets/imba-C-oGt11l-CqKI0OVw.js 50.13 kB +out/renderer/assets/requirementDiagram-BXWQKSXE-C3ERdAvT.js 51.39 kB +out/renderer/assets/erDiagram-RLTQ6QDP-DVzk9HUA.js 52.41 kB +out/renderer/assets/browserify-C9uP_nIr.js 52.80 kB +out/renderer/assets/gitGraphDiagram-WWUBYQGX-gZr6P8x8.js 53.82 kB +out/renderer/assets/everforest-dark-gCM8XhEI-DzRrg06U.js 53.94 kB +out/renderer/assets/everforest-light-DhK35DkL-BEDtvHw1.js 53.95 kB +out/renderer/assets/timeline-definition-24CTP7MA-DuvjToaj.js 54.31 kB +out/renderer/assets/wikitext-CQNrXTmv-DJ18wIlO.js 56.09 kB +out/renderer/assets/stata-BUONSdsT-BPnapjPC.js 57.23 kB +out/renderer/assets/quadrantDiagram-AXDQQJYC-D8rBdZOq.js 58.21 kB +out/renderer/assets/html-Dq1ixqYb-okJOhOmu.js 58.25 kB +out/renderer/assets/chunk-OSK3NFVY-DeXYmBeV.js 58.56 kB +out/renderer/assets/ocaml-CUdGm1iq-BKX30YEX.js 62.65 kB +out/renderer/assets/model-settings-source-JYisGYmM.js 63.03 kB +out/renderer/assets/ballerina-CpYcPBJI-D9ac3462.js 64.89 kB +out/renderer/assets/markdown-BSrOIEaF-BFwOzGIM.js 65.52 kB +out/renderer/assets/chunk-IMKFNOWR-20hk4CFt.js 67.22 kB +out/renderer/assets/mojo-BNaitZ-7-E_psDM2x.js 70.00 kB +out/renderer/assets/python-Cld0Iwtn-tcCJ5L_g.js 70.17 kB +out/renderer/assets/blockDiagram-I7D4REHJ-BEOA2O5R.js 71.01 kB +out/renderer/assets/bsl-CtP8370o-Pi14XlIU.js 71.07 kB +out/renderer/assets/c-B4augMcT-B5ncIjy5.js 72.57 kB +out/renderer/assets/chunk-75Z2AOVW-D7MfFP0x.js 72.67 kB +out/renderer/assets/latex-g2Pus_l2-CP0G7LTN.js 72.85 kB +out/renderer/assets/vyper-C1nscAY5-BTAKd5p2.js 74.85 kB +out/renderer/assets/ModelSettingsPanel-Bq69xf7M.js 76.64 kB +out/renderer/assets/xychartDiagram-S5SC5T6Z-BLJZsQxl.js 76.79 kB +out/renderer/assets/chunk-GMAD6QVW-Cutm-G6X.js 77.76 kB +out/renderer/assets/hack-B1ag3l4X-CEYIfPfg.js 80.58 kB +out/renderer/assets/src-DsgKm1PY.js 83.16 kB +out/renderer/assets/chunk-TICWLB2K-BF9Dr4eB.js 83.88 kB +out/renderer/assets/fortran-free-form-CsgtTAg3-Dm0PhuY8.js 89.20 kB +out/renderer/assets/vennDiagram-4TSXK5OY-rjTACDc3.js 89.26 kB +out/renderer/assets/csharp-YOPVljXo-CBjcozlW.js 89.91 kB +out/renderer/assets/racket--xYIV9-n-NDM2V4Sc.js 92.62 kB +out/renderer/assets/swift-CgzYrGBX-CaMD6i-j.js 94.14 kB +out/renderer/assets/less-BGhX8xko-CbSvNyvq.js 99.00 kB +out/renderer/assets/chunk-SHT3W25Y-CG3rN0Mp.js 104.10 kB +out/renderer/assets/objective-c-CmcWiAft-DY5tZuMk.js 105.62 kB +out/renderer/assets/blade-Bq8WPf0E-BehdttJf.js 105.98 kB +out/renderer/assets/c4Diagram-7LVT6UL2--i1UKJXs.js 107.96 kB +out/renderer/assets/php-X15vsN4N-ChBJUzAp.js 111.49 kB +out/renderer/assets/dagre-CzI-C3sx.js 122.98 kB +out/renderer/assets/ganttDiagram-EL5Y4UJY-B2ep6Zsp.js 123.77 kB +out/renderer/assets/graphlib-CoAzpIqe.js 127.44 kB +out/renderer/assets/asciidoc-DJWalVNM-Daa-Gl9r.js 146.30 kB +out/renderer/assets/mdx-C_Ato9sK-CDV72_N0.js 146.49 kB +out/renderer/assets/editor.main-POO0Vbhx-DgMLeBiB.js 161.32 kB +out/renderer/assets/cose-bilkent-JH36ORCC-CA60tZpq.js 165.63 kB +out/renderer/assets/objective-cpp-BggTCHV8-BRaaCyEF.js 172.18 kB +out/renderer/assets/javascript-AfZCJ9Uc-C_GZREFb.js 175.31 kB +out/renderer/assets/tsx-BOlKGefW-D7XVyutE.js 176.00 kB +out/renderer/assets/jsx-CPd9p36x-D5Ck2u9I.js 178.26 kB +out/renderer/assets/sequenceDiagram-WJ2MYXX4-DrQZvAZS.js 190.05 kB +out/renderer/assets/typescript-4sRsPriL-Ce01imBq.js 191.16 kB +out/renderer/assets/mermaid.core-CzJUxOu4.js 191.57 kB +out/renderer/assets/angular-ts-YduEkmVa-936ueej5.js 193.82 kB +out/renderer/assets/vue-vine-DXhYlaTf-C8MW7tnI.js 201.27 kB +out/renderer/assets/SourceSelect-Dd7kI5iL.js 203.20 kB +out/renderer/assets/chunk-4HAMMTFA-CZEROUgO.js 210.32 kB +out/renderer/assets/swimlanes-42K2YHIH-Bejk4_Vq.js 265.51 kB +out/renderer/assets/wolfram-BVoTES0L-W3A5YqXk.js 267.14 kB +out/renderer/assets/chunk-DU6HZSFF-BsNLw-4v.js 271.07 kB +out/renderer/assets/architectureDiagram-5GKGNRK7-BXf_ZoM6.js 318.23 kB +out/renderer/assets/katex-Y9ra-ykP.js 497.35 kB +out/renderer/assets/texmath-Bkeg3ZLn.js 594.25 kB +out/renderer/assets/wasm-CVjZL0jK-DcJkdGs4.js 622.62 kB +out/renderer/assets/cpp-9jHBA231-DB3feGjZ.js 626.73 kB +out/renderer/assets/app-4914IQSi.js 675.57 kB +out/renderer/assets/emacs-lisp-DjtOxg4j-CzQ0CKOn.js 780.06 kB +out/renderer/assets/cytoscape.esm-bVGYt-iW.js 869.69 kB +out/renderer/assets/ArtifactPierreDiff-DpqRTCz8.js 1,119.58 kB +out/renderer/assets/chunk-FOHPRMQF-BCllzKJD.js 1,154.18 kB +out/renderer/assets/index-iOggdyqw.js 3,760.13 kB +out/renderer/assets/editor.api2-dPwET-7w-BYIQ9bT3.js 4,889.23 kB + +✓ built in 4.77s diff --git a/docs/协作/evidence/B01-review-02/delete-dark.png b/docs/协作/evidence/B01-review-02/delete-dark.png new file mode 100644 index 0000000..5945463 Binary files /dev/null and b/docs/协作/evidence/B01-review-02/delete-dark.png differ diff --git a/docs/协作/evidence/B01-review-02/menu-report.json b/docs/协作/evidence/B01-review-02/menu-report.json new file mode 100644 index 0000000..2a400d9 --- /dev/null +++ b/docs/协作/evidence/B01-review-02/menu-report.json @@ -0,0 +1,769 @@ +{ + "result": "PASS", + "scope": "Real isolated YCode App/preload/IPC/native filesystem. No upstream calls. Original expectations come from fixed REA archive ev_f5e9d71a676c453daab40928acfb33aeabae68ba57ffda342380cead7f1a1fe2.", + "sourceEvidence": [ + "ev_f5e9d71a676c453daab40928acfb33aeabae68ba57ffda342380cead7f1a1fe2" + ], + "snapshots": { + "menu": { + "rect": [ + 226, + 378, + 170, + 250 + ], + "background": "rgb(255, 255, 255)", + "borderRadius": "16px", + "padding": "8px", + "items": [ + { + "label": "置顶", + "width": 152, + "height": 32, + "fontSize": "14px", + "lineHeight": "22px", + "borderRadius": "8px", + "color": "rgba(0, 0, 0, 0.9)", + "icon": [ + 16, + 16 + ] + }, + { + "label": "重命名", + "width": 152, + "height": 32, + "fontSize": "14px", + "lineHeight": "22px", + "borderRadius": "8px", + "color": "rgba(0, 0, 0, 0.9)", + "icon": [ + 16, + 16 + ] + }, + { + "label": "在独立窗口中打开", + "width": 152, + "height": 32, + "fontSize": "14px", + "lineHeight": "22px", + "borderRadius": "8px", + "color": "rgba(0, 0, 0, 0.9)", + "icon": [ + 16, + 16 + ] + }, + { + "label": "打开文件夹", + "width": 152, + "height": 32, + "fontSize": "14px", + "lineHeight": "22px", + "borderRadius": "8px", + "color": "rgba(0, 0, 0, 0.9)", + "icon": [ + 16, + 16 + ] + }, + { + "label": "归档", + "width": 152, + "height": 32, + "fontSize": "14px", + "lineHeight": "22px", + "borderRadius": "8px", + "color": "rgba(0, 0, 0, 0.9)", + "icon": [ + 16, + 16 + ] + }, + { + "label": "删除任务", + "width": 152, + "height": 32, + "fontSize": "14px", + "lineHeight": "22px", + "borderRadius": "8px", + "color": "rgb(180, 44, 63)", + "icon": [ + 16, + 16 + ] + } + ], + "dividers": [ + { + "width": 152, + "height": 1, + "margin": "6px 0px" + }, + { + "width": 152, + "height": 1, + "margin": "6px 0px" + } + ] + } + }, + "checks": [ + { + "label": "menu labels match the implemented subset", + "pass": true, + "actual": [ + "置顶", + "重命名", + "在独立窗口中打开", + "打开文件夹", + "归档", + "删除任务" + ], + "expected": [ + "置顶", + "重命名", + "在独立窗口中打开", + "打开文件夹", + "归档", + "删除任务" + ] + }, + { + "label": "menu uses two dividers like the original", + "pass": true, + "actual": 2, + "expected": 2 + }, + { + "label": "items are 32 high like the original", + "pass": true, + "actual": true, + "expected": true + }, + { + "label": "item font is 14/22 like the original", + "pass": true, + "actual": true, + "expected": true + }, + { + "label": "item radius is 8 like the original", + "pass": true, + "actual": true, + "expected": true + }, + { + "label": "icon box is 16x16 like the original", + "pass": true, + "actual": true, + "expected": true + }, + { + "label": "menu padding is 8 like the original", + "pass": true, + "actual": "8px", + "expected": "8px" + }, + { + "label": "menu radius is 16 like the original", + "pass": true, + "actual": "16px", + "expected": "16px" + }, + { + "label": "danger item keeps the original danger colour", + "pass": true, + "actual": "rgb(180, 44, 63)", + "expected": "rgb(180, 44, 63)" + }, + { + "label": "normal items keep the original text colour", + "pass": true, + "actual": "rgba(0, 0, 0, 0.9)", + "expected": "rgba(0, 0, 0, 0.9)" + }, + { + "label": "menu minimum width is 160 like the original", + "pass": true, + "actual": true, + "expected": true + }, + { + "label": "menu sits on the original anchor offset (button left - 17, bottom + 4)", + "pass": true, + "actual": [ + 0, + 0 + ], + "expected": [ + 0, + 0 + ] + }, + { + "label": "divider height is 1 like the original", + "pass": true, + "actual": true, + "expected": true + }, + { + "label": "overlay click closes the menu", + "pass": true, + "actual": false, + "expected": false + }, + { + "label": "right-click opens the same implemented menu", + "pass": true, + "actual": [ + "置顶", + "重命名", + "在独立窗口中打开", + "打开文件夹", + "归档", + "删除任务" + ], + "expected": [ + "置顶", + "重命名", + "在独立窗口中打开", + "打开文件夹", + "归档", + "删除任务" + ] + }, + { + "label": "right-click opens the menu for the row under the pointer", + "pass": true, + "actual": "d77f13ed-f42d-481d-8b5f-071ccbedbdcb", + "expected": "d77f13ed-f42d-481d-8b5f-071ccbedbdcb" + }, + { + "label": "right-click does not switch the active conversation", + "pass": true, + "actual": "964a214e-45c8-47bf-b2f5-acc21232cca5", + "expected": "964a214e-45c8-47bf-b2f5-acc21232cca5" + }, + { + "label": "right-click anchors the menu at the pointer", + "pass": true, + "actual": [ + 220, + 420 + ], + "expected": [ + 220, + 420 + ] + }, + { + "label": "pin adds the original pinned-item class", + "pass": true, + "actual": true, + "expected": true + }, + { + "label": "pin shows a persistent pin badge", + "pass": true, + "actual": true, + "expected": true + }, + { + "label": "pin persists to the session store", + "pass": true, + "actual": true, + "expected": true + }, + { + "label": "pinned row offers 取消置顶 first", + "pass": true, + "actual": true, + "expected": true + }, + { + "label": "unpin clears the pinned marker", + "pass": true, + "actual": false, + "expected": false + }, + { + "label": "unpin persists", + "pass": true, + "actual": true, + "expected": true + }, + { + "label": "menu exposes an inline rename input", + "pass": true, + "actual": true, + "expected": true + }, + { + "label": "rename input closes after Enter", + "pass": true, + "actual": false, + "expected": false + }, + { + "label": "rename updates the row title", + "pass": true, + "actual": "Menu Renamed", + "expected": "Menu Renamed" + }, + { + "label": "rename persists to the session store", + "pass": true, + "actual": true, + "expected": true + }, + { + "label": "open folder targets the real session cwd", + "pass": true, + "actual": "C:\\Users\\Administrator\\.codex\\worktrees\\b01-accept-01\\YCode\\.tmp\\task-menu-9cdgdF\\fixture-workspace", + "expected": "C:\\Users\\Administrator\\.codex\\worktrees\\b01-accept-01\\YCode\\.tmp\\task-menu-9cdgdF\\fixture-workspace" + }, + { + "label": "open window creates exactly one extra window", + "pass": true, + "actual": 2, + "expected": 2 + }, + { + "label": "open window loads the task query for that session", + "pass": true, + "actual": "?window=task&taskId=964a214e-45c8-47bf-b2f5-acc21232cca5", + "expected": "?window=task&taskId=964a214e-45c8-47bf-b2f5-acc21232cca5" + }, + { + "label": "archive opens a confirmation before changing the task", + "pass": true, + "actual": "归档任务", + "expected": "归档任务" + }, + { + "label": "archive restores the documented original destination", + "pass": true, + "actual": "确认将该任务归档吗?归档后可在“系统设置-数据管理”中查看。", + "expected": "确认将该任务归档吗?归档后可在“系统设置-数据管理”中查看。" + }, + { + "label": "archive does not append unrequested compatibility copy", + "pass": true, + "actual": false, + "expected": false + }, + { + "label": "archive confirmation actions use the recovered labels", + "pass": true, + "actual": [ + "取消", + "确认归档" + ], + "expected": [ + "取消", + "确认归档" + ] + }, + { + "label": "archive confirmation uses the plan-defined 240px popconfirm", + "pass": true, + "actual": [ + 240, + "16px", + "16px" + ], + "expected": [ + 240, + "16px", + "16px" + ] + }, + { + "label": "archive light secondary background/border", + "pass": true, + "actual": [ + "rgb(255, 255, 255)", + [ + "1px", + "solid", + "rgb(222, 222, 222)" + ] + ], + "expected": [ + "rgb(255, 255, 255)", + [ + "1px", + "solid", + "rgb(222, 222, 222)" + ] + ] + }, + { + "label": "archive light primary/danger background", + "pass": true, + "actual": "rgba(0, 0, 0, 0.9)", + "expected": "rgba(0, 0, 0, 0.9)" + }, + { + "label": "archive light confirmation foreground", + "pass": true, + "actual": "rgb(255, 255, 255)", + "expected": "rgb(255, 255, 255)" + }, + { + "label": "archive light confirm geometry", + "pass": true, + "actual": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ], + "expected": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ] + }, + { + "label": "archive light cancel geometry", + "pass": true, + "actual": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ], + "expected": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ] + }, + { + "label": "archive light title weight", + "pass": true, + "actual": "600", + "expected": "600" + }, + { + "label": "archive dark secondary background/border", + "pass": true, + "actual": [ + "rgb(38, 38, 38)", + [ + "1px", + "solid", + "rgb(61, 61, 61)" + ] + ], + "expected": [ + "rgb(38, 38, 38)", + [ + "1px", + "solid", + "rgb(61, 61, 61)" + ] + ] + }, + { + "label": "archive dark primary/danger background", + "pass": true, + "actual": "rgba(255, 255, 255, 0.9)", + "expected": "rgba(255, 255, 255, 0.9)" + }, + { + "label": "archive dark confirmation foreground", + "pass": true, + "actual": "rgba(0, 0, 0, 0.9)", + "expected": "rgba(0, 0, 0, 0.9)" + }, + { + "label": "archive dark confirm geometry", + "pass": true, + "actual": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ], + "expected": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ] + }, + { + "label": "archive dark cancel geometry", + "pass": true, + "actual": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ], + "expected": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ] + }, + { + "label": "archive dark title weight", + "pass": true, + "actual": "600", + "expected": "600" + }, + { + "label": "cancelling archive keeps the task visible", + "pass": true, + "actual": 2, + "expected": 2 + }, + { + "label": "archive hides exactly one row", + "pass": true, + "actual": 1, + "expected": 1 + }, + { + "label": "archive keeps both sessions in the archived listing", + "pass": true, + "actual": 2, + "expected": 2 + }, + { + "label": "archived session keeps its archivedAt marker", + "pass": true, + "actual": 1, + "expected": 1 + }, + { + "label": "delete uses the idle confirmation title", + "pass": true, + "actual": "删除任务?", + "expected": "删除任务?" + }, + { + "label": "delete uses the idle confirmation description", + "pass": true, + "actual": "删除后,这些任务将从你的所有设备中移除,且无法恢复。", + "expected": "删除后,这些任务将从你的所有设备中移除,且无法恢复。" + }, + { + "label": "delete confirmation actions use the recovered idle labels", + "pass": true, + "actual": [ + "取消", + "确认" + ], + "expected": [ + "取消", + "确认" + ] + }, + { + "label": "idle delete is not marked as running", + "pass": true, + "actual": null, + "expected": null + }, + { + "label": "delete light secondary background/border", + "pass": true, + "actual": [ + "rgb(255, 255, 255)", + [ + "1px", + "solid", + "rgb(222, 222, 222)" + ] + ], + "expected": [ + "rgb(255, 255, 255)", + [ + "1px", + "solid", + "rgb(222, 222, 222)" + ] + ] + }, + { + "label": "delete light primary/danger background", + "pass": true, + "actual": "rgb(232, 92, 92)", + "expected": "rgb(232, 92, 92)" + }, + { + "label": "delete light confirmation foreground", + "pass": true, + "actual": "rgb(255, 255, 255)", + "expected": "rgb(255, 255, 255)" + }, + { + "label": "delete light confirm geometry", + "pass": true, + "actual": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ], + "expected": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ] + }, + { + "label": "delete light cancel geometry", + "pass": true, + "actual": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ], + "expected": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ] + }, + { + "label": "delete light title weight", + "pass": true, + "actual": "600", + "expected": "600" + }, + { + "label": "delete dark secondary background/border", + "pass": true, + "actual": [ + "rgb(38, 38, 38)", + [ + "1px", + "solid", + "rgb(61, 61, 61)" + ] + ], + "expected": [ + "rgb(38, 38, 38)", + [ + "1px", + "solid", + "rgb(61, 61, 61)" + ] + ] + }, + { + "label": "delete dark primary/danger background", + "pass": true, + "actual": "rgb(175, 25, 26)", + "expected": "rgb(175, 25, 26)" + }, + { + "label": "delete dark confirmation foreground", + "pass": true, + "actual": "rgb(255, 255, 255)", + "expected": "rgb(255, 255, 255)" + }, + { + "label": "delete dark confirm geometry", + "pass": true, + "actual": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ], + "expected": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ] + }, + { + "label": "delete dark cancel geometry", + "pass": true, + "actual": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ], + "expected": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ] + }, + { + "label": "delete dark title weight", + "pass": true, + "actual": "600", + "expected": "600" + }, + { + "label": "delete removes that session from the store", + "pass": true, + "actual": false, + "expected": false + }, + { + "label": "delete leaves only the archived session", + "pass": true, + "actual": 1, + "expected": 1 + }, + { + "label": "no renderer error logs", + "pass": true, + "actual": [], + "expected": [] + } + ], + "rendererErrors": [] +} \ No newline at end of file diff --git a/docs/协作/evidence/B01-review-02/mode-ask-dark-focus.png b/docs/协作/evidence/B01-review-02/mode-ask-dark-focus.png new file mode 100644 index 0000000..f84fe13 Binary files /dev/null and b/docs/协作/evidence/B01-review-02/mode-ask-dark-focus.png differ diff --git a/docs/协作/evidence/B01-review-02/mode-cjs-runner.cjs b/docs/协作/evidence/B01-review-02/mode-cjs-runner.cjs new file mode 100644 index 0000000..fd92616 --- /dev/null +++ b/docs/协作/evidence/B01-review-02/mode-cjs-runner.cjs @@ -0,0 +1,45 @@ +// Acceptance-only CJS harness for the unchanged supplied component fixture. +// Same assertions and native inputs, without ESM top-level await or rebuilding inside Electron. +const fs=require('fs'),path=require('path'),assert=require('assert/strict'); +const {createHash}=require('crypto'); +const electronModule=require('electron'); +const base=path.resolve('.tmp'); +const file='src/renderer/src/workbuddy/composer/ModeChip.tsx'; +if(!process.versions.electron){const env={...process.env};delete env.ELECTRON_RUN_AS_NODE;delete env.ELECTRON_RENDERER_URL;const child=require('child_process').spawn(electronModule,[__filename,process.argv.at(-1)],{env,windowsHide:true,stdio:'inherit'});const timer=setTimeout(()=>child.kill(),60000);child.once('exit',(code,signal)=>{clearTimeout(timer);console.log(JSON.stringify({exitCode:code,signal}));process.exitCode=code===0?0:1});}else{;(async()=>{ +const { app, BrowserWindow } = electronModule, output = path.resolve(process.argv.at(-1)) + assert.ok(path.dirname(output) === base && path.basename(output).startsWith('mode-chip-native-')) + fs.mkdirSync(path.join(output, 'data'), {recursive:true}); app.setPath('userData', path.join(output, 'data')); app.disableHardwareAcceleration() + let win; const checks = [], samples = [], errors = [] + try { + await app.whenReady(); win = new BrowserWindow({ width: 800, height: 300, show: false, webPreferences: { contextIsolation: true, nodeIntegration: false, backgroundThrottling: false } }) + win.webContents.on('console-message', event => { if (event.level === 'error' || event.level >= 3) errors.push(event.message) }) + await win.loadFile(path.join(output, 'index.html')); win.showInactive() + const read = code => win.webContents.executeJavaScript(code), pause = () => new Promise(resolve => setTimeout(resolve, 80)) + const check = (label, actual, expected = true) => { assert.deepEqual(actual, expected, label); checks.push(label) } + const key = async keyCode => { win.focus();win.webContents.focus();await pause();win.webContents.sendInputEvent({type:'keyDown',keyCode});if(keyCode==='Enter'||keyCode==='Space')win.webContents.sendInputEvent({type:'char',keyCode:keyCode==='Enter'?'\r':' '});win.webContents.sendInputEvent({type:'keyUp',keyCode});await pause() } + const sample = () => read(`(()=>{const c=document.querySelector('.yc-mode-chip'),i=c.querySelector('.yc-mode-chip__mode-icon'),b=c.querySelector('button'),s=getComputedStyle(c),r=e=>{const x=e.getBoundingClientRect();return{x:x.x,y:x.y,width:x.width,height:x.height}};return{chip:r(c),icon:r(i),button:b?r(b):null,background:s.backgroundColor,radius:s.borderRadius,color:s.color,expectedColor:s.getPropertyValue('--cr-text-secondary').trim(),font:s.fontSize,weight:s.fontWeight,line:s.lineHeight,padding:s.paddingLeft,iconOpacity:getComputedStyle(i).opacity,clearOpacity:b?getComputedStyle(b).opacity:null}})()`) + await pause() + for (const theme of ['light', 'dark']) for (const mode of ['plan', 'ask']) { + await read(`document.documentElement.dataset.theme='${theme}'; document.querySelector('.chat-pane').dataset.crTheme='${theme}'; qa.setMode('${mode}');qa.setDisabled(false);document.querySelector('#before').focus()`) + win.webContents.sendInputEvent({ type: 'mouseMove', x: 1, y: 1 }); await pause() + const normal = await sample(); samples.push({ theme, mode, state: 'normal', ...normal }) + check('transparent', normal.background, 'rgba(0, 0, 0, 0)'); check('pill', parseFloat(normal.radius) >= normal.chip.height / 2) + check('height', normal.chip.height, 32); check('font', normal.font, '13px'); check('weight', normal.weight, '500'); check('line', normal.line, '20px'); check('padding', normal.padding, '8px') + check('same slot', normal.icon, normal.button); check('icon width', normal.icon.width, 16); check('default icon', normal.iconOpacity, '1'); check('default close', normal.clearOpacity, '0') + check('secondary color', await read(`(()=>{const c=document.querySelector('.yc-mode-chip'),p=document.createElement('span');p.style.color='var(--cr-text-secondary)';c.append(p);const ok=getComputedStyle(p).color===getComputedStyle(c).color;p.remove();return ok})()`)) + win.webContents.sendInputEvent({ type: 'mouseMove', x: Math.round(normal.chip.x + normal.chip.width / 2), y: Math.round(normal.chip.y + normal.chip.height / 2) }); await pause() + const hover = await sample(); samples.push({ theme, mode, state: 'hover', ...hover }); check('hover icon hidden', hover.iconOpacity, '0'); check('hover X', hover.clearOpacity, '1'); check('no hover layout shift', hover.chip, normal.chip) + win.webContents.sendInputEvent({ type: 'mouseMove', x: 1, y: 1 }); await read(`document.querySelector('.yc-mode-chip').focus()`); await pause() + const focus = await sample(); check('focus icon hidden', focus.iconOpacity, '0'); check('focus X', focus.clearOpacity, '1'); check('no focus layout shift', focus.chip, normal.chip) + await fs.promises.writeFile(path.join(output, `${theme}-${mode}-focus.png`), (await win.webContents.capturePage()).toPNG()) + await key('Tab'); check('Tab reaches native clear', await read(`document.activeElement.matches('.yc-mode-chip__clear')`)) + const before = await read('qa.clears'); await key(mode === 'plan' ? 'Enter' : 'Space'); check('native keyboard exit', await read('qa.clears'), before + 1); check('craft hidden', await read(`!document.querySelector('.yc-mode-chip')`)) + await read(`qa.setMode('${mode}');qa.setDisabled(true)`); await pause(); check('disabled has no clear', await read(`!document.querySelector('.yc-mode-chip button')`)); check('disabled not tabbable', await read(`document.querySelector('.yc-mode-chip').tabIndex`), -1) + } + win.setSize(320, 300); await read(`qa.setMode('ask');qa.setDisabled(false)`); await pause(); const narrow = await sample(); check('narrow slot preserved', narrow.icon, narrow.button); check('narrow no overflow', narrow.chip.x + narrow.chip.width <= 320) + await fs.promises.writeFile(path.join(output, 'narrow.png'), (await win.webContents.capturePage()).toPNG()); check('no renderer errors', errors, []) + fs.writeFileSync(path.join(output, 'report.json'), JSON.stringify({ checks, samples, errors, sourceSha256: createHash('sha256').update(fs.readFileSync(file)).digest('hex'), scope: 'Own-YCode isolated component browser test, not full app/store integration or original-app pixel acceptance' }, null, 2)); app.exit(0) + } catch (error) { fs.writeFileSync(path.join(output, 'failure.txt'), String(error.stack || error)); console.error(error); app.exit(1) } + +})().catch(error=>{console.error(error);electronModule.app.exit(1)}); +} diff --git a/docs/协作/evidence/B01-review-02/mode-cjs-runner.txt b/docs/协作/evidence/B01-review-02/mode-cjs-runner.txt new file mode 100644 index 0000000..a4e4698 --- /dev/null +++ b/docs/协作/evidence/B01-review-02/mode-cjs-runner.txt @@ -0,0 +1,2 @@ + +{"exitCode":0,"signal":null} diff --git a/docs/协作/evidence/B01-review-02/mode-host-probe.cjs b/docs/协作/evidence/B01-review-02/mode-host-probe.cjs new file mode 100644 index 0000000..6c001f3 --- /dev/null +++ b/docs/协作/evidence/B01-review-02/mode-host-probe.cjs @@ -0,0 +1,84 @@ +const fs = require('node:fs/promises') +const path = require('node:path') +const { pathToFileURL } = require('node:url') + +if (!process.versions.electron) { + ;(async () => { + const dir = await fs.mkdtemp(path.resolve('.tmp/alignment-window-')) + const data = path.join(dir, 'data'), home = path.join(dir, 'home'), cwd = path.join(dir, 'workspace') + for (const folder of [data, home, cwd]) await fs.mkdir(folder) + const now = Date.now() + const model = { id:'audit-model', name:'Audit Model', providerId:'custom', model:'fixture', baseUrl:'http://127.0.0.1:1', authMode:'none', protocol:'anthropic', supportsToolCall:true } + await fs.writeFile(path.join(data,'models.json'), JSON.stringify({version:1, models:[model], selectedModelId:model.id})) + await fs.writeFile(path.join(data,'workspaces.json'),JSON.stringify({selectedWorkspaceId:'audit-space',workspaces:[{id:'audit-space',name:'Audit Workspace',root:cwd,createdAt:now}]})) + const question = { id:'q1', question:'Which target should be inspected?', answers:['Local fixture'] } + const messages = [ + {id:'u1',role:'user',content:'Inspect the local fixture.',createdAt:now-10000,status:'done'}, + {id:'a1',role:'assistant',content:'The local fixture is ready.',createdAt:now-9000,status:'done',turnStartedAt:now-10000,turnFinishedAt:now,turnDurationMs:10000, + tools:[{id:'q-tool',name:'AskUserQuestion',args:{questions:[question]},argsRaw:'{}',status:'ok',output:'ANSWER_RAW_SENTINEL',metadata:{questionAnswer:{questions:[question]}}}], + parts:[{type:'reasoning',id:'r1',text:'I need the target.',finished:true},{type:'tool',toolId:'q-tool'},{type:'reasoning',id:'r2',text:'The target is selected.',finished:true},{type:'text',text:'The local fixture is ready.'}]} + ] + const session = (id,agentMode,ms) => ({id,title:`Audit ${agentMode}`,cwd,workspaceId:'audit-space',modelId:model.id,agentMode,permissionMode:'full-access',createdAt:ms,updatedAt:ms,messages}) + await fs.writeFile(path.join(data,'sessions.json'),JSON.stringify({sessions:[session('audit-plan','plan',now+1),session('audit-ask','ask',now)]})) + const env={...process.env,YCODE_USER_DATA_DIR:data,YCODE_QA_DIRECTORY:dir,YCODE_QA_OFFSCREEN:'1',YCODE_DISABLE_GPU:'1',YCODE_DISABLE_SYSTEM_INTEGRATION:'1',AUDIT_WINDOW_DIR:dir} + delete env.ELECTRON_RUN_AS_NODE; delete env.ELECTRON_RENDERER_URL + const child=require('node:child_process').spawn(require('electron'),['--no-sandbox','--disable-gpu-sandbox',__filename],{env,windowsHide:true,stdio:['ignore','pipe','pipe']}) + let log='';child.stdout.on('data',x=>{log+=x});child.stderr.on('data',x=>{log+=x}) + const timeout=setTimeout(()=>child.kill(),90000) + child.on('exit',async code=>{clearTimeout(timeout);await fs.writeFile(path.join(dir,'process.log'),log);console.log(JSON.stringify({directory:dir,exitCode:code}));if(code)console.error(log.slice(-7000));process.exitCode=code??1}) + })().catch(e=>{console.error(e);process.exitCode=1}) +} else { + const {app,BrowserWindow,ipcMain}=require('electron') + const dir=process.env.AUDIT_WINDOW_DIR + app.disableHardwareAcceleration();app.setPath('home',path.join(dir,'home')) + const originalHandle=ipcMain.handle.bind(ipcMain) + ipcMain.handle=(channel,listener)=>originalHandle(channel,async(...args)=>{if(channel==='session:messages')await new Promise(r=>setTimeout(r,1200));return listener(...args)}) + let win + const pause=ms=>new Promise(r=>setTimeout(r,ms)) + const read=code=>win.webContents.executeJavaScript(code) + async function wait(code){for(let i=0;i<250;i++){const x=await read(code);if(x)return x;await pause(40)}throw new Error('Timeout '+code)} + async function shot(name){await read('document.fonts.ready');await pause(80);await fs.writeFile(path.join(dir,name+'.png'),(await win.webContents.capturePage()).toPNG())} + const styleProbe=`(selector)=>{const e=document.querySelector(selector);if(!e)return null;const c=getComputedStyle(e),r=e.getBoundingClientRect();return {selector,text:e.textContent,width:r.width,height:r.height,fontSize:c.fontSize,fontWeight:c.fontWeight,lineHeight:c.lineHeight,padding:c.padding,borderRadius:c.borderRadius,background:c.backgroundColor,color:c.color,display:c.display,opacity:c.opacity}}` + const styles=selectors=>read(`(()=>{const p=${styleProbe};return ${JSON.stringify(selectors)}.map(p)})()`) + ;(async()=>{ + await import(pathToFileURL(path.resolve('out/main/index.mjs')).href);await app.whenReady();win=BrowserWindow.getAllWindows()[0];win.setSize(1336,902);win.showInactive() + const errors=[];win.webContents.on('console-message',(_e,level,message)=>{if(level>=3)errors.push(message)}) + await wait('!!document.querySelector(".yc-session-skeleton")') + const skeleton=await styles(['.yc-session-skeleton','.yc-session-skeleton__avatar','.yc-session-skeleton__name','.yc-session-skeleton__user','.yc-session-skeleton__line','.yc-session-skeleton__line--short']) + await shot('loading') + await wait('!!document.querySelector(".yc-mode-chip") && !!document.querySelector(".msg--assistant")') + await pause(350) + const mode=await styles(['.yc-mode-chip','.yc-mode-chip__mode-icon','.yc-mode-chip__clear']) + await shot('plan') + await read('document.querySelector(".yc-mode-chip").focus()') + const focusedMode=await styles(['.yc-mode-chip','.yc-mode-chip__mode-icon','.yc-mode-chip__clear']) + await shot('plan-focus') + + const checks=[]; + for(const agentMode of ['plan','ask']){ + const sessionId='audit-'+agentMode; + if(agentMode==='ask'){ + await read('document.querySelector("[data-session-id=\\"audit-ask\\"]").click()'); + await wait('!!document.querySelector(".yc-mode-chip") && !document.querySelector(".yc-session-skeleton") && document.querySelector(".yc-mode-chip").textContent.includes("仅问答")'); + } + await read('document.querySelector(".wb-composer textarea").focus()'); + await win.webContents.insertText('KEEP_'+agentMode+'_DRAFT'); + await wait('document.querySelector(".wb-composer textarea").value.includes("KEEP_'+agentMode+'_DRAFT")'); + const before=await read('({draft:document.querySelector(".wb-composer textarea").value,permissionDisabled:document.querySelector(".yc-source-permission-trigger > button").disabled})'); + const metadataBefore=await read('window.ycode.session.list().then(list=>list.find(item=>item.id==='+JSON.stringify(sessionId)+'))'); + await read('document.querySelector(".yc-mode-chip__clear").focus()'); + win.focus();win.webContents.focus();await pause(100); + win.webContents.sendInputEvent({type:'keyDown',keyCode:'Enter'}); + win.webContents.sendInputEvent({type:'char',keyCode:'\r'}); + win.webContents.sendInputEvent({type:'keyUp',keyCode:'Enter'}); + await wait('!document.querySelector(".yc-mode-chip")'); + const after=await read('({draft:document.querySelector(".wb-composer textarea").value,permissionDisabled:document.querySelector(".yc-source-permission-trigger > button").disabled})'); + const metadataAfter=await read('window.ycode.session.list().then(list=>list.find(item=>item.id==='+JSON.stringify(sessionId)+'))'); + if(before.draft!==after.draft||!before.permissionDisabled||after.permissionDisabled||metadataBefore.permissionMode!=='full-access'||metadataAfter.permissionMode!=='full-access'||metadataAfter.agentMode!=='craft')throw Error('Mode host state mismatch '+agentMode); + checks.push({agentMode,before,after,savedPermissionBefore:metadataBefore.permissionMode,savedPermissionAfter:metadataAfter.permissionMode,savedModeAfter:metadataAfter.agentMode}); + await shot(agentMode+'-craft-draft-kept'); + } + await fs.writeFile(path.join(dir,'report.json'),JSON.stringify({codeSha:'1ed71b63b5af9a98b942ff47c66df5799d4d2c8a',scope:'Actual isolated app; native keyboard exits plan/ask with draft and saved permission retained; no model requests',checks,errors},null,2)); + if(errors.length)throw Error('Renderer errors');app.exit(0); + })().catch(async e=>{console.error(e);if(win)await shot('failure').catch(()=>{});await fs.writeFile(path.join(dir,'failure.txt'),String(e));app.exit(1)}) +} diff --git a/docs/协作/evidence/B01-review-02/mode-host-report.json b/docs/协作/evidence/B01-review-02/mode-host-report.json new file mode 100644 index 0000000..701c591 --- /dev/null +++ b/docs/协作/evidence/B01-review-02/mode-host-report.json @@ -0,0 +1,35 @@ +{ + "codeSha": "1ed71b63b5af9a98b942ff47c66df5799d4d2c8a", + "scope": "Actual isolated app; native keyboard exits plan/ask with draft and saved permission retained; no model requests", + "checks": [ + { + "agentMode": "plan", + "before": { + "draft": "KEEP_plan_DRAFT", + "permissionDisabled": true + }, + "after": { + "draft": "KEEP_plan_DRAFT", + "permissionDisabled": false + }, + "savedPermissionBefore": "full-access", + "savedPermissionAfter": "full-access", + "savedModeAfter": "craft" + }, + { + "agentMode": "ask", + "before": { + "draft": "KEEP_ask_DRAFT", + "permissionDisabled": true + }, + "after": { + "draft": "KEEP_ask_DRAFT", + "permissionDisabled": false + }, + "savedPermissionBefore": "full-access", + "savedPermissionAfter": "full-access", + "savedModeAfter": "craft" + } + ], + "errors": [] +} \ No newline at end of file diff --git a/docs/协作/evidence/B01-review-02/mode-plan-focus.png b/docs/协作/evidence/B01-review-02/mode-plan-focus.png new file mode 100644 index 0000000..82a5e12 Binary files /dev/null and b/docs/协作/evidence/B01-review-02/mode-plan-focus.png differ diff --git a/docs/协作/evidence/B01-review-02/mode-report.json b/docs/协作/evidence/B01-review-02/mode-report.json new file mode 100644 index 0000000..d21d803 --- /dev/null +++ b/docs/协作/evidence/B01-review-02/mode-report.json @@ -0,0 +1,368 @@ +{ + "checks": [ + "transparent", + "pill", + "height", + "font", + "weight", + "line", + "padding", + "same slot", + "icon width", + "default icon", + "default close", + "secondary color", + "hover icon hidden", + "hover X", + "no hover layout shift", + "focus icon hidden", + "focus X", + "no focus layout shift", + "Tab reaches native clear", + "native keyboard exit", + "craft hidden", + "disabled has no clear", + "disabled not tabbable", + "transparent", + "pill", + "height", + "font", + "weight", + "line", + "padding", + "same slot", + "icon width", + "default icon", + "default close", + "secondary color", + "hover icon hidden", + "hover X", + "no hover layout shift", + "focus icon hidden", + "focus X", + "no focus layout shift", + "Tab reaches native clear", + "native keyboard exit", + "craft hidden", + "disabled has no clear", + "disabled not tabbable", + "transparent", + "pill", + "height", + "font", + "weight", + "line", + "padding", + "same slot", + "icon width", + "default icon", + "default close", + "secondary color", + "hover icon hidden", + "hover X", + "no hover layout shift", + "focus icon hidden", + "focus X", + "no focus layout shift", + "Tab reaches native clear", + "native keyboard exit", + "craft hidden", + "disabled has no clear", + "disabled not tabbable", + "transparent", + "pill", + "height", + "font", + "weight", + "line", + "padding", + "same slot", + "icon width", + "default icon", + "default close", + "secondary color", + "hover icon hidden", + "hover X", + "no hover layout shift", + "focus icon hidden", + "focus X", + "no focus layout shift", + "Tab reaches native clear", + "native keyboard exit", + "craft hidden", + "disabled has no clear", + "disabled not tabbable", + "narrow slot preserved", + "narrow no overflow", + "no renderer errors" + ], + "samples": [ + { + "theme": "light", + "mode": "plan", + "state": "normal", + "chip": { + "x": 88.125, + "y": 40, + "width": 62, + "height": 32 + }, + "icon": { + "x": 96.125, + "y": 48, + "width": 16, + "height": 16 + }, + "button": { + "x": 96.125, + "y": 48, + "width": 16, + "height": 16 + }, + "background": "rgba(0, 0, 0, 0)", + "radius": "9999px", + "color": "rgba(0, 0, 0, 0.7)", + "expectedColor": "#000000b3", + "font": "13px", + "weight": "500", + "line": "20px", + "padding": "8px", + "iconOpacity": "1", + "clearOpacity": "0" + }, + { + "theme": "light", + "mode": "plan", + "state": "hover", + "chip": { + "x": 88.125, + "y": 40, + "width": 62, + "height": 32 + }, + "icon": { + "x": 96.125, + "y": 48, + "width": 16, + "height": 16 + }, + "button": { + "x": 96.125, + "y": 48, + "width": 16, + "height": 16 + }, + "background": "rgba(0, 0, 0, 0)", + "radius": "9999px", + "color": "rgba(0, 0, 0, 0.7)", + "expectedColor": "#000000b3", + "font": "13px", + "weight": "500", + "line": "20px", + "padding": "8px", + "iconOpacity": "0", + "clearOpacity": "1" + }, + { + "theme": "light", + "mode": "ask", + "state": "normal", + "chip": { + "x": 88.125, + "y": 40, + "width": 75, + "height": 32 + }, + "icon": { + "x": 96.125, + "y": 48, + "width": 16, + "height": 16 + }, + "button": { + "x": 96.125, + "y": 48, + "width": 16, + "height": 16 + }, + "background": "rgba(0, 0, 0, 0)", + "radius": "9999px", + "color": "rgba(0, 0, 0, 0.7)", + "expectedColor": "#000000b3", + "font": "13px", + "weight": "500", + "line": "20px", + "padding": "8px", + "iconOpacity": "1", + "clearOpacity": "0" + }, + { + "theme": "light", + "mode": "ask", + "state": "hover", + "chip": { + "x": 88.125, + "y": 40, + "width": 75, + "height": 32 + }, + "icon": { + "x": 96.125, + "y": 48, + "width": 16, + "height": 16 + }, + "button": { + "x": 96.125, + "y": 48, + "width": 16, + "height": 16 + }, + "background": "rgba(0, 0, 0, 0)", + "radius": "9999px", + "color": "rgba(0, 0, 0, 0.7)", + "expectedColor": "#000000b3", + "font": "13px", + "weight": "500", + "line": "20px", + "padding": "8px", + "iconOpacity": "0", + "clearOpacity": "1" + }, + { + "theme": "dark", + "mode": "plan", + "state": "normal", + "chip": { + "x": 88.125, + "y": 40, + "width": 62, + "height": 32 + }, + "icon": { + "x": 96.125, + "y": 48, + "width": 16, + "height": 16 + }, + "button": { + "x": 96.125, + "y": 48, + "width": 16, + "height": 16 + }, + "background": "rgba(0, 0, 0, 0)", + "radius": "9999px", + "color": "rgba(255, 255, 255, 0.65)", + "expectedColor": "#ffffffa6", + "font": "13px", + "weight": "500", + "line": "20px", + "padding": "8px", + "iconOpacity": "1", + "clearOpacity": "0" + }, + { + "theme": "dark", + "mode": "plan", + "state": "hover", + "chip": { + "x": 88.125, + "y": 40, + "width": 62, + "height": 32 + }, + "icon": { + "x": 96.125, + "y": 48, + "width": 16, + "height": 16 + }, + "button": { + "x": 96.125, + "y": 48, + "width": 16, + "height": 16 + }, + "background": "rgba(0, 0, 0, 0)", + "radius": "9999px", + "color": "rgba(255, 255, 255, 0.65)", + "expectedColor": "#ffffffa6", + "font": "13px", + "weight": "500", + "line": "20px", + "padding": "8px", + "iconOpacity": "0", + "clearOpacity": "1" + }, + { + "theme": "dark", + "mode": "ask", + "state": "normal", + "chip": { + "x": 88.125, + "y": 40, + "width": 75, + "height": 32 + }, + "icon": { + "x": 96.125, + "y": 48, + "width": 16, + "height": 16 + }, + "button": { + "x": 96.125, + "y": 48, + "width": 16, + "height": 16 + }, + "background": "rgba(0, 0, 0, 0)", + "radius": "9999px", + "color": "rgba(255, 255, 255, 0.65)", + "expectedColor": "#ffffffa6", + "font": "13px", + "weight": "500", + "line": "20px", + "padding": "8px", + "iconOpacity": "1", + "clearOpacity": "0" + }, + { + "theme": "dark", + "mode": "ask", + "state": "hover", + "chip": { + "x": 88.125, + "y": 40, + "width": 75, + "height": 32 + }, + "icon": { + "x": 96.125, + "y": 48, + "width": 16, + "height": 16 + }, + "button": { + "x": 96.125, + "y": 48, + "width": 16, + "height": 16 + }, + "background": "rgba(0, 0, 0, 0)", + "radius": "9999px", + "color": "rgba(255, 255, 255, 0.65)", + "expectedColor": "#ffffffa6", + "font": "13px", + "weight": "500", + "line": "20px", + "padding": "8px", + "iconOpacity": "0", + "clearOpacity": "1" + } + ], + "errors": [], + "sourceSha256": "805cb1c06baf00480f2cbfad8e432d0c984a3b2cce2e12683a9db2defbbe6110", + "scope": "Own-YCode isolated component browser test, not full app/store integration or original-app pixel acceptance" +} \ No newline at end of file diff --git a/docs/协作/evidence/B01-review-02/original-mode-runner.txt b/docs/协作/evidence/B01-review-02/original-mode-runner.txt new file mode 100644 index 0000000..904181b --- /dev/null +++ b/docs/协作/evidence/B01-review-02/original-mode-runner.txt @@ -0,0 +1,2 @@ + +{"output":"C:\\Users\\Administrator\\.codex\\worktrees\\b01-accept-01\\YCode\\.tmp\\mode-chip-native-iW7Uhk","exitCode":null} diff --git a/docs/协作/evidence/B01-review-02/popconfirm-browser-report.json b/docs/协作/evidence/B01-review-02/popconfirm-browser-report.json new file mode 100644 index 0000000..d38accf --- /dev/null +++ b/docs/协作/evidence/B01-review-02/popconfirm-browser-report.json @@ -0,0 +1,817 @@ +{ + "pass": true, + "results": [ + { + "label": "light/archive/false geometry", + "actual": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ], + "expected": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ] + }, + { + "label": "light/archive/false geometry", + "actual": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ], + "expected": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ] + }, + { + "label": "light/archive/false primary/danger colors", + "actual": [ + "rgba(0, 0, 0, 0.9)", + "rgb(255, 255, 255)" + ], + "expected": [ + "rgba(0, 0, 0, 0.9)", + "rgb(255, 255, 255)" + ] + }, + { + "label": "light/archive/false secondary colors/border", + "actual": [ + "rgb(255, 255, 255)", + "1px", + "solid", + "rgb(222, 222, 222)" + ], + "expected": [ + "rgb(255, 255, 255)", + "1px", + "solid", + "rgb(222, 222, 222)" + ] + }, + { + "label": "light/archive/false shell", + "actual": [ + "240px", + "16px", + "600" + ], + "expected": [ + "240px", + "16px", + "600" + ] + }, + { + "label": "light/archive/false shell background", + "actual": "rgb(255, 255, 255)", + "expected": "rgb(255, 255, 255)" + }, + { + "label": "light/archive/false initial focus", + "actual": true, + "expected": true + }, + { + "label": "light/archive/false busy prevents duplicates", + "actual": [ + 1, + true, + true, + "处理中…" + ], + "expected": [ + 1, + true, + true, + "处理中…" + ] + }, + { + "label": "light/archive/false busy cannot dismiss", + "actual": 0, + "expected": 0 + }, + { + "label": "light/archive/false failure retained", + "actual": "fixture failure", + "expected": "fixture failure" + }, + { + "label": "light/archive/false retry enabled", + "actual": false, + "expected": false + }, + { + "label": "light/archive/false retry success", + "actual": [ + 2, + 1, + false + ], + "expected": [ + 2, + 1, + false + ] + }, + { + "label": "light/delete/false geometry", + "actual": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ], + "expected": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ] + }, + { + "label": "light/delete/false geometry", + "actual": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ], + "expected": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ] + }, + { + "label": "light/delete/false primary/danger colors", + "actual": [ + "rgb(232, 92, 92)", + "rgb(255, 255, 255)" + ], + "expected": [ + "rgb(232, 92, 92)", + "rgb(255, 255, 255)" + ] + }, + { + "label": "light/delete/false secondary colors/border", + "actual": [ + "rgb(255, 255, 255)", + "1px", + "solid", + "rgb(222, 222, 222)" + ], + "expected": [ + "rgb(255, 255, 255)", + "1px", + "solid", + "rgb(222, 222, 222)" + ] + }, + { + "label": "light/delete/false shell", + "actual": [ + "240px", + "16px", + "600" + ], + "expected": [ + "240px", + "16px", + "600" + ] + }, + { + "label": "light/delete/false shell background", + "actual": "rgb(255, 255, 255)", + "expected": "rgb(255, 255, 255)" + }, + { + "label": "light/delete/false initial focus", + "actual": true, + "expected": true + }, + { + "label": "light/delete/false busy prevents duplicates", + "actual": [ + 1, + true, + true, + "处理中…" + ], + "expected": [ + 1, + true, + true, + "处理中…" + ] + }, + { + "label": "light/delete/false busy cannot dismiss", + "actual": 0, + "expected": 0 + }, + { + "label": "light/delete/false danger busy background", + "actual": "rgb(245, 185, 185)", + "expected": "rgb(245, 185, 185)" + }, + { + "label": "light/delete/false failure retained", + "actual": "fixture failure", + "expected": "fixture failure" + }, + { + "label": "light/delete/false retry enabled", + "actual": false, + "expected": false + }, + { + "label": "light/delete/false retry success", + "actual": [ + 2, + 1, + false + ], + "expected": [ + 2, + 1, + false + ] + }, + { + "label": "light/delete/true geometry", + "actual": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ], + "expected": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ] + }, + { + "label": "light/delete/true geometry", + "actual": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ], + "expected": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ] + }, + { + "label": "light/delete/true primary/danger colors", + "actual": [ + "rgb(232, 92, 92)", + "rgb(255, 255, 255)" + ], + "expected": [ + "rgb(232, 92, 92)", + "rgb(255, 255, 255)" + ] + }, + { + "label": "light/delete/true secondary colors/border", + "actual": [ + "rgb(255, 255, 255)", + "1px", + "solid", + "rgb(222, 222, 222)" + ], + "expected": [ + "rgb(255, 255, 255)", + "1px", + "solid", + "rgb(222, 222, 222)" + ] + }, + { + "label": "light/delete/true shell", + "actual": [ + "240px", + "16px", + "600" + ], + "expected": [ + "240px", + "16px", + "600" + ] + }, + { + "label": "light/delete/true shell background", + "actual": "rgb(255, 255, 255)", + "expected": "rgb(255, 255, 255)" + }, + { + "label": "light/delete/true initial focus", + "actual": true, + "expected": true + }, + { + "label": "light/delete/true running delete semantic", + "actual": "停止并删除", + "expected": "停止并删除" + }, + { + "label": "light/delete/true busy prevents duplicates", + "actual": [ + 1, + true, + true, + "处理中…" + ], + "expected": [ + 1, + true, + true, + "处理中…" + ] + }, + { + "label": "light/delete/true busy cannot dismiss", + "actual": 0, + "expected": 0 + }, + { + "label": "light/delete/true danger busy background", + "actual": "rgb(245, 185, 185)", + "expected": "rgb(245, 185, 185)" + }, + { + "label": "light/delete/true failure retained", + "actual": "fixture failure", + "expected": "fixture failure" + }, + { + "label": "light/delete/true retry enabled", + "actual": false, + "expected": false + }, + { + "label": "light/delete/true retry success", + "actual": [ + 2, + 1, + false + ], + "expected": [ + 2, + 1, + false + ] + }, + { + "label": "dark/archive/false geometry", + "actual": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ], + "expected": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ] + }, + { + "label": "dark/archive/false geometry", + "actual": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ], + "expected": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ] + }, + { + "label": "dark/archive/false primary/danger colors", + "actual": [ + "rgba(255, 255, 255, 0.9)", + "rgba(0, 0, 0, 0.9)" + ], + "expected": [ + "rgba(255, 255, 255, 0.9)", + "rgba(0, 0, 0, 0.9)" + ] + }, + { + "label": "dark/archive/false secondary colors/border", + "actual": [ + "rgb(38, 38, 38)", + "1px", + "solid", + "rgb(61, 61, 61)" + ], + "expected": [ + "rgb(38, 38, 38)", + "1px", + "solid", + "rgb(61, 61, 61)" + ] + }, + { + "label": "dark/archive/false shell", + "actual": [ + "240px", + "16px", + "600" + ], + "expected": [ + "240px", + "16px", + "600" + ] + }, + { + "label": "dark/archive/false shell background", + "actual": "rgb(36, 36, 36)", + "expected": "rgb(36, 36, 36)" + }, + { + "label": "dark/archive/false initial focus", + "actual": true, + "expected": true + }, + { + "label": "dark/archive/false busy prevents duplicates", + "actual": [ + 1, + true, + true, + "处理中…" + ], + "expected": [ + 1, + true, + true, + "处理中…" + ] + }, + { + "label": "dark/archive/false busy cannot dismiss", + "actual": 0, + "expected": 0 + }, + { + "label": "dark/archive/false failure retained", + "actual": "fixture failure", + "expected": "fixture failure" + }, + { + "label": "dark/archive/false retry enabled", + "actual": false, + "expected": false + }, + { + "label": "dark/archive/false retry success", + "actual": [ + 2, + 1, + false + ], + "expected": [ + 2, + 1, + false + ] + }, + { + "label": "dark/delete/false geometry", + "actual": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ], + "expected": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ] + }, + { + "label": "dark/delete/false geometry", + "actual": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ], + "expected": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ] + }, + { + "label": "dark/delete/false primary/danger colors", + "actual": [ + "rgb(175, 25, 26)", + "rgb(255, 255, 255)" + ], + "expected": [ + "rgb(175, 25, 26)", + "rgb(255, 255, 255)" + ] + }, + { + "label": "dark/delete/false secondary colors/border", + "actual": [ + "rgb(38, 38, 38)", + "1px", + "solid", + "rgb(61, 61, 61)" + ], + "expected": [ + "rgb(38, 38, 38)", + "1px", + "solid", + "rgb(61, 61, 61)" + ] + }, + { + "label": "dark/delete/false shell", + "actual": [ + "240px", + "16px", + "600" + ], + "expected": [ + "240px", + "16px", + "600" + ] + }, + { + "label": "dark/delete/false shell background", + "actual": "rgb(36, 36, 36)", + "expected": "rgb(36, 36, 36)" + }, + { + "label": "dark/delete/false initial focus", + "actual": true, + "expected": true + }, + { + "label": "dark/delete/false busy prevents duplicates", + "actual": [ + 1, + true, + true, + "处理中…" + ], + "expected": [ + 1, + true, + true, + "处理中…" + ] + }, + { + "label": "dark/delete/false busy cannot dismiss", + "actual": 0, + "expected": 0 + }, + { + "label": "dark/delete/false danger busy background", + "actual": "rgb(128, 56, 56)", + "expected": "rgb(128, 56, 56)" + }, + { + "label": "dark/delete/false failure retained", + "actual": "fixture failure", + "expected": "fixture failure" + }, + { + "label": "dark/delete/false retry enabled", + "actual": false, + "expected": false + }, + { + "label": "dark/delete/false retry success", + "actual": [ + 2, + 1, + false + ], + "expected": [ + 2, + 1, + false + ] + }, + { + "label": "dark/delete/true geometry", + "actual": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ], + "expected": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ] + }, + { + "label": "dark/delete/true geometry", + "actual": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ], + "expected": [ + "66px", + "19px", + "19px", + "28px", + "6px", + "12px" + ] + }, + { + "label": "dark/delete/true primary/danger colors", + "actual": [ + "rgb(175, 25, 26)", + "rgb(255, 255, 255)" + ], + "expected": [ + "rgb(175, 25, 26)", + "rgb(255, 255, 255)" + ] + }, + { + "label": "dark/delete/true secondary colors/border", + "actual": [ + "rgb(38, 38, 38)", + "1px", + "solid", + "rgb(61, 61, 61)" + ], + "expected": [ + "rgb(38, 38, 38)", + "1px", + "solid", + "rgb(61, 61, 61)" + ] + }, + { + "label": "dark/delete/true shell", + "actual": [ + "240px", + "16px", + "600" + ], + "expected": [ + "240px", + "16px", + "600" + ] + }, + { + "label": "dark/delete/true shell background", + "actual": "rgb(36, 36, 36)", + "expected": "rgb(36, 36, 36)" + }, + { + "label": "dark/delete/true initial focus", + "actual": true, + "expected": true + }, + { + "label": "dark/delete/true running delete semantic", + "actual": "停止并删除", + "expected": "停止并删除" + }, + { + "label": "dark/delete/true busy prevents duplicates", + "actual": [ + 1, + true, + true, + "处理中…" + ], + "expected": [ + 1, + true, + true, + "处理中…" + ] + }, + { + "label": "dark/delete/true busy cannot dismiss", + "actual": 0, + "expected": 0 + }, + { + "label": "dark/delete/true danger busy background", + "actual": "rgb(128, 56, 56)", + "expected": "rgb(128, 56, 56)" + }, + { + "label": "dark/delete/true failure retained", + "actual": "fixture failure", + "expected": "fixture failure" + }, + { + "label": "dark/delete/true retry enabled", + "actual": false, + "expected": false + }, + { + "label": "dark/delete/true retry success", + "actual": [ + 2, + 1, + false + ], + "expected": [ + 2, + 1, + false + ] + } + ], + "rendererErrors": [], + "scope": "Actual Electron Chromium component fixture; isolated callbacks, no IPC/model/session execution" +} \ No newline at end of file diff --git a/docs/协作/evidence/B01-review-02/popconfirm-cjs-runner.cjs b/docs/协作/evidence/B01-review-02/popconfirm-cjs-runner.cjs new file mode 100644 index 0000000..ca011ef --- /dev/null +++ b/docs/协作/evidence/B01-review-02/popconfirm-cjs-runner.cjs @@ -0,0 +1,44 @@ +// Acceptance-only Electron runner for the unchanged supplied Chromium HTML fixture. +const fs = require('fs') +const path = require('path') +const assert = require('assert/strict') +const electron = require('electron') +const directory = path.resolve(process.argv.at(-1)) +assert.ok(path.dirname(directory) === path.resolve('.tmp') && path.basename(directory).startsWith('task-popconfirm-browser-')) +if (!process.versions.electron) { + const env = { ...process.env } + delete env.ELECTRON_RUN_AS_NODE + delete env.ELECTRON_RENDERER_URL + const child = require('child_process').spawn(electron, [__filename, directory], { env, windowsHide: true, stdio: 'inherit' }) + const timer = setTimeout(() => child.kill(), 60000) + child.once('exit', (code, signal) => { + clearTimeout(timer) + console.log(JSON.stringify({ directory, exitCode: code, signal })) + process.exitCode = code === 0 ? 0 : 1 + }) +} else { + const { app, BrowserWindow } = electron + const data = path.join(directory, 'electron-profile') + fs.mkdirSync(data, { recursive: true }) + app.setPath('userData', data) + app.disableHardwareAcceleration() + app.whenReady().then(async () => { + const win = new BrowserWindow({ width: 1000, height: 700, show: false, webPreferences: { contextIsolation: true, nodeIntegration: false, backgroundThrottling: false } }) + const errors = [] + win.webContents.on('console-message', event => { if (event.level === 'error' || event.level >= 3) errors.push(event.message) }) + await win.loadFile(path.join(directory, 'index.html')) + win.showInactive() + for (let i = 0; i < 300; i++) { + const result = await win.webContents.executeJavaScript('document.querySelector("#result")?.textContent') + if (result) { + const report = JSON.parse(result) + fs.writeFileSync(path.join(directory, 'electron-report.json'), JSON.stringify({ ...report, rendererErrors: errors, scope: 'Actual Electron Chromium component fixture; isolated callbacks, no IPC/model/session execution' }, null, 2)) + console.log(JSON.stringify({ pass: report.pass, checks: report.results.length, error: report.error, rendererErrors: errors })) + app.exit(report.pass && errors.length === 0 ? 0 : 1) + return + } + await new Promise(resolve => setTimeout(resolve, 80)) + } + throw Error('Fixture result timed out') + }).catch(error => { console.error(error); app.exit(1) }) +} diff --git a/docs/协作/evidence/B01-review-02/question-report.json b/docs/协作/evidence/B01-review-02/question-report.json new file mode 100644 index 0000000..a1a91ee --- /dev/null +++ b/docs/协作/evidence/B01-review-02/question-report.json @@ -0,0 +1,362 @@ +{ + "codeSha": "1ed71b63b5af9a98b942ff47c66df5799d4d2c8a", + "scope": "Real isolated Windows Electron main/preload/renderer; synthetic persisted messages, no model/SDK or original app access.", + "light": { + "theme": "light", + "titleOutsideContent": true, + "cardCount": 1, + "rawAnswerVisible": false, + "horizontalOverflow": false, + "styles": [ + { + "selector": ".ask-user-question--completed", + "fontSize": "13px", + "fontWeight": "400", + "lineHeight": "19px", + "background": "rgba(0, 0, 0, 0)", + "padding": "2px 0px", + "borderRadius": "0px", + "border": "0px none rgb(51, 51, 51)", + "overflow": "visible", + "maxHeight": "none", + "width": 752, + "height": 117.5, + "scrollHeight": 118, + "clientHeight": 118 + }, + { + "selector": ".ask-user-question__header", + "fontSize": "14px", + "fontWeight": "400", + "lineHeight": "24.5px", + "background": "rgba(0, 0, 0, 0)", + "padding": "0px", + "borderRadius": "0px", + "border": "0px none rgba(0, 0, 0, 0.5)", + "overflow": "visible", + "maxHeight": "none", + "width": 752, + "height": 24.5, + "scrollHeight": 25, + "clientHeight": 25 + }, + { + "selector": ".ask-user-question__content", + "fontSize": "13px", + "fontWeight": "400", + "lineHeight": "19px", + "background": "rgb(242, 242, 242)", + "padding": "12px 16px", + "borderRadius": "16px", + "border": "0px none rgb(51, 51, 51)", + "overflow": "auto", + "maxHeight": "300px", + "width": 752, + "height": 77, + "scrollHeight": 77, + "clientHeight": 77 + }, + { + "selector": ".question-answer-transcript__question", + "fontSize": "14px", + "fontWeight": "400", + "lineHeight": "24.5px", + "background": "rgba(0, 0, 0, 0)", + "padding": "0px", + "borderRadius": "0px", + "border": "0px none rgb(128, 128, 128)", + "overflow": "visible", + "maxHeight": "none", + "width": 720, + "height": 24.5, + "scrollHeight": 25, + "clientHeight": 25 + }, + { + "selector": ".question-answer-transcript__answer", + "fontSize": "14px", + "fontWeight": "400", + "lineHeight": "24.5px", + "background": "rgba(0, 0, 0, 0)", + "padding": "0px", + "borderRadius": "0px", + "border": "0px none rgb(51, 51, 51)", + "overflow": "visible", + "maxHeight": "none", + "width": 720, + "height": 24.5, + "scrollHeight": 25, + "clientHeight": 25 + } + ] + }, + "dark": { + "theme": "dark", + "titleOutsideContent": true, + "cardCount": 1, + "rawAnswerVisible": false, + "horizontalOverflow": false, + "styles": [ + { + "selector": ".ask-user-question--completed", + "fontSize": "13px", + "fontWeight": "400", + "lineHeight": "19px", + "background": "rgba(0, 0, 0, 0)", + "padding": "2px 0px", + "borderRadius": "0px", + "border": "0px none rgb(210, 211, 224)", + "overflow": "visible", + "maxHeight": "none", + "width": 752, + "height": 117.5, + "scrollHeight": 118, + "clientHeight": 118 + }, + { + "selector": ".ask-user-question__header", + "fontSize": "14px", + "fontWeight": "400", + "lineHeight": "24.5px", + "background": "rgba(0, 0, 0, 0)", + "padding": "0px", + "borderRadius": "0px", + "border": "0px none rgba(255, 255, 255, 0.45)", + "overflow": "visible", + "maxHeight": "none", + "width": 752, + "height": 24.5, + "scrollHeight": 25, + "clientHeight": 25 + }, + { + "selector": ".ask-user-question__content", + "fontSize": "13px", + "fontWeight": "400", + "lineHeight": "19px", + "background": "rgb(42, 44, 49)", + "padding": "12px 16px", + "borderRadius": "16px", + "border": "0px none rgb(210, 211, 224)", + "overflow": "auto", + "maxHeight": "300px", + "width": 752, + "height": 77, + "scrollHeight": 77, + "clientHeight": 77 + }, + { + "selector": ".question-answer-transcript__question", + "fontSize": "14px", + "fontWeight": "400", + "lineHeight": "24.5px", + "background": "rgba(0, 0, 0, 0)", + "padding": "0px", + "borderRadius": "0px", + "border": "0px none rgb(160, 160, 160)", + "overflow": "visible", + "maxHeight": "none", + "width": 720, + "height": 24.5, + "scrollHeight": 25, + "clientHeight": 25 + }, + { + "selector": ".question-answer-transcript__answer", + "fontSize": "14px", + "fontWeight": "400", + "lineHeight": "24.5px", + "background": "rgba(0, 0, 0, 0)", + "padding": "0px", + "borderRadius": "0px", + "border": "0px none rgb(210, 211, 224)", + "overflow": "visible", + "maxHeight": "none", + "width": 720, + "height": 24.5, + "scrollHeight": 25, + "clientHeight": 25 + } + ] + }, + "narrow": { + "theme": "light", + "titleOutsideContent": true, + "cardCount": 1, + "rawAnswerVisible": false, + "horizontalOverflow": false, + "styles": [ + { + "selector": ".ask-user-question--completed", + "fontSize": "13px", + "fontWeight": "400", + "lineHeight": "19px", + "background": "rgba(0, 0, 0, 0)", + "padding": "2px 0px", + "borderRadius": "0px", + "border": "0px none rgb(51, 51, 51)", + "overflow": "visible", + "maxHeight": "none", + "width": 446, + "height": 117.5, + "scrollHeight": 118, + "clientHeight": 118 + }, + { + "selector": ".ask-user-question__header", + "fontSize": "14px", + "fontWeight": "400", + "lineHeight": "24.5px", + "background": "rgba(0, 0, 0, 0)", + "padding": "0px", + "borderRadius": "0px", + "border": "0px none rgba(0, 0, 0, 0.5)", + "overflow": "visible", + "maxHeight": "none", + "width": 446, + "height": 24.5, + "scrollHeight": 25, + "clientHeight": 25 + }, + { + "selector": ".ask-user-question__content", + "fontSize": "13px", + "fontWeight": "400", + "lineHeight": "19px", + "background": "rgb(242, 242, 242)", + "padding": "12px 16px", + "borderRadius": "16px", + "border": "0px none rgb(51, 51, 51)", + "overflow": "auto", + "maxHeight": "300px", + "width": 446, + "height": 77, + "scrollHeight": 77, + "clientHeight": 77 + }, + { + "selector": ".question-answer-transcript__question", + "fontSize": "14px", + "fontWeight": "400", + "lineHeight": "24.5px", + "background": "rgba(0, 0, 0, 0)", + "padding": "0px", + "borderRadius": "0px", + "border": "0px none rgb(128, 128, 128)", + "overflow": "visible", + "maxHeight": "none", + "width": 414, + "height": 24.5, + "scrollHeight": 25, + "clientHeight": 25 + }, + { + "selector": ".question-answer-transcript__answer", + "fontSize": "14px", + "fontWeight": "400", + "lineHeight": "24.5px", + "background": "rgba(0, 0, 0, 0)", + "padding": "0px", + "borderRadius": "0px", + "border": "0px none rgb(51, 51, 51)", + "overflow": "visible", + "maxHeight": "none", + "width": 414, + "height": 24.5, + "scrollHeight": 25, + "clientHeight": 25 + } + ] + }, + "long": { + "theme": "light", + "titleOutsideContent": true, + "cardCount": 1, + "rawAnswerVisible": false, + "horizontalOverflow": false, + "styles": [ + { + "selector": ".ask-user-question--completed", + "fontSize": "13px", + "fontWeight": "400", + "lineHeight": "19px", + "background": "rgba(0, 0, 0, 0)", + "padding": "2px 0px", + "borderRadius": "0px", + "border": "0px none rgb(51, 51, 51)", + "overflow": "visible", + "maxHeight": "none", + "width": 446, + "height": 340.5, + "scrollHeight": 341, + "clientHeight": 341 + }, + { + "selector": ".ask-user-question__header", + "fontSize": "14px", + "fontWeight": "400", + "lineHeight": "24.5px", + "background": "rgba(0, 0, 0, 0)", + "padding": "0px", + "borderRadius": "0px", + "border": "0px none rgba(0, 0, 0, 0.5)", + "overflow": "visible", + "maxHeight": "none", + "width": 446, + "height": 24.5, + "scrollHeight": 25, + "clientHeight": 25 + }, + { + "selector": ".ask-user-question__content", + "fontSize": "13px", + "fontWeight": "400", + "lineHeight": "19px", + "background": "rgb(242, 242, 242)", + "padding": "12px 16px", + "borderRadius": "16px", + "border": "0px none rgb(51, 51, 51)", + "overflow": "auto", + "maxHeight": "300px", + "width": 446, + "height": 300, + "scrollHeight": 5688, + "clientHeight": 300 + }, + { + "selector": ".question-answer-transcript__question", + "fontSize": "14px", + "fontWeight": "400", + "lineHeight": "24.5px", + "background": "rgba(0, 0, 0, 0)", + "padding": "0px", + "borderRadius": "0px", + "border": "0px none rgb(128, 128, 128)", + "overflow": "visible", + "maxHeight": "none", + "width": 404, + "height": 98, + "scrollHeight": 98, + "clientHeight": 98 + }, + { + "selector": ".question-answer-transcript__answer", + "fontSize": "14px", + "fontWeight": "400", + "lineHeight": "24.5px", + "background": "rgba(0, 0, 0, 0)", + "padding": "0px", + "borderRadius": "0px", + "border": "0px none rgb(51, 51, 51)", + "overflow": "visible", + "maxHeight": "none", + "width": 404, + "height": 122.5, + "scrollHeight": 123, + "clientHeight": 123 + } + ] + }, + "innerQuestionPreserved": "true", + "rendererErrors": [] +} \ No newline at end of file diff --git a/docs/协作/evidence/B01-review-02/regressions.json b/docs/协作/evidence/B01-review-02/regressions.json new file mode 100644 index 0000000..1f08a13 --- /dev/null +++ b/docs/协作/evidence/B01-review-02/regressions.json @@ -0,0 +1,27 @@ +[ + { + "Command": "npm run test:conversation", + "ExitCode": 0, + "Log": ".tmp/b01-acceptance/test-conversation-02.log" + }, + { + "Command": "npm run test:workbuddy-import", + "ExitCode": 0, + "Log": ".tmp/b01-acceptance/test-workbuddy-import-02.log" + }, + { + "Command": "npm run test:artifacts", + "ExitCode": 0, + "Log": ".tmp/b01-acceptance/test-artifacts-02.log" + }, + { + "Command": "npm run test:fold-summary", + "ExitCode": 1, + "Log": ".tmp/b01-acceptance/test-fold-summary-02.log" + }, + { + "Command": "npm run check:tokens", + "ExitCode": 1, + "Log": ".tmp/b01-acceptance/check-tokens-02.log" + } +] diff --git a/docs/协作/evidence/B01-review-02/typed-part-repro.mjs b/docs/协作/evidence/B01-review-02/typed-part-repro.mjs new file mode 100644 index 0000000..d304a58 --- /dev/null +++ b/docs/协作/evidence/B01-review-02/typed-part-repro.mjs @@ -0,0 +1,96 @@ +/** Independent read-only acceptance probe. Writes only .tmp output; no SDK/Electron/services. */ +import { build } from 'esbuild' +import { spawnSync, execFileSync } from 'node:child_process' +import { writeFileSync, mkdirSync } from 'node:fs' +import path from 'node:path' +const baseline = process.argv.includes('--baseline') +mkdirSync('.tmp/b01-readonly-review', {recursive:true}) +const baselineModulesLoaded = [] +const checkoutRevision = execFileSync('git', ['rev-parse', 'HEAD'], {encoding:'utf8'}).trim() +if (checkoutRevision !== '1ed71b63b5af9a98b942ff47c66df5799d4d2c8a') throw new Error('Run in the fixed 1ed71b6 acceptance checkout') +const revision = baseline ? '37ddb2ce24c23d1fab7d0609a62901cc666d4975' : '1ed71b63b5af9a98b942ff47c66df5799d4d2c8a' +const baselinePaths = new Set([ + 'src/renderer/src/components/MessageBubble.tsx', + 'src/renderer/src/workbuddy/conversation/CompletedFold.tsx', + 'src/renderer/src/workbuddy/conversation/SpecializedBlocks.tsx', + 'src/renderer/src/workbuddy/conversation/SourceToolHeader.tsx', + 'src/renderer/src/workbuddy/conversation/ToolCall.tsx', + 'src/renderer/src/workbuddy/conversation/ToolCallRenderer.tsx', + 'src/renderer/src/workbuddy/conversation/AskUserQuestion.tsx' +]) +const source=String.raw` +import assert from 'node:assert/strict' +import {createRequire} from 'node:module' +const domModule=process.env.YCODE_TEST_DOM_MODULE||process.cwd()+'/.tmp/b01-dom/node_modules/jsdom' +const {JSDOM}=createRequire(process.cwd()+'/package.json')(domModule) +const dom=new JSDOM('
',{pretendToBeVisual:true,url:'http://localhost/'}) +for(const key of ['window','document','Node','Element','HTMLElement','MouseEvent','KeyboardEvent','Event'])Object.defineProperty(globalThis,key,{value:dom.window[key],configurable:true}) +Object.defineProperty(globalThis,'navigator',{value:dom.window.navigator,configurable:true}) +Object.assign(globalThis,{IS_REACT_ACT_ENVIRONMENT:true}) +const {act}=require('react') as typeof import('react') +const {createRoot}=require('react-dom/client') as typeof import('react-dom/client') +const MessageBubble=require('./src/renderer/src/components/MessageBubble').default +const {applyAssistantEvent}=require('./src/shared/message-parts') +const root=createRoot(document.querySelector('#root')!) +const selectors={plan:'.cb-plan-header-left',task:'.cb-task-result-item-title'} +const get=(selector:string)=>{const node=document.querySelector(selector);assert.ok(node,selector);return node} +const state=()=>Object.fromEntries(Object.entries(selectors).map(([kind,selector])=>[kind,get(selector).getAttribute('aria-expanded')])) +async function render(message:any){await act(async()=>root.render())} +async function click(selector:string){await act(async()=>get(selector).dispatchEvent(new MouseEvent('click',{bubbles:true})))} +async function main(){ + let message:any={id:'b01-typed-part-repro',role:'assistant',createdAt:1,content:'',status:'streaming',parts:[]} + const streamingEvents=[ + {type:'text',delta:'Draft one'}, + {type:'part',part:{type:'reasoning',id:'r',text:'Thought',finished:true}}, + {type:'text',delta:'Draft two'}, + {type:'part',part:{type:'plan',plan:{id:'p',title:'Plan',steps:[]}}}, + {type:'part',part:{type:'task',task:{id:'x',title:'Task',status:'success',summary:'Task result'}}} + ] + for(const event of streamingEvents)message=applyAssistantEvent(message,event) + const input=JSON.parse(JSON.stringify(message)) + await render(message) + const initially=state() + await click(selectors.plan);await click(selectors.task) + const selected=state() + assert.deepEqual(selected,{plan:'false',task:'false'}) + const terminalEvent={type:'done',content:'Corrected final prose',tools:[],turnDurationMs:1000} + const finished=applyAssistantEvent(message,terminalEvent) + await render(finished) + const after=state() + const result={ + testedRevision:process.env.B01_PROBE_REVISION, + runtime:{node:process.version,platform:process.platform,react:require('react/package.json').version,jsdom:createRequire(process.cwd()+'/package.json')(domModule+'/package.json').version}, + input,terminalEvent,outputParts:finished.parts, + ariaExpanded:{initially,afterUserCollapse:selected,afterTerminalCorrection:after}, + expectedAfterTerminalCorrection:selected, + retainsUserChoices:JSON.stringify(selected)===JSON.stringify(after) + } + console.log(JSON.stringify(result,null,2)) + await act(async()=>root.unmount());dom.window.close() +} +main().then(()=>process.exit(0)).catch(error=>{console.error(error);dom.window.close();process.exit(1)}) +` +const outfile=`.tmp/b01-readonly-review/typed-part-repro-${baseline?'baseline':'1ed71b6'}.cjs` +await build({ + stdin:{contents:source,sourcefile:'b01-typed-part-repro.tsx',loader:'tsx',resolveDir:process.cwd()}, + outfile,bundle:true,platform:'node',format:'cjs',jsx:'automatic',loader:{'.css':'empty'},logLevel:'warning', + plugins:baseline?[{name:'read-baseline-product-modules',setup(build){build.onLoad({filter:/\.tsx$/},args=>{ + const relative=path.relative(process.cwd(),args.path).split(path.sep).join('/') + if(!baselinePaths.has(relative))return + baselineModulesLoaded.push(relative) + return {contents:execFileSync('git',['show',`${revision}:${relative}`],{encoding:'utf8'}),loader:'tsx',resolveDir:path.dirname(args.path)} + })}}]:[] +}) +const result=spawnSync(process.execPath,[outfile],{encoding:'utf8',timeout:120000,env:{...process.env,B01_PROBE_REVISION:revision}}) +const output=`.tmp/b01-readonly-review/typed-part-repro-${baseline?'baseline':'1ed71b6'}.json` +if(result.stderr)process.stderr.write(result.stderr) +if(result.status!==0){process.stderr.write(result.stdout);throw result.error||new Error(`probe exited ${result.status}`)} +if(baseline && baselineModulesLoaded.length !== baselinePaths.size) throw new Error('Baseline override did not load every changed React module') +const parsed=JSON.parse(result.stdout) +parsed.verificationMethod = baseline ? 'Bundled every changed React module from git show 37ddb2c; remaining product code equals tested checkout for this path' : 'Bundled fixed 1ed71b6 checkout product modules' +parsed.baselineModulesLoaded=baselineModulesLoaded +writeFileSync(output,JSON.stringify(parsed,null,2)+'\n') +console.log(JSON.stringify({evidence:output,testedRevision:revision,ariaExpanded:parsed.ariaExpanded,inputParts:parsed.input.parts.map(part=>part.type),outputParts:parsed.outputParts.map(part=>part.type),retainsUserChoices:parsed.retainsUserChoices},null,2)) + + +if(process.argv.includes('--assert') && !parsed.retainsUserChoices) process.exitCode=1 diff --git a/docs/协作/evidence/B01-review-02/typed-part-result.json b/docs/协作/evidence/B01-review-02/typed-part-result.json new file mode 100644 index 0000000..cf8805d --- /dev/null +++ b/docs/协作/evidence/B01-review-02/typed-part-result.json @@ -0,0 +1,105 @@ +{ + "testedRevision": "1ed71b63b5af9a98b942ff47c66df5799d4d2c8a", + "runtime": { + "node": "v24.21.0", + "platform": "win32", + "react": "19.3.0", + "jsdom": "30.1.3" + }, + "input": { + "id": "b01-typed-part-repro", + "role": "assistant", + "createdAt": 1, + "content": "Draft oneDraft two", + "status": "streaming", + "parts": [ + { + "type": "text", + "text": "Draft one" + }, + { + "type": "reasoning", + "id": "r", + "text": "Thought", + "finished": true + }, + { + "type": "text", + "text": "Draft two" + }, + { + "type": "plan", + "plan": { + "id": "p", + "title": "Plan", + "steps": [] + } + }, + { + "type": "task", + "task": { + "id": "x", + "title": "Task", + "status": "success", + "summary": "Task result" + } + } + ] + }, + "terminalEvent": { + "type": "done", + "content": "Corrected final prose", + "tools": [], + "turnDurationMs": 1000 + }, + "outputParts": [ + { + "type": "text", + "text": "Corrected final prose" + }, + { + "type": "reasoning", + "id": "r", + "text": "Thought", + "finished": true + }, + { + "type": "plan", + "plan": { + "id": "p", + "title": "Plan", + "steps": [] + } + }, + { + "type": "task", + "task": { + "id": "x", + "title": "Task", + "status": "success", + "summary": "Task result" + } + } + ], + "ariaExpanded": { + "initially": { + "plan": "true", + "task": "true" + }, + "afterUserCollapse": { + "plan": "false", + "task": "false" + }, + "afterTerminalCorrection": { + "plan": "false", + "task": "false" + } + }, + "expectedAfterTerminalCorrection": { + "plan": "false", + "task": "false" + }, + "retainsUserChoices": true, + "verificationMethod": "Bundled fixed 51531dc checkout product modules", + "baselineModulesLoaded": [] +} diff --git a/docs/协作/evidence/B02-review-01/alignment.txt b/docs/协作/evidence/B02-review-01/alignment.txt new file mode 100644 index 0000000..7b4fbde --- /dev/null +++ b/docs/协作/evidence/B02-review-01/alignment.txt @@ -0,0 +1,25 @@ + +> ycode@0.0.7 test:alignment +> node scripts/run-alignment-regression.mjs + +PASS model alignment: fresh/legacy migration, new/edit/default/delete/reload, valid selection (offline host fixtures) +PASS model settings: deferred owner switch, rename mapping, addition selection, empty deletion, immutable history +PASS session factory: first-send preference, mode preservation, invalid permission rejection (isolated ports) +{"historyMessages":10000,"bytes":747781,"parseMs":4.274399999999986,"storeHydrationMs":0.18410000000000082,"note":"Node parsing/store benchmark only, not browser rendering or Windows IPC performance"} +session-composer-alignment: loading/cache/retry/races/model/permissions/modes/SSR passed +alignment-conversation: local groups, original expanded order, question projection and truthful status passed +A01 native MessageBubble identity aliases, immutable inputs and ordinary raw output passed +A01 imported native card, linked dedup and unknown-position compatibility passed +question-answer-shell: structural and recovered CSS contracts passed +question-answer-shell: DOM hierarchy, controls linkage, click, Enter, Space and inert contracts passed +Runtime progress, session-grant scope and approval lifecycle regressions passed +Permission intercept static rendering passed; interactive keyboard/focus remains UI acceptance +Claude host approval policy unit checks passed (no SDK process/application/matching verification) +Mock SDK replay lifecycle passed: fail closed, retry, session isolation, independent mode guard +task popconfirm DOM regression: 34 checks passed (jsdom, not pixel validation) +question-interaction: 24 DOM behavioral checks passed +question-identity: 30 A01 DOM checks passed (not Electron/pixel/SDK acceptance) +completed-fold-nested: real question/tool/thinking/local-summary remount, event, keyboard and identity contracts passed +completed-fold-native-identity: real reducer done correction, native IDs, insertion/reorder, repeated outer toggles, message isolation and legacy fallback passed +Permission intercept DOM: 14 checks passed (not pixel/SDK verification) +{"checks":37,"passed":true,"scope":"Isolated React DOM and CSS contracts; no native keyboard/layout/pixel acceptance"} diff --git a/docs/协作/evidence/B02-review-01/build.txt b/docs/协作/evidence/B02-review-01/build.txt new file mode 100644 index 0000000..a440889 --- /dev/null +++ b/docs/协作/evidence/B02-review-01/build.txt @@ -0,0 +1,660 @@ + +> ycode@0.0.7 build +> npm run typecheck && electron-vite build + + +> ycode@0.0.7 typecheck +> tsc --noEmit -p tsconfig.node.json && tsc --noEmit -p tsconfig.web.json + +vite v8.3.4 building ssr environment for production... +transforming... +✓ 444 modules transformed. +rendering chunks... +out/main/index.mjs 1,596.10 kB + +✓ built in 205ms +vite v8.3.4 building ssr environment for production... +transforming... +✓ 2 modules transformed. +rendering chunks... +out/preload/index.cjs 15.89 kB + +✓ built in 13ms +vite v8.3.4 building client environment for production... +transforming... +✓ 3039 modules transformed. +rendering chunks... +out/renderer/settings.html 1.57 kB +out/renderer/index.html 1.75 kB +out/renderer/assets/KaTeX_Size3-Regular-CTq5MqoE.woff 4.42 kB +out/renderer/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 4.92 kB +out/renderer/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 5.20 kB +out/renderer/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 5.46 kB +out/renderer/assets/KaTeX_Size4-Regular-BF-4gkZK.woff 5.98 kB +out/renderer/assets/KaTeX_Size2-Regular-oD1tc_U0.woff 6.18 kB +out/renderer/assets/KaTeX_Size1-Regular-C195tn64.woff 6.49 kB +out/renderer/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 6.90 kB +out/renderer/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 6.91 kB +out/renderer/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf 7.58 kB +out/renderer/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff 7.65 kB +out/renderer/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff 7.71 kB +out/renderer/assets/archify-owner-avatar-BdE-HOjX.jpg 9.46 kB +out/renderer/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 9.64 kB +out/renderer/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 10.34 kB +out/renderer/assets/KaTeX_Size4-Regular-DWFBv043.ttf 10.36 kB +out/renderer/assets/KaTeX_Script-Regular-D5yQViql.woff 10.58 kB +out/renderer/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 11.31 kB +out/renderer/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 11.34 kB +out/renderer/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf 11.50 kB +out/renderer/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 12.02 kB +out/renderer/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 12.21 kB +out/renderer/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf 12.22 kB +out/renderer/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff 12.31 kB +out/renderer/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf 12.34 kB +out/renderer/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf 12.36 kB +out/renderer/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff 13.20 kB +out/renderer/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff 13.29 kB +out/renderer/assets/workbuddy-buddy-thumbnail-2713ed5b-CUhW0EYr.png 13.42 kB +out/renderer/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 13.56 kB +out/renderer/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff 14.11 kB +out/renderer/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff 14.40 kB +out/renderer/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff 16.02 kB +out/renderer/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 16.40 kB +out/renderer/assets/KaTeX_Math-Italic-t53AETM-.woff2 16.44 kB +out/renderer/assets/KaTeX_Script-Regular-C5JkGWo-.ttf 16.64 kB +out/renderer/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 16.78 kB +out/renderer/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 16.98 kB +out/renderer/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff 18.66 kB +out/renderer/assets/KaTeX_Math-Italic-DA0__PXp.woff 18.74 kB +out/renderer/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff 19.41 kB +out/renderer/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf 19.43 kB +out/renderer/assets/KaTeX_Fraktur-Regular-CB_wures.ttf 19.57 kB +out/renderer/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf 19.58 kB +out/renderer/assets/KaTeX_Main-Italic-BMLOBm91.woff 19.67 kB +out/renderer/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf 22.36 kB +out/renderer/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf 24.50 kB +out/renderer/assets/KaTeX_Main-Bold-Cx986IdX.woff2 25.32 kB +out/renderer/assets/KaTeX_Main-Regular-B22Nviop.woff2 26.27 kB +out/renderer/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf 27.55 kB +out/renderer/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 28.07 kB +out/renderer/assets/KaTeX_Main-Bold-Jm3AIy58.woff 29.91 kB +out/renderer/assets/KaTeX_Main-Regular-Dr94JaBh.woff 30.77 kB +out/renderer/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf 31.19 kB +out/renderer/assets/KaTeX_Math-Italic-flOr_0UB.ttf 31.30 kB +out/renderer/assets/design-case-3-DaIvrslH.png 32.76 kB +out/renderer/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf 32.96 kB +out/renderer/assets/KaTeX_AMS-Regular-DMm9YOAa.woff 33.51 kB +out/renderer/assets/KaTeX_Main-Italic-3WenGoN9.ttf 33.58 kB +out/renderer/assets/design-case-4-0hVdAJQR.png 45.16 kB +out/renderer/assets/design-case-2-BH_iQ5r3.png 45.56 kB +out/renderer/assets/KaTeX_Main-Bold-waoOVXN0.ttf 51.33 kB +out/renderer/assets/design-case-1-DOYiafVz.png 52.97 kB +out/renderer/assets/KaTeX_Main-Regular-ypZvNtVU.ttf 53.58 kB +out/renderer/assets/KaTeX_AMS-Regular-DRggAlZN.ttf 63.63 kB +out/renderer/assets/workbuddy-appearance-dark-CXQX3TZX.png 109.34 kB +out/renderer/assets/workbuddy-appearance-light-BbpPCukh.png 113.02 kB +out/renderer/assets/codicon-ngg6Pgfi-ngg6Pgfi.ttf 121.97 kB +out/renderer/assets/kimi-DiLyRSiJ.svg 129.22 kB +out/renderer/assets/json.worker-DEWrzUkU-FVRG9O7E.js 438.21 kB +out/renderer/assets/worker-portable-D1lwTqsk-Dg0RNmO0.js 456.22 kB +out/renderer/assets/landing-hero-B6659kdy.png 629.28 kB +out/renderer/assets/html.worker-BC4B-9NY-BDdNc3ca.js 756.63 kB +out/renderer/assets/css.worker-D7wyZb8r-YRw1jg-F.js 1,086.92 kB +out/renderer/assets/ts.worker-BsXRl7a--BbqraoNr.js 8,187.30 kB +out/renderer/assets/ArtifactPierreDiff-CNAfnhAF.css 1.16 kB +out/renderer/assets/GeneralSettingsPanel-CntDyB52.css 1.25 kB +out/renderer/assets/AgentsSettingsPanel-R0teGDyD.css 2.56 kB +out/renderer/assets/AboutHelpSettingsPanel-ksqGLObi.css 5.72 kB +out/renderer/assets/updates-ui-COSnOGKS.css 6.84 kB +out/renderer/assets/AppearanceSettingsPanel-DcaRECSa.css 8.03 kB +out/renderer/assets/ShortcutsSettingsPanel-Bu_5_488.css 18.05 kB +out/renderer/assets/MemorySettingsPanel-C3dtDAif.css 32.49 kB +out/renderer/assets/ModelSettingsPanel-BjNmxQAH.css 88.98 kB +out/renderer/assets/PersonalizationSettingsPanel-DnAyzaM6.css 98.77 kB +out/renderer/assets/app-DH7L1ZF2.css 259.93 kB +out/renderer/assets/index-33QIcM1B.css 2,684.72 kB +out/renderer/assets/pie-WAS4IAKB-1a9lbjhh.js 0.11 kB +out/renderer/assets/info-A6RAGUB7-Dsq8pPGK.js 0.11 kB +out/renderer/assets/radar-RG4KPBEZ-BwNT2qWb.js 0.11 kB +out/renderer/assets/packet-AYTQ26CC-C-iOIVQo.js 0.11 kB +out/renderer/assets/cynefin-OW5HDTMX-CTYbUR58.js 0.11 kB +out/renderer/assets/treemap-WGGIJYW6-CWek0LQD.js 0.11 kB +out/renderer/assets/wardley-WFR3VGLG-BnrEXTnU.js 0.11 kB +out/renderer/assets/gitGraph-4MIJSDKK-NHpEvzKf.js 0.12 kB +out/renderer/assets/railroad-74A4TZTK-CyYHr3KR.js 0.12 kB +out/renderer/assets/treeView-Q6P3EWNA-CzdWA6Mh.js 0.12 kB +out/renderer/assets/railroad-peg-WCYAUIDC-DyA9P8dX.js 0.12 kB +out/renderer/assets/architecture-7GRP2DOG-VyF0wzFW.js 0.12 kB +out/renderer/assets/railroad-abnf-HS5TGJTU-DWOH6PDU.js 0.12 kB +out/renderer/assets/railroad-ebnf-LZEXJU2U-B8jXqV-T.js 0.12 kB +out/renderer/assets/eventmodeling-NTZA5JFV-Dmu4IHsI.js 0.12 kB +out/renderer/assets/array-75Ih5Qg4.js 0.16 kB +out/renderer/assets/channel-DHarOYgZ.js 0.25 kB +out/renderer/assets/init-DHdG6DHP.js 0.27 kB +out/renderer/assets/chunk-Y2CYZVJY-CrOJDJJy.js 0.38 kB +out/renderer/assets/chunk-JWPE2WC7-BWmaSNkB.js 0.42 kB +out/renderer/assets/chunk-2Q5K7J3B-BBOGhvIe.js 0.44 kB +out/renderer/assets/prism-tsx-BJWEHjlk.js 0.48 kB +out/renderer/assets/chunk-5VM5RSS4-D50WUAUX.js 0.52 kB +out/renderer/assets/chunk-XXDRQBXY-BsO966Nz.js 0.58 kB +out/renderer/assets/flowDiagram-HODETNUW-DS2cT8EG.js 0.59 kB +out/renderer/assets/prism-json-DxLGXN1o.js 0.62 kB +out/renderer/assets/codeowners-C7Y3CTAA-BmB2_gvY.js 0.75 kB +out/renderer/assets/prism-clike-BcH_eOfE.js 0.89 kB +out/renderer/assets/tsv-DVa1_Ovr-BeS2kE5e.js 0.94 kB +out/renderer/assets/shellsession-C0HwRpr0-B630Ulnl.js 0.96 kB +out/renderer/assets/javascript-DGySzfUB-CQaVVFGk.js 0.99 kB +out/renderer/assets/settings-CauUETdq.js 1.01 kB +out/renderer/assets/infoDiagram-27XIBGKW-BxQCd_Wi.js 1.09 kB +out/renderer/assets/swimlanesDiagram-VR7AAH4N-CDntzTUl.js 1.09 kB +out/renderer/assets/html-derivative-D3Jld805-D0QQ5MTi.js 1.10 kB +out/renderer/assets/prism-go-Cw8Jg9YT.js 1.11 kB +out/renderer/assets/classDiagram-ZZMXUADV-B1CifpN6.js 1.16 kB +out/renderer/assets/classDiagram-v2-VYDZK3BY-CUL8warN.js 1.16 kB +out/renderer/assets/stateDiagram-v2-MP3YSRHH-Cd_OI8Qg.js 1.16 kB +out/renderer/assets/qmldir-DIq06gp2-CFVtueeV.js 1.20 kB +out/renderer/assets/git-rebase-CgwCWTNR-Cpss9r90.js 1.23 kB +out/renderer/assets/chunk-POPQ4Y6H-DJbU6j1e.js 1.23 kB +out/renderer/assets/azcli-Bsxmaz-H-Dgh56k5-.js 1.26 kB +out/renderer/assets/personalization-prefs-DASR3vwn.js 1.28 kB +out/renderer/assets/csv-BRhERoQG-DKrQczXm.js 1.36 kB +out/renderer/assets/prism-latex-CHSuA_Lo.js 1.38 kB +out/renderer/assets/jsx-runtime-C48wkPcG.js 1.41 kB +out/renderer/assets/git-commit-DGtBy1vY-s2uHofP2.js 1.47 kB +out/renderer/assets/AgentsSettingsPanel-CMYBwUKH.js 1.56 kB +out/renderer/assets/xsl-DV28r3Jw-B8bWzO_h.js 1.59 kB +out/renderer/assets/dotenv-DXc2fSbR-CUbEjgJq.js 1.62 kB +out/renderer/assets/general-settings-icons-DOmPIusw.js 1.64 kB +out/renderer/assets/prism-scala-CRTYzCpy.js 1.65 kB +out/renderer/assets/ini-D4-1Iswn-DaNDgFS8.js 1.65 kB +out/renderer/assets/prism-typescript-D-7ZUUQ-.js 1.65 kB +out/renderer/assets/sizeCapture-INFHLROL-CCEMv_MJ.js 1.68 kB +out/renderer/assets/csp-Bsbijh2H-033SDyRW.js 1.69 kB +out/renderer/assets/sparql-Mj-YIaDH-DAUou2oc.js 1.71 kB +out/renderer/assets/prism-css-Cmyw76Xa.js 1.73 kB +out/renderer/assets/ini-DMSv7OY2-xgSkktY4.js 1.74 kB +out/renderer/assets/rolldown-runtime-BJCASTsb-DKQFAHUF.js 1.78 kB +out/renderer/assets/line-BFbLTOFm.js 1.89 kB +out/renderer/assets/fortran-fixed-form-D91DiZLE-NxoUlVkB.js 1.91 kB +out/renderer/assets/docker-B7J3eHK7-C3FNXPS_.js 1.96 kB +out/renderer/assets/hxml-938TheZ7-pE5ojWPT.js 1.97 kB +out/renderer/assets/desktop-BwI-o01e-Da9rFJOd.js 2.03 kB +out/renderer/assets/ordinal-CmpyCcm_.js 2.22 kB +out/renderer/assets/prism-c-B7tsC1jE.js 2.23 kB +out/renderer/assets/rolldown-runtime-EITvVbkG.js 2.32 kB +out/renderer/assets/erb-BgMB3Uiw-CLkRQ9Hf.js 2.40 kB +out/renderer/assets/prism-kotlin-Bc2NQYRR.js 2.43 kB +out/renderer/assets/jssm-CIisorE2-ggX0kbSA.js 2.44 kB +out/renderer/assets/prism-python-CTkfasgb.js 2.48 kB +out/renderer/assets/reg-mzCtpvUf-BHC3bGU6.js 2.54 kB +out/renderer/assets/bat-2PwuskcT-BbFmQdFU.js 2.55 kB +out/renderer/assets/prism-mermaid-DSoNsh6-.js 2.56 kB +out/renderer/assets/pla-HAHcX3CH-DHyEyFew.js 2.57 kB +out/renderer/assets/sb-O6mPt74--_nMcDiF8.js 2.60 kB +out/renderer/assets/chunk-GVQU2GXP-CCUOPT_c.js 2.61 kB +out/renderer/assets/edge-DcEd3r9D-ZJX3cnY_.js 2.62 kB +out/renderer/assets/scheme-C-yCXfo--BHhgh59u.js 2.66 kB +out/renderer/assets/flow9-z3HgHIql-qOic_Sv2.js 2.72 kB +out/renderer/assets/prism-yaml-cmjQ_1eD.js 2.77 kB +out/renderer/assets/gleam-DEEAoY6G-DgJJp7nh.js 2.78 kB +out/renderer/assets/railroadDiagram-O6MQD6OU-CrE_AuZP.js 2.78 kB +out/renderer/assets/diff-lAxbRYdS--5gtlmD4.js 2.79 kB +out/renderer/assets/hy-BKymZdC0-4uNvYh3y.js 2.86 kB +out/renderer/assets/dockerfile-CnkhFuxG-CfXHMZr-.js 3.01 kB +out/renderer/assets/openscad-BRTETpP_-BThzc9qL.js 3.03 kB +out/renderer/assets/pascaligo-DI1dd1Zd-D23AoFdQ.js 3.03 kB +out/renderer/assets/log-Cn1ZE6kb-BE4srnlV.js 3.05 kB +out/renderer/assets/objective-c-gNYZndaF-4hkcNMcE.js 3.06 kB +out/renderer/assets/sparql-DxWbGozt-B7qTmycl.js 3.08 kB +out/renderer/assets/prism-markup-templating-D4pSJIpH.js 3.11 kB +out/renderer/assets/prism-cpp-CEgmwlDT.js 3.11 kB +out/renderer/assets/cameligo-B6LDhzzR-DSNRk43W.js 3.12 kB +out/renderer/assets/wenyan-BVgiL1tD-C7ph_xMt.js 3.12 kB +out/renderer/assets/cairo-D_LzMZ4I-C21twps2.js 3.17 kB +out/renderer/assets/prism-rust-Du0Qa8GC.js 3.18 kB +out/renderer/assets/lua-CJt09SGy-3O0VAMVx.js 3.19 kB +out/renderer/assets/graphql-C0cKWTiE-BQOKksLE.js 3.20 kB +out/renderer/assets/berry-DTcSbIs7-DsDdtWdB.js 3.20 kB +out/renderer/assets/jsonl-Cn_fzNA8-cIG9lf61.js 3.21 kB +out/renderer/assets/json-CKKhFIOr-DuiQFrCF.js 3.29 kB +out/renderer/assets/mips-Df5bwPtM-DJn7b529.js 3.29 kB +out/renderer/assets/jsonc-Bf3Xcgeq-BGBJ2TDY.js 3.31 kB +out/renderer/assets/logo-BxqPaaID-DK9gUnx4.js 3.33 kB +out/renderer/assets/abnfDiagram-VCTEODGH-BEqo0QPU.js 3.36 kB +out/renderer/assets/go-BejFoqvR-BnGoIlsY.js 3.42 kB +out/renderer/assets/po-DI6EG-tz-DIkePE8T.js 3.44 kB +out/renderer/assets/lexon-5NyrCfQ6-B1bdOCGH.js 3.45 kB +out/renderer/assets/prism-sql-BggiY1Ht.js 3.45 kB +out/renderer/assets/json5-BlijqrwT-Ci88mndw.js 3.45 kB +out/renderer/assets/mipsasm-U3SQfJCQ-kat_Vj1M.js 3.46 kB +out/renderer/assets/sophia-foSZ3xPI-DGYIHURw.js 3.47 kB +out/renderer/assets/tasl-C74Cvwdf-se1Ptgso.js 3.49 kB +out/renderer/assets/genie-CjS3m_gh-DHydh9_z.js 3.56 kB +out/renderer/assets/prism-swift-xplGsQ1n.js 3.56 kB +out/renderer/assets/vala-DMgevQbf-ByJQiTkp.js 3.57 kB +out/renderer/assets/pegDiagram-XKGWAZYB-CmGvFb7R.js 3.59 kB +out/renderer/assets/rel-D6dNeDZv-CUAJzmkw.js 3.60 kB +out/renderer/assets/prism-java-6uFEGwWz.js 3.63 kB +out/renderer/assets/fsharp-Ba-cvOiG-BoxQhS9v.js 3.64 kB +out/renderer/assets/chunk-P2QGCYS3-B9n3RDRx.js 3.65 kB +out/renderer/assets/ebnfDiagram-PWID7BFC-DlFL4szh.js 3.66 kB +out/renderer/assets/qsharp-78iLGMHs-Dbh3PRIx.js 3.68 kB +out/renderer/assets/m3-Bu81_nWr-4t51Qx0i.js 3.69 kB +out/renderer/assets/chunk-F27PBJKO-DsTJ-19K.js 3.70 kB +out/renderer/assets/pascal-DyPgZbsX-Ba58YM7a.js 3.71 kB +out/renderer/assets/path-CSWwviF2.js 3.79 kB +out/renderer/assets/fluent-BSSEgVQa-BCOQigl1.js 3.81 kB +out/renderer/assets/splunk-BdqSfgpd-BtOEh0Mo.js 3.81 kB +out/renderer/assets/jsonnet-Bn71vRY8-QjPNMWdY.js 3.82 kB +out/renderer/assets/ssh-config-BO51LXox-DkFt_ueS.js 3.82 kB +out/renderer/assets/bicep-DujF3y-4-DHww3ZLF.js 3.87 kB +out/renderer/assets/narrat-DdgkgBr0-CSyxDqta.js 3.87 kB +out/renderer/assets/redis-Bo427DT4-DBDF4ZWx.js 3.88 kB +out/renderer/assets/turtle-DAmmiOda-C48PN72o.js 3.92 kB +out/renderer/assets/dist-CE9GMTNb.js 3.97 kB +out/renderer/assets/prism-jsx-BO0yI1A3.js 3.97 kB +out/renderer/assets/xml-BBFzlEmT-CqLnJtYa.js 3.99 kB +out/renderer/assets/java-Z7anYNQ6-DdC7WVZS.js 4.01 kB +out/renderer/assets/r-Xh-gXEK4-DKEPC8dA.js 4.02 kB +out/renderer/assets/ron-CdysqNkW-BG7UwPdX.js 4.11 kB +out/renderer/assets/zenscript-XbBI4c9W-C-aTQo6e.js 4.12 kB +out/renderer/assets/glsl-CZF-bvQV-UaBdSZy0.js 4.14 kB +out/renderer/assets/shell-DGp7WuK3-X00pamiI.js 4.15 kB +out/renderer/assets/gn-DJxfXStl-BD_k0CWf.js 4.20 kB +out/renderer/assets/kotlin-C61BvWgT-B7MkJpdU.js 4.20 kB +out/renderer/assets/typespec-B704GmX3-f1l-QmOw.js 4.26 kB +out/renderer/assets/kdl-YTd72GVl-DLkP_pAB.js 4.27 kB +out/renderer/assets/AppearanceSettingsPanel-B_352Jrg.js 4.28 kB +out/renderer/assets/hurl-CDXCvJNd-Xd5k76nE.js 4.28 kB +out/renderer/assets/cypher-CjfQI0Y9-9gjOyi6P.js 4.33 kB +out/renderer/assets/pascal-CLPA94yO-C11lM2uy.js 4.35 kB +out/renderer/assets/powershell-CaPzBwIT-C9KgMPOP.js 4.50 kB +out/renderer/assets/tcl-D-NiFh9X-CYwv4uzi.js 4.63 kB +out/renderer/assets/apex-BE-040ts-wdfiR7V6.js 4.65 kB +out/renderer/assets/tcl-DowxIvU4-Bbhzqrsw.js 4.65 kB +out/renderer/assets/rosmsg-DDyuMVTo-DSHWRdSZ.js 4.72 kB +out/renderer/assets/nextflow-DVTlkzu9-Cis-JUmb.js 4.75 kB +out/renderer/assets/http-DhxVjYFh-CjwVOaui.js 4.76 kB +out/renderer/assets/hcl-CbjaVS9i-DCS43mBd.js 4.79 kB +out/renderer/assets/rust-Ij2gfGoT-DLzaBWYs.js 4.83 kB +out/renderer/assets/polar-CwTxzzWE-DygHL4ZA.js 4.87 kB +out/renderer/assets/prism-ruby-PgHh3fQm.js 4.91 kB +out/renderer/assets/fennel-COJTUo2O-DYh8-dep.js 4.97 kB +out/renderer/assets/bibtex-yEKRWsaj-xHthw1sC.js 5.00 kB +out/renderer/assets/coffee-CcgZJF1B-DkN4xoBX.js 5.04 kB +out/renderer/assets/llvm-DiFwU398-BQjCVu39.js 5.25 kB +out/renderer/assets/less-CXux59mP-BM7SkPLH.js 5.27 kB +out/renderer/assets/msdax-DEyWhkWP-CwdIr_-P.js 5.29 kB +out/renderer/assets/prism-javascript-B6zosBCV.js 5.31 kB +out/renderer/assets/wgsl-Ds7VVNHP-yP3bMkfO.js 5.34 kB +out/renderer/assets/markdown-CBag5COD-B_1rbk64.js 5.36 kB +out/renderer/assets/dart-DK8_VUW5-Bnb_Tn57.js 5.39 kB +out/renderer/assets/zig-BBWfbOQ5-B8x_JL1P.js 5.54 kB +out/renderer/assets/restructuredtext-D2p7PcFG-DDHAm_JI.js 5.55 kB +out/renderer/assets/dax-CmrIxjmL-CDTyHmZ_.js 5.56 kB +out/renderer/assets/gdresource-4lq4eh4q-CjhvlVte.js 5.56 kB +out/renderer/assets/qml-D6gd64uC-_ykXVPoZ.js 5.57 kB +out/renderer/assets/bicep-wTwvD1CI-C568hcwN.js 5.58 kB +out/renderer/assets/cssMode-Z-o80aSY-BvzV-1yi.js 5.59 kB +out/renderer/assets/awk-DTjcVAOD-BmfaVU4m.js 5.66 kB +out/renderer/assets/liquid-Dv-zz5BA-D9ukCDuL.js 5.71 kB +out/renderer/assets/csharp-DpS7Vfy9-CbQzv1ql.js 5.76 kB +out/renderer/assets/coq-BFytDJOI-C5vNmx0q.js 5.81 kB +out/renderer/assets/swift-C3A42nmX-BBVToPkN.js 5.83 kB +out/renderer/assets/xml-bIkPj5aH-Bx1v5u6-.js 5.89 kB +out/renderer/assets/ecl-CYzojQ6a-C8m0_osY.js 5.91 kB +out/renderer/assets/jinja-Dl-Ji_JA-BBL5sTd0.js 5.92 kB +out/renderer/assets/lean-Cu10prRO-BUTVAAdc.js 6.03 kB +out/renderer/assets/yaml-GEMDST6R-D-0AGe4F.js 6.09 kB +out/renderer/assets/moonbit-B8-g2u5v-CGBFUznC.js 6.10 kB +out/renderer/assets/powerquery-tKWDTKOo-CejxekA_.js 6.11 kB +out/renderer/assets/SourceCodePreview-rs88mqRs.js 6.11 kB +out/renderer/assets/python-CHafhQyI-DmJIfgbV.js 6.14 kB +out/renderer/assets/shaderlab-Df7nOKvI-0G488FSx.js 6.16 kB +out/renderer/assets/css-sG8ozMHf-pZGexMoj.js 6.17 kB +out/renderer/assets/cpp-CipCPBaT-7uQRIwsC.js 6.17 kB +out/renderer/assets/vb-BKV3Sgm5-D5ytx6Ln.js 6.29 kB +out/renderer/assets/htmlMode-BDZbYlMj-CRoXjFoW.js 6.40 kB +out/renderer/assets/red-CYaKK_PD-iiAMl8iL.js 6.45 kB +out/renderer/assets/min-dark-DGPfDRqJ-gZu6HtcU.js 6.48 kB +out/renderer/assets/pug-EKWpNZSi-oQ708bsr.js 6.51 kB +out/renderer/assets/prisma-CdZyz3OC-ChFCtYaa.js 6.53 kB +out/renderer/assets/gdshader-ryZhEIxg-DpcQqwXn.js 6.55 kB +out/renderer/assets/ara-_lrJyEFe-qigo-wGx.js 6.56 kB +out/renderer/assets/clojure-WSq30mUj-Bswhoa1y.js 6.61 kB +out/renderer/assets/toml-DPP887_3-aOuHoLTy.js 6.62 kB +out/renderer/assets/postcss-CcIp2ENG-DpmxBCXW.js 6.64 kB +out/renderer/assets/verilog-bragEGMk-CemzLugw.js 6.64 kB +out/renderer/assets/solarized-light-BIMszn7B-vPMkTTwP.js 6.68 kB +out/renderer/assets/cypher-COYrq2Yy-BtVrfsLp.js 6.75 kB +out/renderer/assets/arc-LpCwTDer.js 6.75 kB +out/renderer/assets/proto-CQIfhs_g-Deqofbl3.js 6.77 kB +out/renderer/assets/smalltalk-BLGdLDJX-BKGgemER.js 6.79 kB +out/renderer/assets/vb-D1Cw85Ss-BSz-V9M4.js 6.86 kB +out/renderer/assets/talonscript-DA9pg7Tj-CPXKQ95R.js 6.96 kB +out/renderer/assets/r-Bb2Mu7Fo-Dq0URONw.js 7.00 kB +out/renderer/assets/solarized-dark-D_I-4EGa-BZbeAUhW.js 7.04 kB +out/renderer/assets/diagram-Z3DM3KII-Dq9cpJHo.js 7.08 kB +out/renderer/assets/riscv-CQHqXr1Z-BFlZFId-.js 7.11 kB +out/renderer/assets/soy-DybHqX1A-DOhErZPj.js 7.15 kB +out/renderer/assets/min-light-BF0EjVgr-DvViuJW_.js 7.16 kB +out/renderer/assets/scheme-Dn0tgEWN-BK64z0tZ.js 7.37 kB +out/renderer/assets/prism-bash-B2ETaHUm.js 7.43 kB +out/renderer/assets/typescript-sfPIqb8J-DtIl1kXb.js 7.44 kB +out/renderer/assets/hlsl-CAmjcFpk-B3FZWMVz.js 7.48 kB +out/renderer/assets/mdx-Bdu4uO-C-BrzgNjCw.js 7.58 kB +out/renderer/assets/qss-DkzwWM0J-04JPp7d-.js 7.67 kB +out/renderer/assets/html-DKbmsqz6-Cnkf6ew3.js 7.69 kB +out/renderer/assets/systemd-CS6mVasZ-HbzlQlDs.js 8.07 kB +out/renderer/assets/monokai-CYqILLdj-CEXuJ8HO.js 8.08 kB +out/renderer/assets/twig-r8vgPZrm-D2l24YwI.js 8.18 kB +out/renderer/assets/updates-ui-BoiWSsup.js 8.22 kB +out/renderer/assets/wgsl-D_5Qxf6T-D508aVGZ.js 8.27 kB +out/renderer/assets/sdbl-BXfz6d3_-C4Qk7OPN.js 8.42 kB +out/renderer/assets/regexp-Dv0OUts_-BqK6b4KR.js 8.46 kB +out/renderer/assets/prism-php-dzcOOH50.js 8.49 kB +out/renderer/assets/systemverilog-BreNGkRs-RIXr4hNf.js 8.65 kB +out/renderer/assets/plsql-C-xpsZfV-frBdohcC.js 8.71 kB +out/renderer/assets/vue-html-DvuHo2mm-b7I-opwf.js 8.71 kB +out/renderer/assets/haml-CIYwkycC-3fSMp7m2.js 8.81 kB +out/renderer/assets/scss-CLoW-2dr-BBC_GO_6.js 8.86 kB +out/renderer/assets/dart-CBkkDIWs-ezKLFP5s.js 8.94 kB +out/renderer/assets/horizon-CELVL8Ba-x0NmpRb6.js 8.97 kB +out/renderer/assets/horizon-bright-DBDyMeUQ-Bhh-QDk3.js 8.98 kB +out/renderer/assets/julia-DvNkK6LK-Bi3Rlfah.js 9.04 kB +out/renderer/assets/clojure-886L7m2N-BhGJsUM7.js 9.14 kB +out/renderer/assets/make-CsAfL-jc-DaQVAww0.js 9.18 kB +out/renderer/assets/andromeeda--j5Bq-48-DxyWS_fJ.js 9.21 kB +out/renderer/assets/dark-plus-FAPM6M6c-DKexDF--.js 9.29 kB +out/renderer/assets/sas-BQIEUTPQ-Bwx-ZPYU.js 9.31 kB +out/renderer/assets/slack-dark-nDxLkSCC-C5pzIEPN.js 9.31 kB +out/renderer/assets/perl-Bec3eWyr-CDmSu3_s.js 9.32 kB +out/renderer/assets/plastic-DY_h9Vzh-CZzPFkTC.js 9.49 kB +out/renderer/assets/sass-Ysv8HTNa-CHNQIGaT.js 9.49 kB +out/renderer/assets/st-BrgXZ-Ag-BUs-RRgp.js 9.58 kB +out/renderer/assets/typst-Co5rZla4-COemceoz.js 9.61 kB +out/renderer/assets/slack-ochin-7zJWY-K--C7KFpXik.js 9.63 kB +out/renderer/assets/defaultLocale-QNqK0iCN.js 9.84 kB +out/renderer/assets/handlebars-CIJAyfa9-6toBlNYk.js 9.94 kB +out/renderer/assets/jison-Cbw0l5It-BNek_9Kq.js 9.95 kB +out/renderer/assets/sql-DviNlDJO-CwV6bDIP.js 9.97 kB +out/renderer/assets/kotlin-DIw6ua6F-CdVnL0aF.js 10.01 kB +out/renderer/assets/cmake-CyNDuJo8-2Hk4zQCd.js 10.07 kB +out/renderer/assets/light-plus-DkScKIB5-e8Q5AKjf.js 10.14 kB +out/renderer/assets/hcl-DoJdlYjN-DdpM5wFm.js 10.25 kB +out/renderer/assets/scala-Dj45wWzI-CAMCqIXS.js 10.40 kB +out/renderer/assets/postiats-SaHD9Qcv-FPvOr1pn.js 10.45 kB +out/renderer/assets/beancount-CyZf3Huc-C4n-y8pc.js 10.58 kB +out/renderer/assets/tex-gcnXexI3-BUpeblVA.js 10.60 kB +out/renderer/assets/php-Bn8AF0uj-CBbpr2vs.js 10.62 kB +out/renderer/assets/nextflow-groovy-D4ZyOBoZ-C7jziUwg.js 10.63 kB +out/renderer/assets/dream-maker-5oXa1Z51-CLRrQkBL.js 10.67 kB +out/renderer/assets/ts-tags-xeTAUNHG-CG_gr3En.js 10.70 kB +out/renderer/assets/raku-Bfr41qeN-C7t9XlCj.js 10.72 kB +out/renderer/assets/mysql-CZJtil0v-CP4gK9vT.js 10.73 kB +out/renderer/assets/task-menu-icons-BRdNqJF0.js 10.78 kB +out/renderer/assets/prism-csharp-D9xOwbIN.js 10.91 kB +out/renderer/assets/yaml-CsitfczK-Cu7vbJZs.js 10.97 kB +out/renderer/assets/diagram-UQ7AKVKN-B1EaevB-.js 11.05 kB +out/renderer/assets/elm-Dl1XrIiD-CwXBAFKd.js 11.18 kB +out/renderer/assets/just-He7qscmV-Bkq-0zku.js 11.19 kB +out/renderer/assets/redshift-Djb4PK3z-9Ar4PFWD.js 11.35 kB +out/renderer/assets/github-light-B_J7N1HZ-DWSXFnsf.js 11.38 kB +out/renderer/assets/ruby-CxOCB7_P-BzsjPJ6Z.js 11.48 kB +out/renderer/assets/prolog-DAqMMM08-BFKdnH0S.js 11.56 kB +out/renderer/assets/terraform-BW8B2WXV-zeRjs0zr.js 11.59 kB +out/renderer/assets/github-dark-BgqEY2WG-C9QbkZU3.js 11.60 kB +out/renderer/assets/puppet-CaR8DEdW-Biai9WKX.js 11.65 kB +out/renderer/assets/pkl-DrXR3Dxy-Bno7kqPT.js 11.67 kB +out/renderer/assets/laserwave-Clkc4Pj8-DOjuqF9n.js 11.69 kB +out/renderer/assets/pieDiagram-E7YTZNPT-BwiXBDwO.js 11.95 kB +out/renderer/assets/rst-BJFdabDk-Cv-fSo2B.js 12.04 kB +out/renderer/assets/linear-WS155L0r.js 12.11 kB +out/renderer/assets/wasm-DYwNZ-r4-BrA6oOvM.js 12.21 kB +out/renderer/assets/hjson-CmvCiVhY-BdH9CbZ2.js 12.25 kB +out/renderer/assets/razor-D5kquflS-CWY5AfCS.js 12.39 kB +out/renderer/assets/abap-BJyKdrbp-hWIyERPx.js 12.52 kB +out/renderer/assets/handlebars-B1z64YSt-MC-VEvxc.js 12.52 kB +out/renderer/assets/apache-BUbWdjM2-2Zu7IlVl.js 12.66 kB +out/renderer/assets/vesper-B5lCMuIY-CXGQHRuW.js 12.88 kB +out/renderer/assets/pgsql-BYm17UA1-Cvj1smQI.js 12.93 kB +out/renderer/assets/protobuf-BOGxqb2m-yTWn-oM_.js 12.98 kB +out/renderer/assets/bat-D2y8Uewi-CEJzP2ue.js 13.09 kB +out/renderer/assets/fish-CaZR_ofm-BcO_q5kQ.js 13.24 kB +out/renderer/assets/elixir-Lipcswxh-DnZCznfr.js 13.27 kB +out/renderer/assets/v-wnWoBHkK-CzCOTyIp.js 13.41 kB +out/renderer/assets/AboutHelpSettingsPanel-Ui_VOvh7.js 13.48 kB +out/renderer/assets/vitesse-light-DQXFiRFx-Ct7fN8pJ.js 13.81 kB +out/renderer/assets/aurora-x-9vUYYjHV-CImifmUW.js 13.85 kB +out/renderer/assets/vitesse-black-cwK5rWgD-BGrq81WC.js 13.87 kB +out/renderer/assets/vitesse-dark-CsfgW0oH-Dx8cqxrm.js 13.96 kB +out/renderer/assets/ShortcutsSettingsPanel-KgJeI7QZ.js 14.15 kB +out/renderer/assets/pug-D0UckVoV-BTWU19Nk.js 14.16 kB +out/renderer/assets/synthwave-84-LX1B8mRG-yuUErnSx.js 14.23 kB +out/renderer/assets/github-light-default-BRmIzqWc-B3gMi7zW.js 14.36 kB +out/renderer/assets/clarity-AxkJPY5c-DfVHSVIk.js 14.48 kB +out/renderer/assets/github-light-high-contrast-BUKIZOxn-DL0r2b0z.js 14.49 kB +out/renderer/assets/github-dark-dimmed-DoIdqTey-CDc6YqEM.js 14.64 kB +out/renderer/assets/github-dark-default-CwWjzI40-_0bgyJYv.js 14.64 kB +out/renderer/assets/chunk-PWAF6VOD-DUCy2J9a.js 14.76 kB +out/renderer/assets/github-dark-high-contrast-bFLNMLvK-BUp3HmXY.js 14.80 kB +out/renderer/assets/diagram-S7CK7UJ4-DZ0Sug9N.js 14.98 kB +out/renderer/assets/gnuplot-Dw3FRha5-D6o75ylb.js 14.98 kB +out/renderer/assets/rust-C0Ih6nmc-Bm01RMLz.js 15.27 kB +out/renderer/assets/actionscript-3-O8jnLcvn-C7OtofMN.js 15.41 kB +out/renderer/assets/luau-BzxGbjcn-aQpsBeQB.js 15.64 kB +out/renderer/assets/nix-zl191KBb-CxSq6jsB.js 15.85 kB +out/renderer/assets/lua-BwTLfNCK-IuSxl8fO.js 16.04 kB +out/renderer/assets/abap-FvPUHv8B-BVQp86jh.js 16.05 kB +out/renderer/assets/solidity-96fhzG-Q-CZEni-ZB.js 16.28 kB +out/renderer/assets/matlab-8ZQqHKQX-g_ODc8QU.js 16.29 kB +out/renderer/assets/cue-eHSfcyUV-BO0bCEDm.js 16.40 kB +out/renderer/assets/kusto-D8vBBISG-C0y2Wtyy.js 16.45 kB +out/renderer/assets/powerquery-B7BjLMcF-BkVSWPtX.js 16.49 kB +out/renderer/assets/elixir-B1NaQxrO-Ba6X-FuW.js 16.50 kB +out/renderer/assets/react-DrereneL.js 16.50 kB +out/renderer/assets/odin-B-YqhW9I-B-ZI05Ll.js 16.71 kB +out/renderer/assets/solidity-Dpt2BLAA-BD_YSA0r.js 16.98 kB +out/renderer/assets/bird2-BMkLvc4r-CyoW3El7.js 17.17 kB +out/renderer/assets/kanagawa-wave-CM_o6oKV-VzWuxPSA.js 17.32 kB +out/renderer/assets/kanagawa-lotus-Cj3XDpoG-cmeMwVaD.js 17.32 kB +out/renderer/assets/kanagawa-dragon-D_NPnIy_-Cyd8MANv.js 17.33 kB +out/renderer/assets/cynefinDiagram-5FMLGOSQ-DUo_T9ft.js 17.61 kB +out/renderer/assets/stateDiagram-D77RDMKH-BbeuRtup.js 18.11 kB +out/renderer/assets/chunk-L3NEJ4N5-BZPl6K5u.js 18.16 kB +out/renderer/assets/liquid-D_7zu7XR-BZ3z6-Mj.js 18.46 kB +out/renderer/assets/svelte-DUGqPubT-CAfIEh4G.js 18.60 kB +out/renderer/assets/graphql-ObxcfEHH-9pUo2yjR.js 18.65 kB +out/renderer/assets/jsonMode-DdQpkp6D-CRQw31fq.js 18.79 kB +out/renderer/assets/material-theme-q28j4V_0-s4HtqlFv.js 18.81 kB +out/renderer/assets/material-theme-ocean-DAvlEnSm-Cyw7qD-l.js 18.83 kB +out/renderer/assets/material-theme-darker-CHEuMVX9-D-hz3EEt.js 18.83 kB +out/renderer/assets/material-theme-lighter-DY4T1_JG-C0HwKluR.js 18.84 kB +out/renderer/assets/material-theme-palenight-CqDFvQ-v-RoTowTME.js 18.84 kB +out/renderer/assets/gherkin-BcjDDslM-BdnbjalD.js 19.20 kB +out/renderer/assets/gdscript-CekKc1U_-DVmAmHvE.js 19.21 kB +out/renderer/assets/groovy-DH3arekX-StnUgJL0.js 19.38 kB +out/renderer/assets/mdc-D-U85KZE-DPbAVRTg.js 19.85 kB +out/renderer/assets/diagram-VSXAHHWV-CbmzU86w.js 20.01 kB +out/renderer/assets/move-CmExnPjU-DPj_eIaE.js 20.22 kB +out/renderer/assets/ayu-dark-BeByMiYw-CS3MEELg.js 20.27 kB +out/renderer/assets/ayu-mirage-C1jJ6Jfs-CnA8kJ7r.js 20.28 kB +out/renderer/assets/ayu-light-DmTZeN54-CDULCKqM.js 20.35 kB +out/renderer/assets/glimmer-js-D9ZnrcNN-BS431Ogg.js 20.44 kB +out/renderer/assets/glimmer-ts-DuhFj6qR-CsFesiaT.js 20.44 kB +out/renderer/assets/viml-DPVJ_KYe-De3CdqgJ.js 20.56 kB +out/renderer/assets/nushell-Cd8Dwa1M-Dhf9XkYz.js 20.62 kB +out/renderer/assets/snazzy-light-B8znOqT6-B1FX3-IF.js 20.97 kB +out/renderer/assets/dagre-GXQ25YYZ-_SHLHEAK.js 21.01 kB +out/renderer/assets/dracula-DeMffiYO-Bl4juROY.js 21.26 kB +out/renderer/assets/dracula-soft-BnfvpcDv-CYsUeSum.js 21.27 kB +out/renderer/assets/twig-7zjsCqYg-CMujKsZl.js 21.44 kB +out/renderer/assets/freemarker2-enkimFXA-0bWMkoTL.js 21.73 kB +out/renderer/assets/PersonalizationSettingsPanel-B06BA6F_.js 21.87 kB +out/renderer/assets/rose-pine-CEVQiaW0-DaA_4NNK.js 21.94 kB +out/renderer/assets/rose-pine-moon-B9bum7Ik-B6_AhIsD.js 21.96 kB +out/renderer/assets/rose-pine-dawn-2Q5fMoJp-DxMkAwKM.js 21.96 kB +out/renderer/assets/powershell-ycAdP1r9-B7r4Hnhz.js 22.11 kB +out/renderer/assets/common-lisp-DcFHcTKh-CWH5diwh.js 22.81 kB +out/renderer/assets/gruvbox-dark-hard-gOzMLqif-DDlcfu4q.js 22.83 kB +out/renderer/assets/gruvbox-dark-soft-CKvURktN-C6MJezBg.js 22.83 kB +out/renderer/assets/gruvbox-light-hard-CMa_c48J-BUQ67Msp.js 22.84 kB +out/renderer/assets/gruvbox-light-soft-yfAGJYsX-DNM2qqWB.js 22.84 kB +out/renderer/assets/gruvbox-dark-medium-BQSVGwWb-qh8C4DPZ.js 22.84 kB +out/renderer/assets/gruvbox-light-medium-B9S5UNr1-DZxV_o-P.js 22.84 kB +out/renderer/assets/nim-CD961Jl3-CuyTrDpQ.js 22.91 kB +out/renderer/assets/cadence-C2JmJjDr-B-b63Epg.js 23.87 kB +out/renderer/assets/sql-C_oMiPb0-CRnSOxMo.js 23.87 kB +out/renderer/assets/wit-CXpQol8Q-D2NEDOhy.js 24.11 kB +out/renderer/assets/templ-gFcHJbF7-BqIwRUQe.js 24.38 kB +out/renderer/assets/astro-kV3HjkbP-CH6o6jKA.js 24.46 kB +out/renderer/assets/vhdl-Ci4REirV-D-qSzcJD.js 24.46 kB +out/renderer/assets/purescript-DCsDAdnX-DsynrkKe.js 24.97 kB +out/renderer/assets/vue-Cuk7Vimg-CFbFXIr8.js 25.25 kB +out/renderer/assets/surrealql-GFjNBdcm-Vm68TOTE.js 25.34 kB +out/renderer/assets/one-light-CMfGrl_P-B-1jUQM9.js 25.49 kB +out/renderer/assets/night-owl-light-CAEa42tO-TPCLv7z5.js 26.10 kB +out/renderer/assets/system-verilog-D_bVVpLE-C_dvOlr3.js 26.41 kB +out/renderer/assets/angular-html-BrLPO2Fv-DJgz5E5d.js 26.48 kB +out/renderer/assets/typespec-D5WYs8C4-AaOHagqW.js 26.72 kB +out/renderer/assets/nord-DlCAGdjr-Div2jUYm.js 26.91 kB +out/renderer/assets/codeql-DidIlXer-D6RBJOzg.js 27.08 kB +out/renderer/assets/scss-BhK8Ovpn-DfDLQi2C.js 27.52 kB +out/renderer/assets/coffee-DrMWXxy6-BoavQsuh.js 27.68 kB +out/renderer/assets/java-DaupjRFz-zQd9RZAc.js 27.69 kB +out/renderer/assets/razor-B2hRAVmz-Dj7TOgY5.js 27.72 kB +out/renderer/assets/apl-C42PBett-BNW4FTmO.js 27.87 kB +out/renderer/assets/chunk-SVP7TREG-BJrMMBGT.js 28.38 kB +out/renderer/assets/fsharp-BHFgIxsY-CvR6tsY8.js 28.48 kB +out/renderer/assets/marko-DXKHPFnH-C0z2-ucz.js 28.74 kB +out/renderer/assets/GeneralSettingsPanel-CA6yOnsk.js 29.10 kB +out/renderer/assets/night-owl-DegwdXaM-6ZGfBB7K.js 29.11 kB +out/renderer/assets/c3-BOs4FlGA-BuhFXrRY.js 29.17 kB +out/renderer/assets/MemorySettingsPanel-cqwWfj-O.js 29.75 kB +out/renderer/assets/crystal-DlzoxO28-BWa_t1Io.js 29.84 kB +out/renderer/assets/applescript-ij24h7OO-_xHQcvud.js 29.87 kB +out/renderer/assets/tsMode-SiG-Sp2b-DB8xZUGJ.js 30.55 kB +out/renderer/assets/pierre-dark-Daa2n9wr-D7rla9B_.js 30.74 kB +out/renderer/assets/pierre-light-D_hZXvUj-DJnIOKLO.js 30.75 kB +out/renderer/assets/pierre-dark-soft-BhNM3pgh-Dp_VeHWv.js 30.76 kB +out/renderer/assets/pierre-light-soft-BVrSv6ZG-C6Na39F-.js 30.76 kB +out/renderer/assets/ishikawaDiagram-5VMMS53U-D5VU_Gfi.js 30.78 kB +out/renderer/assets/pierre-dark-tritanopia-CGKuoAZi-C0HpbU3l.js 30.78 kB +out/renderer/assets/pierre-light-tritanopia-BiDEaWaH-wWduIsi3.js 30.78 kB +out/renderer/assets/pierre-dark-protanopia-deuteranopia-Cs1lz9lE-enlgPsHw.js 30.82 kB +out/renderer/assets/pierre-light-protanopia-deuteranopia-BM0RLBB_-Dz5iBHkO.js 30.82 kB +out/renderer/assets/stylus-ZCryC73G-urFW3_yk.js 31.29 kB +out/renderer/assets/diagram-VX7I27RA-uopNEQPp.js 31.44 kB +out/renderer/assets/scala-BBsC3Oz3-VCjyobQG.js 31.48 kB +out/renderer/assets/mermaid-D6CQfUGU-C6DHNxVz.js 33.37 kB +out/renderer/assets/poimandres-EIt_jotH-DHKFQj5Q.js 33.69 kB +out/renderer/assets/kanban-definition-UXKFOSKX-DFn9PSNU.js 33.91 kB +out/renderer/assets/one-dark-pro-DR9QpZM3-BA4d4lw2.js 33.98 kB +out/renderer/assets/mermaid-parser.core-CstzWfPU.js 34.66 kB +out/renderer/assets/haxe-BWT5wSyZ-BuUsQb-h.js 35.38 kB +out/renderer/assets/nginx-DhtViCEk-C18zABFg.js 35.58 kB +out/renderer/assets/houston-BdS5A_yD-NUige_z1.js 35.61 kB +out/renderer/assets/tokyo-night-BS1_DFu7-CYsPn2J-.js 35.86 kB +out/renderer/assets/erlang-Dd62d0xZ-DHVWwcKa.js 37.71 kB +out/renderer/assets/rough.esm-BX5QqLti.js 38.33 kB +out/renderer/assets/mindmap-definition-YA3MSWOX-Beo2z6Zl.js 38.59 kB +out/renderer/assets/cobol-D7RZfOK--CEk2iYO9.js 39.37 kB +out/renderer/assets/journeyDiagram-3NMN7TZE-D1O_nld8.js 40.13 kB +out/renderer/assets/julia-ZzkUXm0W-BIm_zTAN.js 40.32 kB +out/renderer/assets/lspLanguageFeatures-DK9zifhE-DeEqLmGO.js 40.76 kB +out/renderer/assets/asm-DYVIzeEk-Byg5xzam.js 40.91 kB +out/renderer/assets/haskell-Ba6HbLj8-D0OYaIy8.js 41.78 kB +out/renderer/assets/sankeyDiagram-P5KCCOFB-8RQXHBl8.js 41.83 kB +out/renderer/assets/shellscript-B69gKcss-49Zm6IyC.js 41.97 kB +out/renderer/assets/wardleyDiagram-VM6X3IG4-BulU0_1W.js 42.40 kB +out/renderer/assets/perl-Dv6Cq_FS-DIORmO5G.js 43.55 kB +out/renderer/assets/pierre-dark-vibrant-BMsyYliQ-84Eeh-Uj.js 44.96 kB +out/renderer/assets/pierre-light-vibrant-CWzM4Pa_-QZvTkTJe.js 44.97 kB +out/renderer/assets/ruby-DWcdJvcx-q0K84ieK.js 46.50 kB +out/renderer/assets/go-BOpYl7fu-BiT4MB-v.js 47.02 kB +out/renderer/assets/apex-B48ZHHzN-BBt8sSNQ.js 47.18 kB +out/renderer/assets/catppuccin-mocha-cPsH7Lup-SVLZehhk.js 47.46 kB +out/renderer/assets/catppuccin-latte-DcEecI7n-jo2cPJyK.js 47.46 kB +out/renderer/assets/catppuccin-frappe-BdOW2tdI-BI0Hc9cS.js 47.46 kB +out/renderer/assets/catppuccin-macchiato-Bvz_yAZY-DWewRa4S.js 47.47 kB +out/renderer/assets/ada-BT0j8ine-CLTLBE8n.js 48.28 kB +out/renderer/assets/d-B1HbH29p-Bi6t8Ck6.js 49.10 kB +out/renderer/assets/css-NFwnoVns-BvwuZkcY.js 49.49 kB +out/renderer/assets/imba-C-oGt11l-CqKI0OVw.js 50.13 kB +out/renderer/assets/requirementDiagram-BXWQKSXE-BW3eBKn6.js 51.39 kB +out/renderer/assets/erDiagram-RLTQ6QDP-CRW8KnKL.js 52.41 kB +out/renderer/assets/browserify-C9uP_nIr.js 52.80 kB +out/renderer/assets/gitGraphDiagram-WWUBYQGX-SNvwtaLo.js 53.82 kB +out/renderer/assets/everforest-dark-gCM8XhEI-DzRrg06U.js 53.94 kB +out/renderer/assets/everforest-light-DhK35DkL-BEDtvHw1.js 53.95 kB +out/renderer/assets/timeline-definition-24CTP7MA-DHkWKYwu.js 54.31 kB +out/renderer/assets/wikitext-CQNrXTmv-DJ18wIlO.js 56.09 kB +out/renderer/assets/stata-BUONSdsT-BPnapjPC.js 57.23 kB +out/renderer/assets/quadrantDiagram-AXDQQJYC-DF0YuDtz.js 58.21 kB +out/renderer/assets/html-Dq1ixqYb-okJOhOmu.js 58.25 kB +out/renderer/assets/chunk-OSK3NFVY-B3NvnB1z.js 58.56 kB +out/renderer/assets/ocaml-CUdGm1iq-BKX30YEX.js 62.65 kB +out/renderer/assets/model-settings-source-JYisGYmM.js 63.03 kB +out/renderer/assets/ballerina-CpYcPBJI-D9ac3462.js 64.89 kB +out/renderer/assets/markdown-BSrOIEaF-BFwOzGIM.js 65.52 kB +out/renderer/assets/chunk-IMKFNOWR-BIe7x3W7.js 67.22 kB +out/renderer/assets/mojo-BNaitZ-7-E_psDM2x.js 70.00 kB +out/renderer/assets/python-Cld0Iwtn-tcCJ5L_g.js 70.17 kB +out/renderer/assets/blockDiagram-I7D4REHJ-CyHqCc1n.js 71.01 kB +out/renderer/assets/bsl-CtP8370o-Pi14XlIU.js 71.07 kB +out/renderer/assets/c-B4augMcT-B5ncIjy5.js 72.57 kB +out/renderer/assets/chunk-75Z2AOVW-BnN-mv3P.js 72.67 kB +out/renderer/assets/latex-g2Pus_l2-CP0G7LTN.js 72.85 kB +out/renderer/assets/vyper-C1nscAY5-BTAKd5p2.js 74.85 kB +out/renderer/assets/ModelSettingsPanel-Bq69xf7M.js 76.64 kB +out/renderer/assets/xychartDiagram-S5SC5T6Z-B0HnmiNK.js 76.79 kB +out/renderer/assets/chunk-GMAD6QVW-B_AU-1G2.js 77.76 kB +out/renderer/assets/hack-B1ag3l4X-CEYIfPfg.js 80.58 kB +out/renderer/assets/src-DsgKm1PY.js 83.16 kB +out/renderer/assets/chunk-TICWLB2K-HMkllssg.js 83.88 kB +out/renderer/assets/fortran-free-form-CsgtTAg3-Dm0PhuY8.js 89.20 kB +out/renderer/assets/vennDiagram-4TSXK5OY-4fpVJ9Np.js 89.26 kB +out/renderer/assets/csharp-YOPVljXo-CBjcozlW.js 89.91 kB +out/renderer/assets/racket--xYIV9-n-NDM2V4Sc.js 92.62 kB +out/renderer/assets/swift-CgzYrGBX-CaMD6i-j.js 94.14 kB +out/renderer/assets/less-BGhX8xko-CbSvNyvq.js 99.00 kB +out/renderer/assets/chunk-SHT3W25Y-2hntSx1_.js 104.10 kB +out/renderer/assets/objective-c-CmcWiAft-DY5tZuMk.js 105.62 kB +out/renderer/assets/blade-Bq8WPf0E-BehdttJf.js 105.98 kB +out/renderer/assets/c4Diagram-7LVT6UL2-BUPZp1Fb.js 107.96 kB +out/renderer/assets/php-X15vsN4N-ChBJUzAp.js 111.49 kB +out/renderer/assets/dagre-CzI-C3sx.js 122.98 kB +out/renderer/assets/ganttDiagram-EL5Y4UJY-3y2lEktC.js 123.77 kB +out/renderer/assets/graphlib-CoAzpIqe.js 127.44 kB +out/renderer/assets/asciidoc-DJWalVNM-Daa-Gl9r.js 146.30 kB +out/renderer/assets/mdx-C_Ato9sK-CDV72_N0.js 146.49 kB +out/renderer/assets/editor.main-POO0Vbhx-D31yi93c.js 161.32 kB +out/renderer/assets/cose-bilkent-JH36ORCC-CA60tZpq.js 165.63 kB +out/renderer/assets/objective-cpp-BggTCHV8-BRaaCyEF.js 172.18 kB +out/renderer/assets/javascript-AfZCJ9Uc-C_GZREFb.js 175.31 kB +out/renderer/assets/tsx-BOlKGefW-D7XVyutE.js 176.00 kB +out/renderer/assets/jsx-CPd9p36x-D5Ck2u9I.js 178.26 kB +out/renderer/assets/sequenceDiagram-WJ2MYXX4-D7FeprQ0.js 190.05 kB +out/renderer/assets/typescript-4sRsPriL-Ce01imBq.js 191.16 kB +out/renderer/assets/mermaid.core-_tuT8V40.js 191.57 kB +out/renderer/assets/angular-ts-YduEkmVa-936ueej5.js 193.82 kB +out/renderer/assets/vue-vine-DXhYlaTf-C8MW7tnI.js 201.27 kB +out/renderer/assets/SourceSelect-Dd7kI5iL.js 203.20 kB +out/renderer/assets/chunk-4HAMMTFA-BusRJl4_.js 210.32 kB +out/renderer/assets/swimlanes-42K2YHIH-7v_MGc-X.js 265.51 kB +out/renderer/assets/wolfram-BVoTES0L-W3A5YqXk.js 267.14 kB +out/renderer/assets/chunk-DU6HZSFF-ev5NGQFs.js 271.07 kB +out/renderer/assets/architectureDiagram-5GKGNRK7-BLwHQNCJ.js 318.23 kB +out/renderer/assets/katex-Y9ra-ykP.js 497.35 kB +out/renderer/assets/texmath-Bkeg3ZLn.js 594.25 kB +out/renderer/assets/wasm-CVjZL0jK-DcJkdGs4.js 622.62 kB +out/renderer/assets/cpp-9jHBA231-DB3feGjZ.js 626.73 kB +out/renderer/assets/app-4914IQSi.js 675.57 kB +out/renderer/assets/emacs-lisp-DjtOxg4j-CzQ0CKOn.js 780.06 kB +out/renderer/assets/cytoscape.esm-bVGYt-iW.js 869.69 kB +out/renderer/assets/ArtifactPierreDiff-DpqRTCz8.js 1,119.58 kB +out/renderer/assets/chunk-FOHPRMQF-BCllzKJD.js 1,154.18 kB +out/renderer/assets/index-Bk2r1j2x.js 3,761.37 kB +out/renderer/assets/editor.api2-dPwET-7w-BYIQ9bT3.js 4,889.23 kB + +✓ built in 2.31s diff --git a/docs/协作/evidence/B02-review-01/dom-report.json b/docs/协作/evidence/B02-review-01/dom-report.json new file mode 100644 index 0000000..7ae01cb --- /dev/null +++ b/docs/协作/evidence/B02-review-01/dom-report.json @@ -0,0 +1,70 @@ +{ + "result": "PASS", + "checks": [ + "uninstalled uses add slot", + "normal footer removed from DOM", + "current uses installed CardFrame", + "current removes Plus/add DOM", + "current use occupies status slot exactly once", + "use invokes one draft callback without installation", + "use does not open install detail", + "top nav count reflects installed list", + "reopen retains current state", + "enable failure prevents draft invocation", + "disabled skill enabled before callback", + "non-invocable current cannot use or reinstall", + "outdated installed identity distinction", + "outdated not represented as first add", + "outdated requires explicit confirmation", + "modified installed identity distinction", + "modified not represented as first add", + "modified requires explicit confirmation", + "broken installed identity distinction", + "broken not represented as first add", + "broken requires explicit confirmation", + "same-name local installed identity distinction", + "same-name local not represented as first add", + "same-name local requires explicit confirmation", + "broken same-name local installed identity distinction", + "broken same-name local not represented as first add", + "broken same-name local requires explicit confirmation", + "different source installed identity distinction", + "different source not represented as first add", + "different source requires explicit confirmation", + "workspace is not treated as managed current", + "external current while confirming prevents duplicate installation", + "first install confirms provenance and scripts", + "duplicate confirmation issues only one request", + "real host progress rendered", + "install success automatically switches action DOM", + "external uninstall restores add", + "external install blocks new add", + "external terminal progress clears block", + "unavailable has no duplicate installed entry", + "catalog retry recovers in place", + "empty catalog has no footer", + "SkillHub has only top installed navigation", + "套件 has only top installed navigation", + "no uncaught renderer errors" + ], + "calls": [ + [ + "enable", + "user:rec" + ], + [ + "enable", + "user:rec" + ], + [ + "install", + "archify", + { + "operationId": "c4b39eb6-c00b-423a-8c37-8446f6c787bd", + "overwrite": false + } + ] + ], + "errors": [], + "limits": "Real React in offline jsdom; callback boundary tested, not production composer dispatch. No native Chromium, computed layout, screenshot, theme/hover/focus pixels, model SDK, actual install or network." +} \ No newline at end of file diff --git a/docs/协作/evidence/B02-review-01/dom.txt b/docs/协作/evidence/B02-review-01/dom.txt new file mode 100644 index 0000000..d44545f --- /dev/null +++ b/docs/协作/evidence/B02-review-01/dom.txt @@ -0,0 +1,5 @@ + +> ycode@0.0.7 test:recommended-skills:dom +> node scripts/test-recommended-skills-dom.mjs + +{"result":"PASS","checks":45,"output":"C:\\Users\\Administrator\\.codex\\worktrees\\b02-accept-01\\YCode\\.tmp\\recommended-skills-dom-lBbu5l"} diff --git a/docs/协作/evidence/B02-review-01/hover-control.json b/docs/协作/evidence/B02-review-01/hover-control.json new file mode 100644 index 0000000..6213352 --- /dev/null +++ b/docs/协作/evidence/B02-review-01/hover-control.json @@ -0,0 +1,6 @@ +{ + "matches": false, + "background": "rgb(50, 60, 70)", + "hit": "qa-hover-control", + "hovered": 0 +} \ No newline at end of file diff --git a/docs/协作/evidence/B02-review-01/hover-diagnostics.json b/docs/协作/evidence/B02-review-01/hover-diagnostics.json new file mode 100644 index 0000000..89e97eb --- /dev/null +++ b/docs/协作/evidence/B02-review-01/hover-diagnostics.json @@ -0,0 +1,36 @@ +{ + "theme": "light", + "normal": { + "width": "24px", + "height": "24px", + "background": "rgba(0, 0, 0, 0)", + "color": "rgb(0, 0, 0)", + "outline": "rgb(0, 0, 0) none 0px", + "focused": false, + "hover": false + }, + "hover": { + "width": "24px", + "height": "24px", + "background": "rgb(230, 230, 230)", + "color": "rgb(0, 0, 0)", + "outline": "rgb(0, 0, 0) none 0px", + "focused": false, + "hover": false + }, + "probe": { + "button": "", + "buttonStyle": { + "pointerEvents": "auto", + "display": "flex", + "visibility": "visible" + }, + "point": { + "x": 315, + "y": 157 + }, + "hit": " ycode@0.0.7 test:recommended-skills:ui +> node scripts/test-recommended-skills-ui.mjs + + +(electron) 'console-message' arguments are deprecated and will be removed. Please use Event object instead. +AssertionError [ERR_ASSERTION]: light pointer enters use action: false + at check (file:///C:/Users/Administrator/.codex/worktrees/b02-accept-01/YCode/scripts/test-recommended-skills-ui.mjs:180:14) + at verifyCurrentActionStyles (file:///C:/Users/Administrator/.codex/worktrees/b02-accept-01/YCode/scripts/test-recommended-skills-ui.mjs:210:7) + at async file:///C:/Users/Administrator/.codex/worktrees/b02-accept-01/YCode/scripts/test-recommended-skills-ui.mjs:270:7 { + generatedMessage: false, + code: 'ERR_ASSERTION', + actual: false, + expected: true, + operator: '==', + diff: 'simple' +} diff --git a/docs/协作/evidence/B02-review-01/pointer-ui-probe.mjs b/docs/协作/evidence/B02-review-01/pointer-ui-probe.mjs new file mode 100644 index 0000000..ce84adc --- /dev/null +++ b/docs/协作/evidence/B02-review-01/pointer-ui-probe.mjs @@ -0,0 +1,417 @@ +/** Isolated Electron fixture for the recommended-skill page. + * The host is fully controlled: no network, no real skill storage, no user data. */ +import fs from 'node:fs' +import path from 'node:path' +import assert from 'node:assert/strict' +import { createRequire } from 'node:module' +import { spawn } from 'node:child_process' + +const require = createRequire(import.meta.url) +const electronModule = require('electron') +const electron = typeof electronModule === 'object' && electronModule.app ? electronModule : null +const repository = path.resolve('.'), base = path.join(repository, '.tmp') + +if (!electron) { + fs.mkdirSync(base, { recursive: true }) + const output = fs.mkdtempSync(path.join(base, 'recommended-skills-ui-')) + const env = { ...process.env } + delete env.ELECTRON_RUN_AS_NODE + delete env.ELECTRON_RENDERER_URL + const child = spawn(electronModule, [path.resolve('.tmp/b02-acceptance/recommended-skills-ui-pointer.mjs'), output], { stdio: 'inherit', windowsHide: true, env }) + const timer = setTimeout(() => child.kill(), 120000) + process.exitCode = await new Promise(resolve => child.on('exit', code => { clearTimeout(timer); resolve(code ?? 1) })) +} else { + void (async () => { + const { app, BrowserWindow, ipcMain } = electron + const output = path.resolve(process.argv.at(-1)), relative = path.relative(base, output) + assert.ok(relative.startsWith('recommended-skills-ui-') && !relative.includes('..') && !path.isAbsolute(relative)) + const userData = path.join(output, 'data') + fs.mkdirSync(userData, { recursive: true }) + app.setPath('userData', userData) + const checks = [], errors = [], calls = [], screenshots = [], actionStyles = [] + + const recommendation = { + id: 'archify', + name: 'Archify', + description: '生成可交互的架构图、流程图和一页式说明', + author: 'tt-a1i', + license: 'MIT', + repository: 'tt-a1i/archify', + version: '3.2.0', + commit: '25cf37080fc8b1dbe758a4efc3935b55f3327083', + packagePath: 'archify.zip', + sha256: '70e210265c59f24dcbdf2a502ff671104b5454e7ee7d3554aecd86bad32384f5', + expectedBytes: 5271959, + containsScripts: true + } + const localSkill = { + id: 'user:local', name: 'Archify', description: '本地导入的同名技能', version: '1.0.0', + path: 'C:/local/archify', scope: 'user', enabled: true, userInvocable: true, + disableModelInvocation: false, source: 'imported', userModified: true + } + const installedRecommendation = { + id: 'user:rec', name: 'Archify', description: recommendation.description, version: '3.2.0', + path: 'C:/managed/archify', scope: 'user', enabled: true, userInvocable: true, + disableModelInvocation: false, source: 'imported', userModified: false, + origin: { + recommendationId: 'archify', repository: recommendation.repository, commit: recommendation.commit, + packagePath: recommendation.packagePath, archiveSha256: recommendation.sha256, version: '3.2.0', installedAt: 1 + } + } + + let installed = [], progress = null, failNext = false, cancelRequested = false, delay = 0, recommendationOverride = null, recommendationFails = false + let clock = 0 + const listeners = new Set(), changedListeners = new Set() + const emit = state => { + // The host stamps a monotonic time; a strict comparison rejects a stale frame. + const stamped = { ...state, updatedAt: ++clock } + progress = stamped + for (const listener of listeners) listener(stamped) + for (const win of BrowserWindow.getAllWindows()) if (!win.isDestroyed()) win.webContents.send('skills:install-progress', stamped) + } + const changed = () => { + for (const listener of changedListeners) listener() + for (const win of BrowserWindow.getAllWindows()) if (!win.isDestroyed()) win.webContents.send('skills:changed') + } + + ipcMain.handle('skills-qa', async (_event, method, args) => { + calls.push([method, ...args]) + if (method === 'recommendations') { + if (recommendationFails) throw Error('推荐目录服务不可用') + return recommendationOverride ?? [recommendation] + } + if (method === 'list') return installed + if (method === 'setEnabled') { installed = installed.map(skill => skill.id === args[0] ? { ...skill, enabled: args[1] } : skill); changed(); return } + if (method === 'installState') return progress + // The host only accepts the cancel request; the terminal frame still comes from the install flow. + if (method === 'cancelInstall') { cancelRequested = true; return { cancelled: true } } + if (method === 'installRecommended') { + const [id, options] = args + if (id !== recommendation.id) throw Error('未知推荐技能') + if (failNext) { + failNext = false + emit({ operationId: options.operationId, recommendationId: id, phase: 'failed', receivedBytes: 0, error: '下载失败:网络错误', updatedAt: Date.now() }) + throw Error('下载失败:网络错误') + } + emit({ operationId: options.operationId, recommendationId: id, phase: 'downloading', receivedBytes: 0, totalBytes: recommendation.expectedBytes, updatedAt: Date.now() }) + await new Promise(resolve => setTimeout(resolve, delay)) + if (cancelRequested) { cancelRequested = false; emit({ operationId: options.operationId, recommendationId: id, phase: 'cancelled', receivedBytes: 0, updatedAt: Date.now() }); throw Object.assign(Error('推荐技能安装已取消'), { name: 'AbortError' }) } + emit({ operationId: options.operationId, recommendationId: id, phase: 'validating', receivedBytes: recommendation.expectedBytes, totalBytes: recommendation.expectedBytes, updatedAt: Date.now() }) + await new Promise(resolve => setTimeout(resolve, delay)) + if (cancelRequested) { cancelRequested = false; emit({ operationId: options.operationId, recommendationId: id, phase: 'cancelled', receivedBytes: recommendation.expectedBytes, updatedAt: Date.now() }); throw Object.assign(Error('推荐技能安装已取消'), { name: 'AbortError' }) } + emit({ operationId: options.operationId, recommendationId: id, phase: 'installing', receivedBytes: recommendation.expectedBytes, totalBytes: recommendation.expectedBytes, updatedAt: Date.now() }) + await new Promise(resolve => setTimeout(resolve, delay)) + installed = [installedRecommendation] + emit({ operationId: options.operationId, recommendationId: id, phase: 'installed', receivedBytes: recommendation.expectedBytes, totalBytes: recommendation.expectedBytes, updatedAt: Date.now() }) + changed() + return installedRecommendation + } + if (method === 'qaSetInstalled') { installed = args[0]; changed(); return installed } + if (method === 'qaFailNext') { failNext = true; return true } + if (method === 'qaDelay') { delay = args[0]; return true } + if (method === 'qaSetRecommendations') { recommendationOverride = args[0]; return true } + if (method === 'qaFailRecommendations') { recommendationFails = args[0] === true; return true } + // Simulate an operation owned by another window. + if (method === 'qaEmitForeign') { + const [phase, operationId] = args + emit({ operationId, recommendationId: recommendation.id, phase, receivedBytes: 0, totalBytes: recommendation.expectedBytes, updatedAt: Date.now() }) + return true + } + // Replay a frame with an older timestamp to prove the terminal state never regresses. + if (method === 'qaEmitStale') { + const [phase, operationId, updatedAt] = args + const stamped = { operationId, recommendationId: recommendation.id, phase, receivedBytes: 0, totalBytes: recommendation.expectedBytes, updatedAt } + progress = stamped + for (const listener of listeners) listener(stamped) + for (const win of BrowserWindow.getAllWindows()) if (!win.isDestroyed()) win.webContents.send('skills:install-progress', stamped) + return true + } + if (method === 'qaSubscribe') { listeners.add(args[0]); return true } + if (method === 'qaSubscribeChanged') { changedListeners.add(args[0]); return true } + throw Error('Unknown QA method ' + method) + }) + + fs.writeFileSync(path.join(output, 'preload.cjs'), `const{contextBridge,ipcRenderer}=require('electron'); +const invoke=(method,...args)=>ipcRenderer.invoke('skills-qa',method,args); +contextBridge.exposeInMainWorld('ycode',{skills:{ + list:(cwd)=>invoke('list',cwd), + recommendations:()=>invoke('recommendations'), + installRecommended:(id,options)=>invoke('installRecommended',id,options), + cancelInstall:(operationId)=>invoke('cancelInstall',operationId), + installState:()=>invoke('installState'), + onInstallProgress:(listener)=>{const wrapped=(_event,state)=>listener(state);ipcRenderer.on('skills:install-progress',wrapped);return()=>ipcRenderer.removeListener('skills:install-progress',wrapped)}, + onChanged:(listener)=>{const wrapped=()=>listener();ipcRenderer.on('skills:changed',wrapped);return()=>ipcRenderer.removeListener('skills:changed',wrapped)}, + read:async()=>({skill:{},content:'',files:[]}), + setEnabled:(...args)=>invoke('setEnabled',...args), remove:async()=>{}, export:async()=>null, importPath:async()=>null + ,qaSetInstalled:(v)=>invoke('qaSetInstalled',v), + qaFailNext:()=>invoke('qaFailNext'), + qaDelay:(v)=>invoke('qaDelay',v), + qaSetRecommendations:(v)=>invoke('qaSetRecommendations',v), + qaFailRecommendations:(v)=>invoke('qaFailRecommendations',v), + qaEmitForeign:(phase,operationId)=>invoke('qaEmitForeign',phase,operationId), + qaEmitStale:(phase,operationId,updatedAt)=>invoke('qaEmitStale',phase,operationId,updatedAt) +},resources:{openExternal:async()=>undefined}});`) + + const location = file => JSON.stringify(path.join(repository, file).replaceAll('\\', '/')) + fs.writeFileSync(path.join(output, 'fixture.tsx'), `import React from 'react'; +import{createRoot}from'react-dom/client'; +import Center from ${location('src/renderer/src/capabilities/CapabilityCenter')}; +import${location('src/renderer/src/styles/tokens.css')}; +import${location('src/renderer/src/styles/app.css')}; +window.__qa={uses:[],created:0,find:0}; +createRoot(document.getElementById('root')).render( +
+
{}} onUseSkill={skill=>window.__qa.uses.push(skill)} onCreateSkill={()=>window.__qa.created++} onFindSkill={()=>window.__qa.find++}/> +
);`) + await require('esbuild').build({ + entryPoints: [path.join(output, 'fixture.tsx')], bundle: true, platform: 'browser', format: 'esm', jsx: 'automatic', + outfile: path.join(output, 'fixture.js'), loader: { '.svg': 'file', '.png': 'file', '.jpg': 'file', '.woff': 'file', '.woff2': 'file', '.ttf': 'file' }, logLevel: 'warning' + }) + fs.writeFileSync(path.join(output, 'index.html'), '
') + + const win = new BrowserWindow({ + width: 1052, height: 901, useContentSize: true, frame: false, show: false, + webPreferences: { preload: path.join(output, 'preload.cjs'), contextIsolation: true, nodeIntegration: false, backgroundThrottling: false } + }) + win.webContents.on('console-message', (_event, level, message) => { if (level === 3) errors.push(message) }) + const read = code => win.webContents.executeJavaScript(code) + const check = (label, actual, expected) => { + const pass = typeof expected === 'function' ? expected(actual) : JSON.stringify(actual) === JSON.stringify(expected) + assert.ok(pass, `${label}: ${JSON.stringify(actual)}`) + checks.push(label) + } + const pause = ms => new Promise(resolve => setTimeout(resolve, ms)) + const wait = async code => { for (let index = 0; index < 200; index++) { if (await read(code)) return; await pause(50) } throw Error('Timeout ' + code) } + const click = async selector => { + await read(`(()=>{const e=document.querySelector(${JSON.stringify(selector)});if(!e)throw Error('Missing '+${JSON.stringify(selector)});e.click();return true})()`) + await pause(140) + } + const capture = async name => { + win.webContents.invalidate() + await pause(120) + // A hidden window can capture the previous frame; warm the compositor first. + await win.webContents.capturePage() + await pause(200) + const image = await win.webContents.capturePage() + fs.writeFileSync(path.join(output, name + '.png'), image.toPNG()) + screenshots.push(name + '.png') + } + + const verifyCurrentActionStyles = async theme => { + const selector = '[data-recommendation-id=archify] .sm-use-btn' + const inspect = () => read(`(()=>{const b=document.querySelector(${JSON.stringify(selector)});const s=getComputedStyle(b);return{width:s.width,height:s.height,background:s.backgroundColor,color:s.color,outline:s.outline,focused:document.activeElement===b,hover:b.matches(':hover')}})()`) + win.webContents.sendInputEvent({type:'mouseMove',x:1,y:1}) + await read(`document.activeElement?.blur()`); await pause(200) + const normal = await inspect() + check(theme + ' use action default background is transparent', normal.background, value => value === 'rgba(0, 0, 0, 0)' || value === 'transparent') + const point = await read(`(()=>{const r=document.querySelector(${JSON.stringify(selector)}).getBoundingClientRect();return{x:Math.round(r.x+r.width/2),y:Math.round(r.y+r.height/2)}})()`) + await read('(()=>{window.__qaPointerEntry=null;document.querySelector(".sm-use-btn").addEventListener("pointerenter",event=>{window.__qaPointerEntry={trusted:event.isTrusted,type:event.pointerType}},{once:true})})()'); + win.webContents.sendInputEvent({type:'mouseMove',...point});await pause(200) + const hover = await inspect() + const pointerEntry=await read('window.__qaPointerEntry'); check(theme + ' trusted native pointer enters use action', pointerEntry?.trusted === true && pointerEntry?.type === 'mouse', true); actionStyles.push({theme,pointerEntry,selectorHover: hover.hover}); + check(theme + ' hover has a distinct background', hover.background !== normal.background, true) + await capture('installed-use-' + theme + '-hover') + win.webContents.sendInputEvent({type:'mouseMove',x:1,y:1}) + win.webContents.sendInputEvent({type:'keyDown',keyCode:'Tab'});win.webContents.sendInputEvent({type:'keyUp',keyCode:'Tab'}) + await read(`document.querySelector(${JSON.stringify(selector)}).focus()`);await pause(200) + const focus = await inspect() + check(theme + ' use action remains focusable with stable 24px slot', focus.focused && focus.width === '24px' && focus.height === '24px', true) + await capture('installed-use-' + theme + '-focus') + actionStyles.push({theme,normal,hover,focus}) + await read(`document.activeElement?.blur()`) + } + + try { + await win.loadFile(path.join(output, 'index.html'));win.showInactive();await pause(200) + await wait('!!document.querySelector(".yc-skills-page")') + await wait('!!document.querySelector("[data-recommendation-id=archify]")') + + check('the recommendation card renders from the host catalog', await read('document.querySelector("[data-recommendation-id=archify] .sm-card-name")?.textContent'), 'Archify') + check('the card exposes its install state for the host test', await read('document.querySelector("[data-recommendation-id=archify]").dataset.recommendationState'), 'none') + check('the card shows the author supplied description', await read('document.querySelector("[data-recommendation-id=archify] .sm-card-desc")?.textContent'), recommendation.description) + check('no maintenance placeholder is shown', await read('!!document.querySelector("[data-capability-maintenance]")'), false) + check('the remote catalog tabs still report no connection', await read('!!document.querySelector(".yc-skill-market-unavailable")'), false) + await capture('recommendation-card') + + // First install asks for an explicit confirmation. + await click('[aria-label="安装 Archify"]') + await wait('!!document.querySelector(".yc-skill-detail-shell")') + check('the confirm dialog names the source repository', await read('document.querySelector(".yc-skill-detail-shell").textContent.includes("tt-a1i/archify")'), true) + check('the confirm dialog states that no install script runs', await read('document.querySelector(".yc-skill-detail-shell").textContent.includes("不会执行仓库中的任何安装命令")'), true) + check('the confirm dialog warns that the skill contains scripts', await read('document.querySelector(".yc-skill-detail-shell").textContent.includes("包含脚本") || document.querySelector(".yc-skill-detail-shell").textContent.includes("脚本")'), true) + await capture('install-confirm') + await read('(()=>{const first=document.querySelector("[role=dialog] .sm-skill-detail-close");first.focus();first.dispatchEvent(new KeyboardEvent("keydown",{key:"Tab",shiftKey:true,bubbles:true,cancelable:true}))})()') + check('reverse Tab reaches the collapsible source information', await read('document.activeElement.tagName'), 'SUMMARY') + await read('document.activeElement.dispatchEvent(new KeyboardEvent("keydown",{key:"Tab",bubbles:true,cancelable:true}))') + check('Tab wraps inside the modal rather than entering the sidebar', await read('document.activeElement.getAttribute("aria-label")'), '关闭技能详情') + await read('window.__detailBeforeInstall=document.querySelector("[role=dialog]")') + await click('[aria-label="确认安装推荐技能"]') + await wait('document.querySelector(".yc-skill-inline-install")?.dataset.installPhase==="installed"') + check('the install progress is reported by the host', await read('document.querySelector(".yc-skill-inline-install").dataset.installPhase'), 'installed') + check('the host received the recommendation id', await read(`JSON.stringify(${JSON.stringify(calls)}.filter(c=>c[0]==='installRecommended').map(c=>c[1]))`), '["archify"]') + check('the host received a fresh operation id', await read(`(${JSON.stringify(calls)}.filter(c=>c[0]==='installRecommended').every(c=>typeof c[2]?.operationId==='string'&&c[2].operationId.length>8))`), true) + check('a first install is not an overwrite', await read(`(${JSON.stringify(calls)}.filter(c=>c[0]==='installRecommended').every(c=>c[2]?.overwrite!==true))`), true) + await wait('document.querySelector("[data-recommendation-id=archify]").dataset.recommendationState==="current"') + check('the card reports the recommendation as installed', await read('document.querySelector("[data-recommendation-id=archify]").dataset.recommendationState'), 'current') + check('the installed skill has no add button', await read('!!document.querySelector("[data-recommendation-id=archify] .sm-add-btn")'), false) + check('the installed skill uses the recovered installed card', await read('!!document.querySelector("[data-recommendation-id=archify] .sm-card--installed")'), true) + check('the installed action uses the original action slot', await read('!!document.querySelector("[data-recommendation-id=archify] .sm-status .sm-use-btn")'), true) + check('no duplicate under-card use action remains', await read('!!document.querySelector(".yc-skill-recommendation-meta button")'), false) + check('the duplicate footer is absent', await read('!!document.querySelector(".yc-skill-recommendation-footer")'), false) + check('the detail remains the same DOM instance throughout installation', await read('window.__detailBeforeInstall===document.querySelector("[role=dialog]")'), true) + check('the detail offers use after installation', await read('document.querySelector("[role=dialog] .sm-skill-detail-action-row")?.textContent.includes("去使用")'), true) + check('the success notification also offers use', await read('document.querySelector(".yc-skill-install-success")?.textContent.includes("去使用")'), true) + check('there is no permanent list footer progress panel', await read('!!document.querySelector(".yc-skills-scroll > .yc-skill-inline-install")'), false) + await capture('installed-detail') + await click('[role=dialog] .sm-skill-detail-close') + + const installedActionStyle = await read(`(()=>{const b=document.querySelector('[data-recommendation-id=archify] .sm-use-btn');const s=getComputedStyle(b);const svg=b.querySelector('svg');return {width:s.width,height:s.height,svgWidth:getComputedStyle(svg).width,svgHeight:getComputedStyle(svg).height}})()`) + check('installed action uses recovered 24px slot and 16px icon', installedActionStyle, {width:'24px',height:'24px',svgWidth:'16px',svgHeight:'16px'}) + await capture('installed-recommendation-light') + await verifyCurrentActionStyles('light') + + // The installed list stays reachable and the skill can be used. + await click('[aria-label="已安装技能"]') + await wait('document.querySelectorAll(".sm-card").length===1') + check('the installed skill appears in the installed list', await read('document.querySelector(".sm-card-name")?.textContent'), 'Archify') + await click('[aria-label="返回专家中心"]') + await wait('!!document.querySelector("[data-recommendation-id=archify]")') + + // A local skill with the same name requires an explicit overwrite. + await read(`window.ycode.skills.qaSetInstalled(${JSON.stringify([localSkill])})`) + await wait('document.querySelector("[data-recommendation-id=archify]").dataset.recommendationState==="conflict"') + await click('[aria-label="替换 Archify"]') + await wait('!!document.querySelector(".yc-skill-detail-shell")') + check('a same-name local skill requires an explicit replacement', await read('document.querySelector(".yc-skill-detail-shell").textContent.includes("替换")'), true) + check('the replacement notice mentions the local modification', await read('document.querySelector(".yc-skill-detail-shell").textContent.includes("本地内容已被修改")'), true) + await click('[aria-label="确认安装推荐技能"]') + await wait('document.querySelector("[data-recommendation-id=archify]").dataset.recommendationState==="current"') + check('an explicit replacement is sent to the host as an overwrite', await read(`(${JSON.stringify(calls)}.filter(c=>c[0]==='installRecommended').at(-1)[2]?.overwrite)===true`), true) + await click('[role=dialog] .sm-skill-detail-close') + + // A failing download reports the real host error and allows a retry. + await read(`window.ycode.skills.qaSetInstalled(${JSON.stringify([])})`) + await wait('document.querySelector("[data-recommendation-id=archify]").dataset.recommendationState==="none"') + await read(`window.ycode.skills.qaFailNext()`) + await click('[aria-label="安装 Archify"]') + await click('[aria-label="确认安装推荐技能"]') + await wait('document.querySelector(".yc-skill-inline-install")?.dataset.installPhase==="failed"') + check('a failed install shows the host error', await read('document.querySelector(".yc-skill-inline-install").textContent.includes("网络错误")'), true) + check('a failed install can be retried from the same card', await read('document.querySelector("[data-recommendation-id=archify] .sm-add-btn")?.disabled'), false) + await click('[role=dialog] .sm-skill-detail-close') + + // Cancellation is allowed before the atomic commit phase. + await read(`window.ycode.skills.qaDelay(400)`) + await click('[aria-label="安装 Archify"]') + await click('[aria-label="确认安装推荐技能"]') + await wait('document.querySelector(".yc-skill-inline-install")?.dataset.installPhase==="downloading"') + check('the download phase can be cancelled', await read('[...document.querySelectorAll("[role=dialog] button")].some(e=>e.textContent==="取消安装"&&!e.disabled)'), true) + await read('document.querySelector("[role=dialog]").querySelectorAll("button").forEach(e=>{if(e.textContent==="取消安装")e.click()})') + await wait('document.querySelector(".yc-skill-inline-install")?.dataset.installPhase==="cancelled"') + check('the cancellation is sent to the host', await read(`${JSON.stringify(calls)}.some(c=>c[0]==='cancelInstall')`), true) + await click('[role=dialog] .sm-skill-detail-close') + await read(`window.ycode.skills.qaDelay(0)`) + + // Closing the detail never aborts an accepted install; reopening resumes it. + await read('window.ycode.skills.qaDelay(250)') + await click('[aria-label="安装 Archify"]'); await click('[aria-label="确认安装推荐技能"]') + await wait('document.querySelector(".yc-skill-inline-install")?.dataset.installPhase==="downloading"') + const continuingId = await read('document.querySelector(".yc-skill-inline-install").dataset.operationId') + await click('[role=dialog] .sm-skill-detail-close') + check('closing a running detail restores the background', await read('document.getElementById("root").inert'), false) + await click('[data-recommendation-id=archify] .sm-card') + check('reopening detail keeps the same install operation', await read('document.querySelector(".yc-skill-inline-install").dataset.operationId'), continuingId) + await wait('document.querySelector(".yc-skill-inline-install")?.dataset.installPhase==="installing"') + check('the commit phase disables cancellation in place', await read('[...document.querySelectorAll("[role=dialog] button")].find(e=>e.textContent==="取消安装")?.disabled'), true) + await wait('document.querySelector(".yc-skill-inline-install")?.dataset.installPhase==="installed"') + await click('[role=dialog] .sm-skill-detail-close') + await click('.yc-skill-install-success [aria-label="使用推荐技能 Archify"]') + check('the success notification invokes the same use callback', await read('window.__qa.uses.length'), 1) + await read(`window.ycode.skills.qaSetInstalled(${JSON.stringify([{ ...installedRecommendation, enabled: false }])})`) + await wait('document.querySelector("[data-recommendation-id=archify] .sm-use-btn")?.title.includes("启用")') + await click('[data-recommendation-id=archify] .sm-use-btn') + await wait('window.__qa.uses.length===2') + check('disabled recommendation is enabled before use', await read('window.__qa.uses.at(-1).enabled'), true) + await read('window.ycode.skills.qaDelay(0)'); await read('window.ycode.skills.qaSetInstalled([])') + await wait('document.querySelector("[data-recommendation-id=archify]").dataset.recommendationState==="none"') + + // A failing catalog is reported as unavailable, not as a maintenance page. + // The page loads its catalog once, so the failure is proven on a fresh mount. + await read(`window.ycode.skills.qaFailRecommendations(true)`) + await read(`location.reload()`) + await wait('!!document.querySelector(".yc-skill-recommendation-unavailable")') + check('an empty catalog is reported as unavailable, not as a maintenance page', await read('!!document.querySelector("[data-capability-maintenance]")'), false) + check('the unavailable state keeps top installed navigation', await read('!!document.querySelector("[aria-label=已安装技能]")'), true) + check('the unavailable state has no duplicate installed entry', await read('[...document.querySelectorAll(".yc-skill-recommendation-unavailable button")].some(e=>e.textContent.includes("查看已安装技能"))'), false) + await read(`window.ycode.skills.qaFailRecommendations(false)`) + await click('.yc-skill-recommendation-unavailable button') + await wait('!!document.querySelector("[data-recommendation-id=archify]")') + + // An install owned by another window blocks a new install here. + const foreignOperation = '11111111-2222-4333-8444-555555555555' + await read(`window.ycode.skills.qaEmitForeign('downloading', ${JSON.stringify(foreignOperation)})`) + await wait('!!document.querySelector("[data-foreign-install=true]")') + check('an install from another window is reported', await read('document.querySelector("[data-foreign-install=true]").textContent.includes("其他窗口正在安装推荐技能")'), true) + check('a new install is blocked while another window is installing', await read('document.querySelector("[data-recommendation-id=archify] .sm-add-btn")?.disabled'), true) + check('the blocked state is explained on the card', await read('!!document.querySelector(".yc-skill-recommendation-busy")'), true) + await capture('foreign-install') + await read(`window.ycode.skills.qaEmitForeign('installed', ${JSON.stringify(foreignOperation)})`) + await wait('!document.querySelector("[data-foreign-install=true]")') + check('the foreign block clears when that operation finishes', await read('document.querySelector("[data-recommendation-id=archify] .sm-add-btn")?.disabled'), false) + + // A stale frame must not move a settled operation back into a running phase. + await read(`window.ycode.skills.qaSetInstalled(${JSON.stringify([])})`) + await wait('document.querySelector("[data-recommendation-id=archify]").dataset.recommendationState==="none"') + await read(`window.ycode.skills.qaDelay(0)`) + await click('[aria-label="安装 Archify"]') + await click('[aria-label="确认安装推荐技能"]') + await wait('document.querySelector(".yc-skill-inline-install")?.dataset.installPhase==="installed"') + const settledOperation = await read(`(${JSON.stringify(calls)}.filter(c=>c[0]==='installRecommended').at(-1)[2]?.operationId)`) + check('the settled install recorded its operation id', typeof settledOperation === 'string' && settledOperation.length > 8, true) + await read(`window.ycode.skills.qaEmitStale('downloading', ${JSON.stringify(settledOperation)}, 1)`) + await pause(250) + check('a stale frame does not regress the settled install', await read('document.querySelector(".yc-skill-inline-install")?.dataset.installPhase'), 'installed') + await click('[role=dialog] .sm-skill-detail-close') + + // Dark and narrow captures of the real page. + // This fixture mounts only the capability center, so the theme attribute is set directly. + // The dark token switch is proven here only; the production app harness covers the light flow. + await read(`(()=>{localStorage.setItem('ycode:theme','dark');document.documentElement.dataset.theme='dark';return true})()`) + await wait('document.documentElement.dataset.theme==="dark"') + await wait('!!document.querySelector(".yc-capability-center .expert-center-dark")') + check('the dark theme reaches the real page', await read('!!document.querySelector(".yc-capability-center .expert-center-dark")'), true) + // The card transitions its background, so the dark surface only settles after the animation. + await wait(`(()=>{const card=document.querySelector('[data-recommendation-id=archify] .sm-card');if(!card)return false;const m=/rgba?\\((\\d+)/.exec(getComputedStyle(card).backgroundColor);return !!m&&Number(m[1])<90})()`) + const darkColors = await read(`(()=>{const card=document.querySelector('[data-recommendation-id=archify] .sm-card');const page=document.querySelector('.yc-capability-center .expert-center-page');return{card:card?getComputedStyle(card).backgroundColor:null,page:page?getComputedStyle(page).backgroundColor:null}})()`) + check('the dark card uses a dark surface', darkColors.card, value => typeof value === 'string' && /rgba?\((\d+), (\d+), (\d+)/.test(value) && Number(value.match(/rgba?\((\d+)/)[1]) < 90) + const overflow = await read(`(()=>{const wide=[...document.querySelectorAll('*')].filter(e=>e.getBoundingClientRect().right>innerWidth+1).map(e=>e.className||e.tagName).slice(0,4);return{scrollWidth:document.documentElement.scrollWidth,innerWidth,wide}})()`) + check('the dark layout keeps the recommendation card inside the viewport', await read(`(()=>{const c=document.querySelector('[data-recommendation-id=archify] .sm-card');if(!c)return false;const r=c.getBoundingClientRect();return r.left>=0&&r.right<=innerWidth+1})()`), true) + check('the dark layout does not overflow the document', overflow.scrollWidth <= overflow.innerWidth + 1, true) + await capture('recommendation-dark') + await verifyCurrentActionStyles('dark') + win.setSize(720, 900) + await pause(400) + check('the recommendation card stays inside the narrow viewport', await read('(()=>{const c=document.querySelector("[data-recommendation-id=archify] .sm-card");if(!c)return false;const r=c.getBoundingClientRect();return r.left>=0&&r.right<=innerWidth+1})()'), true) + const narrowOverflow = await read(`(()=>{const wide=[...document.querySelectorAll('*')].filter(e=>e.getBoundingClientRect().right>innerWidth+1).map(e=>String(e.className||e.tagName)).slice(0,5);return{scrollWidth:document.documentElement.scrollWidth,innerWidth,wide}})()`) + check('the narrow recommendation card causes no document overflow', narrowOverflow.scrollWidth <= narrowOverflow.innerWidth + 1, true) + await capture('recommendation-narrow') + win.setSize(1052, 901) + await pause(250) + + check('no renderer errors', errors, []) + fs.writeFileSync(path.join(output, 'report.json'), JSON.stringify({ + result: 'PASS', checks, calls, screenshots, actionStyles, + limits: 'Controlled host in isolated Electron; the shipped page and styles are used. No network, no real skill storage, no real install.' + }, null, 2)) + console.log(JSON.stringify({ result: 'PASS', checks: checks.length, output })) + win.destroy() + app.exit(0) + } catch (error) { + await capture('failure') + fs.writeFileSync(path.join(output, 'failure.json'), JSON.stringify({ error: String(error), stack: error?.stack, checks, errors, calls, html: await read('document.body.innerHTML') }, null, 2)) + console.error(error) + win.destroy() + app.exit(1) + } + })().catch(error => { console.error(error); electron.app.exit(1) }) +} diff --git a/docs/协作/evidence/B02-review-01/pointer-ui-runner.txt b/docs/协作/evidence/B02-review-01/pointer-ui-runner.txt new file mode 100644 index 0000000..131b4b6 --- /dev/null +++ b/docs/协作/evidence/B02-review-01/pointer-ui-runner.txt @@ -0,0 +1,14 @@ + +(electron) 'console-message' arguments are deprecated and will be removed. Please use Event object instead. +Error occurred in handler for 'skills-qa': Error: 下载失败:网络错误 + at file:///C:/Users/Administrator/.codex/worktrees/b02-accept-01/YCode/.tmp/b02-acceptance/recommended-skills-ui-pointer.mjs:94:17 + at Session. (node:electron/js2c/browser_init:2:107269) + at Session.emit (node:events:519:28) +Error occurred in handler for 'skills-qa': Error [AbortError]: 推荐技能安装已取消 + at file:///C:/Users/Administrator/.codex/worktrees/b02-accept-01/YCode/.tmp/b02-acceptance/recommended-skills-ui-pointer.mjs:98:204 + at async Session. (node:electron/js2c/browser_init:2:107253) +Error occurred in handler for 'skills-qa': Error: 推荐目录服务不可用 + at file:///C:/Users/Administrator/.codex/worktrees/b02-accept-01/YCode/.tmp/b02-acceptance/recommended-skills-ui-pointer.mjs:80:40 + at Session. (node:electron/js2c/browser_init:2:107269) + at Session.emit (node:events:519:28) +{"result":"PASS","checks":62,"output":"C:\\Users\\Administrator\\.codex\\worktrees\\b02-accept-01\\YCode\\.tmp\\recommended-skills-ui-yKVyWZ"} diff --git a/docs/协作/evidence/B02-review-01/recommended-backend.txt b/docs/协作/evidence/B02-review-01/recommended-backend.txt new file mode 100644 index 0000000..e0bc43a --- /dev/null +++ b/docs/协作/evidence/B02-review-01/recommended-backend.txt @@ -0,0 +1,7 @@ + +> ycode@0.0.7 test:recommended-skills +> esbuild scripts/recommended-skills-backend-regression.ts --bundle --platform=node --format=esm --external:esbuild --outfile=.tmp/recommended-skills-backend-regression.mjs --log-level=warning && node .tmp/recommended-skills-backend-regression.mjs + +{"result":"PASS","checks":50,"phase":"archive"} +{"result":"SKIP","phase":"real-package","reason":"published package not present in .tmp"} +{"result":"PASS","checks":60,"phase":"real-package"} diff --git a/docs/协作/evidence/B02-review-01/test-results.json b/docs/协作/evidence/B02-review-01/test-results.json new file mode 100644 index 0000000..b849999 --- /dev/null +++ b/docs/协作/evidence/B02-review-01/test-results.json @@ -0,0 +1,22 @@ +[ + { + "Command": "npm run test:recommended-skills", + "ExitCode": 0, + "Log": ".tmp/b02-acceptance/test-recommended-skills.log" + }, + { + "Command": "npm run test:composer-capabilities", + "ExitCode": 0, + "Log": ".tmp/b02-acceptance/test-composer-capabilities.log" + }, + { + "Command": "npm run check:tokens", + "ExitCode": 1, + "Log": ".tmp/b02-acceptance/check-tokens.log" + }, + { + "Command": "npm run test:fold-summary", + "ExitCode": 1, + "Log": ".tmp/b02-acceptance/test-fold-summary.log" + } +] diff --git a/docs/协作/evidence/B02-review-01/token-check.txt b/docs/协作/evidence/B02-review-01/token-check.txt new file mode 100644 index 0000000..bbc9f10 --- /dev/null +++ b/docs/协作/evidence/B02-review-01/token-check.txt @@ -0,0 +1,29 @@ + +> ycode@0.0.7 check:tokens +> node scripts/check-design-tokens.mjs + +设计 token 漂移检查(静态) + 扫描:src/renderer/src 共 367 个文件(用时 96 ms) + baseline:scripts/design-token-baseline.json(334 个文件) + 门禁分类:adapter 8 | core 6 | local 279(合计 293 个文件) + 合计:裸 hex=611 裸 px=2680 !important=6 --wb-* 定义=525 var(--yc-*) 使用=1650 var(--wb-*) 使用=1209 + 非门禁分类:vendor 2 | recovered 22 | source 47 | tokenSource 3(合计 74 个文件,仅记录不阻塞) + 合计:裸 hex=10642 裸 px=13642 !important=920 --wb-* 定义=17966 var(--yc-*) 使用=77 var(--wb-*) 使用=19638 + 非门禁相对 baseline:文件 +0;裸 hex +78 裸 px +64 !important +0 --wb-* 定义 +0 var(--yc-*) 使用 +22 var(--wb-*) 使用 -120 + +结果:失败,共 6 项: + [新增门禁文件] src/renderer/src/capabilities/recommended-flow.css(local):裸 px=21 + [新增门禁文件] src/renderer/src/capabilities/skill-detail-shell.css(local):裸 px=21 + [回归] src/renderer/src/capabilities/skills-host.css(local):裸 px 25 → 45(+20) + [新增门禁文件] src/renderer/src/workbuddy/composer/capability-picker.css(local):裸 hex=26,裸 px=48 + [回归] src/renderer/src/workbuddy/composer/composer.css(local):裸 hex 23 → 38(+15);裸 px 83 → 139(+56) + [新增门禁文件] src/renderer/src/workbuddy/composer/prompt-queue.css(local):裸 hex=8,裸 px=35 + +提示:确认变更符合预期后运行 `node scripts/check-design-tokens.mjs --update-baseline` 刷新 baseline; + 否则请改用 --yc-* token、复用现有值,或去掉重复的 --wb-* 定义。 +提示(不失败,仅记录):3 个门禁文件 token 使用数上升: + src/renderer/src/capabilities/skills-host.css(local):var(--wb-*) 使用 12 → 19(+7) + src/renderer/src/workbuddy/composer/composer.css(local):var(--yc-*) 使用 35 → 47(+12);var(--wb-*) 使用 0 → 1(+1) + src/renderer/src/workbuddy/conversation/conversation.css(local):var(--yc-*) 使用 0 → 4(+4) +提示(不失败):baseline 中 8 个文件已不存在:src/renderer/src/components/ReportedRunUsage.tsx;src/renderer/src/workbuddy/subagents/SourceMemberIcon.tsx;src/renderer/src/workbuddy/subagents/SubagentCollaboration.tsx;src/renderer/src/workbuddy/subagents/SubagentDetailPanel.tsx;src/renderer/src/workbuddy/subagents/adapters.css;src/renderer/src/workbuddy/subagents/member-view.ts;src/renderer/src/workbuddy/subagents/source.css;src/renderer/src/workbuddy/subagents/theme.css +提示:新增门禁文件 36 个且无受控计数(允许):src/renderer/src/capabilities/CapabilityMaintenance.tsx(local);src/renderer/src/capabilities/RecommendedSkills.tsx(local);src/renderer/src/capabilities/SkillAvatar.tsx(local);src/renderer/src/capabilities/SkillDetailShell.tsx(local);src/renderer/src/capabilities/SkillModalPortal.tsx(local);src/renderer/src/capabilities/skill-modal-focus.ts(local);src/renderer/src/components/SessionLoading.tsx(local);src/renderer/src/components/TaskPopconfirm.tsx(local);src/renderer/src/components/session-loading.css(local);src/renderer/src/components/task-popconfirm.css(local);src/renderer/src/components/updates/UpdateSidebarCard.tsx(local);src/renderer/src/components/updates/update-ui-model.ts(local);src/renderer/src/components/updates/update-ui-store.ts(local);src/renderer/src/components/updates/updates-ui.css(local);src/renderer/src/ui/Button.tsx(local);src/renderer/src/ui/IconButton.tsx(local);src/renderer/src/ui/Input.tsx(local);src/renderer/src/ui/Popover.tsx(local);src/renderer/src/ui/Select.tsx(local);src/renderer/src/ui/Switch.tsx(local);…(还有 16 项,详见 --json)