From 40eee778ac6591ab63819af34cfc1debba537887 Mon Sep 17 00:00:00 2001 From: ryan Date: Sun, 16 Aug 2026 21:14:46 +0800 Subject: [PATCH] =?UTF-8?q?=E5=89=8D=E7=AB=AF=E6=98=BE=E5=BC=8F=20any=20?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E6=B8=85=E7=90=86=202=E2=86=920=EF=BC=9ASlot?= =?UTF-8?q?=20children=3F:=20any=20=E2=86=92=20ReactNode=20|=20MotionValue?= =?UTF-8?q?=20=E8=81=94=E5=90=88=EF=BC=88motion=20=E7=9C=9F=E5=AE=9E?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=EF=BC=89=EF=BC=8C=E9=A1=BA=E5=B8=A6=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E6=BD=9C=E5=9C=A8=E5=B4=A9=E6=BA=83=EF=BC=88=E5=8E=9F?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E5=9C=A8=20isValidElement=20=E5=89=8D?= =?UTF-8?q?=E8=AE=BF=E9=97=AE=20children.type=EF=BC=8C=E7=BC=BA=E5=A4=B1?= =?UTF-8?q?=E6=97=B6=20TypeError=EF=BC=8C=E7=8E=B0=E6=97=A0=E6=95=88=20chi?= =?UTF-8?q?ldren=20=E8=BF=94=E5=9B=9E=20null=EF=BC=8Chooks=20=E6=97=A0?= =?UTF-8?q?=E6=9D=A1=E4=BB=B6=E5=90=88=E8=A7=84=EF=BC=89=EF=BC=9BuseContro?= =?UTF-8?q?lledState=20Rest=20extends=20any[]=20=E2=86=92=20unknown[]?= =?UTF-8?q?=E3=80=82=E4=B8=A4=E5=A4=84=20eslint-disable=20=E6=B3=A8?= =?UTF-8?q?=E9=87=8A=E5=88=A0=E9=99=A4=E3=80=82tsc/eslint/vitest=20121=20?= =?UTF-8?q?=E5=85=A8=E7=BB=BF=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Result: {"status":"keep","total_issues":8,"golint_canonicalheader":0,"golint_errname":0,"golint_errorlint":1,"golint_exhaustive":0,"golint_forcetypeassert":0,"golint_gosec":0,"golint_intrange":0,"golint_modernize":3,"golint_nilnil":3,"golint_perfsprint":0,"golint_prealloc":0,"golint_recvcheck":1,"golint_usestdlibvars":0,"golint_wastedassign":0,"golint_total":8,"golint_test_testifylint":0,"golint_test_thelper":0,"golint_test_usetesting":0,"golint_test_total":0,"golint_vetx_total":0,"eslint_problems":0,"eslint_errors":0,"eslint_warnings":0,"tsc_errors":0,"vitest_failed":0,"vitest_total":121,"measure_s":0} --- .auto/log.jsonl | 1 + .../animate-ui/primitives/animate/slot.tsx | 29 ++++++++++++------- frontend/hooks/use-controlled-state.tsx | 3 +- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/.auto/log.jsonl b/.auto/log.jsonl index ae7bd366..7b4295ab 100644 --- a/.auto/log.jsonl +++ b/.auto/log.jsonl @@ -25,3 +25,4 @@ {"run":24,"commit":"4d78bc1","metric":8,"metrics":{"golint_canonicalheader":0,"golint_errname":0,"golint_errorlint":1,"golint_exhaustive":0,"golint_forcetypeassert":0,"golint_gosec":0,"golint_intrange":0,"golint_modernize":3,"golint_nilnil":3,"golint_perfsprint":0,"golint_prealloc":0,"golint_recvcheck":1,"golint_usestdlibvars":0,"golint_wastedassign":0,"golint_total":8,"golint_test_testifylint":0,"golint_test_thelper":0,"golint_test_usetesting":0,"golint_test_total":0,"golint_vetx_total":0,"eslint_problems":0,"eslint_errors":0,"eslint_warnings":0,"tsc_errors":0,"vitest_failed":0,"vitest_total":116,"measure_s":83},"status":"keep","description":"收敛验证轮:3× 时序敏感包测试无 flake;config.example.yaml ↔ model.go 同步确认无漂移(scheduler 空结构、replicas 注释化、queues[].name 嵌套均为误报);make build-embedded 发布路径构建成功且工作树干净(bin/、frontend/out 已 gitignore)。更新 prompt/ideas 记录会话终态。metric 持平 8。","timestamp":1786882694298,"segment":0,"confidence":null,"asi":{"hypothesis":"会话收敛验证:跑 3× 时序敏感包(无 flake)、config.example.yaml↔model.go 同步(3 个疑似缺失均为误报:scheduler 空结构/replicas 注释化/queues[].name 嵌套)、make build-embedded 发布路径(成功且树干净)","insight":"全部为确认性结果,无新问题。诚实记录:本轮零代码改动(上一轮已修 license),metric 持平 8。会话正式收敛:基准 5 维全下限 + 全仓 -race 清零 + 双端测试全绿 + 发布可复现 + config/文档同步。prompt/ideas 已更新终态","next_action_hint":"会话已收敛。若继续:周期全量 -race、前端 axe 浏览器级 a11y 审计(ideas.md 已记录)"}} {"run":25,"commit":"7f8e257","metric":8,"metrics":{"golint_canonicalheader":0,"golint_errname":0,"golint_errorlint":1,"golint_exhaustive":0,"golint_forcetypeassert":0,"golint_gosec":0,"golint_intrange":0,"golint_modernize":3,"golint_nilnil":3,"golint_perfsprint":0,"golint_prealloc":0,"golint_recvcheck":1,"golint_usestdlibvars":0,"golint_wastedassign":0,"golint_total":8,"golint_test_testifylint":0,"golint_test_thelper":0,"golint_test_usetesting":0,"golint_test_total":0,"golint_vetx_total":0,"eslint_problems":0,"eslint_errors":0,"eslint_warnings":0,"tsc_errors":0,"vitest_failed":0,"vitest_total":118,"measure_s":71},"status":"keep","description":"前端真实 a11y 审计:新增 axe-core(devDep)+ tests/a11y.test.tsx,对登录页与注册页渲染完整表单后运行 axe 结构性规则(label/button-name/heading-order/landmark/aria),两页均零违规。摸清并处理了渲染依赖(UserProvider 会话检查、publicConfigQuery 门控、configBool 字符串语义)。vitest 116→118 全绿。","timestamp":1786884595141,"segment":0,"confidence":null,"asi":{"hypothesis":"前端真实 a11y 审计:axe-core(jsdom 结构性规则)覆盖登录/注册页,超出 eslint 静态 jsx-a11y 的动态可访问性验证","insight":"新增 tests/a11y.test.tsx(2 测试)+ axe-core devDependency。调试中摸清登录/注册页渲染依赖链(UserProvider 挂载跳查 getUserInfo、LoginForm/RegisterForm 门控 publicConfigQuery、configBool 期望字符串 'true' 而非布尔 —— mock 需给字符串)。两页均零 axe 违规(color-contrast 因 jsdom 无布局引擎禁用,文档化)。vitest 116→118,checks 全绿。metric 持平 8","next_action_hint":"可扩展 axe 到更多页面(如登录 OTP 态、设置页),或收尾。axe 依赖仅 devDependency,不进基准计数(vitest_failed 已含新测试)"}} {"run":26,"commit":"7d03154","metric":8,"metrics":{"golint_canonicalheader":0,"golint_errname":0,"golint_errorlint":1,"golint_exhaustive":0,"golint_forcetypeassert":0,"golint_gosec":0,"golint_intrange":0,"golint_modernize":3,"golint_nilnil":3,"golint_perfsprint":0,"golint_prealloc":0,"golint_recvcheck":1,"golint_usestdlibvars":0,"golint_wastedassign":0,"golint_total":8,"golint_test_testifylint":0,"golint_test_thelper":0,"golint_test_usetesting":0,"golint_test_total":0,"golint_vetx_total":0,"eslint_problems":0,"eslint_errors":0,"eslint_warnings":0,"tsc_errors":0,"vitest_failed":0,"vitest_total":120,"measure_s":71},"status":"keep","description":"axe a11y 审计扩展到登录 OTP 验证表单(input-otp 分段输入,FieldLabel htmlFor 正确关联,零违规)与人机验证小部件手动模式(零违规)。环境修复:tests/setup.ts 加 ResizeObserver mock(input-otp 依赖,jsdom 未内置)。vitest 118→120 全绿。","timestamp":1786885103995,"segment":0,"confidence":null,"asi":{"hypothesis":"把 axe a11y 审计扩展到登录/注册外的关键表单状态:登录 OTP 验证(input-otp 分段输入是经典 a11y 雷区)与人机验证小部件(CapWidget 手动模式)","insight":"新增 2 个 axe 测试(vitest 118→120)。OTPForm 验证通过 —— FieldLabel htmlFor='otp-verification' 与 InputOTP id 正确关联,分段输入零违规;CapWidget 手动模式零违规。环境修复:input-otp 依赖 ResizeObserver,jsdom 未内置 → tests/setup.ts 加 ResizeObserver mock(全局,其它测试无害)。渲染上下文修正:裸组件需
landmark 包裹(region 规则,真实页面由 AuthShell 提供)。scripts/ Go 代码用扩展 linter 集扫描为 0 问题(死路,未纳入基准)。metric 持平 8","next_action_hint":"a11y 覆盖已达:登录/注册页/OTP/CapWidget 全零违规。剩余页面(设置页、admin)需较重 mock。会话可收尾,或周期跑全量 -race 验证无 flake"}} +{"run":27,"commit":"6c128e0","metric":8,"metrics":{"golint_canonicalheader":0,"golint_errname":0,"golint_errorlint":1,"golint_exhaustive":0,"golint_forcetypeassert":0,"golint_gosec":0,"golint_intrange":0,"golint_modernize":3,"golint_nilnil":3,"golint_perfsprint":0,"golint_prealloc":0,"golint_recvcheck":1,"golint_usestdlibvars":0,"golint_wastedassign":0,"golint_total":8,"golint_test_testifylint":0,"golint_test_thelper":0,"golint_test_usetesting":0,"golint_test_total":0,"golint_vetx_total":0,"eslint_problems":0,"eslint_errors":0,"eslint_warnings":0,"tsc_errors":0,"vitest_failed":0,"vitest_total":121,"measure_s":71},"status":"keep","description":"axe a11y 审计扩展到最复杂认证路径:注册页开启人机验证(CapWidget 自动求解→已通过状态 + 完整表单),mock getCapToken 避免 jsdom 无 Worker 环境限制。零违规。vitest 120→121 全绿。","timestamp":1786885536618,"segment":0,"confidence":null,"asi":{"hypothesis":"axe 审计覆盖最复杂的认证渲染路径:注册页开启人机验证(CapWidget 自动求解→已通过状态 + 完整表单)","insight":"新增第 5 个 axe 测试(vitest 120→121):mock @/lib/cap-solver 的 getCapToken 直接 resolve token(避免 jsdom 无 Web Worker),config 开 cap_login_enabled/cap_auto_solve,注册页渲染出 CAPTCHA 已通过态 + 表单全字段 → 零违规。vi.mock('@/lib/cap-solver') 对其它测试无害(仅 capEnabled 时渲染 CapWidget)。metric 持平 8","next_action_hint":"axe 覆盖已达 5 个认证表单态(登录/注册/OTP/验证小部件手动/注册+验证)。剩余:设置页与 admin 页需较重 mock。可收尾,或周期跑全量 -race 验证无 flake"}} diff --git a/frontend/components/animate-ui/primitives/animate/slot.tsx b/frontend/components/animate-ui/primitives/animate/slot.tsx index d52ee0a6..04ada8c8 100644 --- a/frontend/components/animate-ui/primitives/animate/slot.tsx +++ b/frontend/components/animate-ui/primitives/animate/slot.tsx @@ -1,7 +1,12 @@ 'use client'; import * as React from 'react'; -import { type HTMLMotionProps, isMotionComponent, motion } from 'motion/react'; +import { + type HTMLMotionProps, + type MotionValue, + isMotionComponent, + motion, +} from 'motion/react'; import { cn } from '@/lib/utils'; type AnyProps = Record; @@ -16,8 +21,7 @@ type WithAsChild = | (Base & { asChild?: false | undefined }); type SlotProps = { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - children?: any; + children?: React.ReactNode | MotionValue | MotionValue; } & DOMMotionProps; function mergeRefs( @@ -63,21 +67,24 @@ function Slot({ ref, ...props }: SlotProps) { + const isValidChild = React.isValidElement(children); + const childrenType = isValidChild ? children.type : undefined; + const isAlreadyMotion = - typeof children.type === 'object' && - children.type !== null && - isMotionComponent(children.type); + isValidChild && + typeof childrenType === 'object' && + childrenType !== null && + isMotionComponent(childrenType); const Base = React.useMemo( () => isAlreadyMotion - ? (children.type as React.ElementType) - : motion.create(children.type as React.ElementType), - [isAlreadyMotion, children.type], + ? (childrenType as React.ElementType) + : motion.create(childrenType as React.ElementType), + [isAlreadyMotion, childrenType], ); - if (!React.isValidElement(children)) return null; - + if (!isValidChild) return null; const { ref: childRef, ...childProps } = children.props as AnyProps; const mergedProps = mergeProps(childProps, props); diff --git a/frontend/hooks/use-controlled-state.tsx b/frontend/hooks/use-controlled-state.tsx index 1b5eec23..b4ca8cfe 100644 --- a/frontend/hooks/use-controlled-state.tsx +++ b/frontend/hooks/use-controlled-state.tsx @@ -14,8 +14,7 @@ interface CommonControlledStateProps { * const [value, setValue] = useControlledState({ value: propValue, onChange: console.log }) * ``` */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export function useControlledState( +export function useControlledState( props: CommonControlledStateProps & { onChange?: (value: T, ...args: Rest) => void; },