Commit Graph

6 Commits

Author SHA1 Message Date
wandering1 842d711ed6 refactor(编号): 测试验证层级去号——CI job / 门禁输出 / 命令行旗标换语义名 + ASCII 段名
用户裁定「我不想看到编号」。测试验证层级这一族的整族清退分三道并行:本笔是**代码与 CI 道**
(CI 步骤与门禁输出面),代码注释面另走、文档面由文档道走。

口径(旧 → 语义名 → ASCII 段名,段名只进日志/旗标/job id/文件名):
  L0 静态门禁 static | L0a 钩子解释器预检 preflight | L0b 提交信息门禁 commitmsg
  L0c 体积门禁 size | L0.5 主机侧纯逻辑单测 host-unit | L0.5c 覆盖率 coverage

- scripts/ci_local.py 43 站点:段标题与 [SUMMARY] 标签改 ASCII 段名(static: /
  host-unit:),函数 run_l0/run_l05 → run_static_gates/run_host_unit_tests,
  收尾「已跑:」列表用段名。旗标改 --static-only / --host-unit-only,**旧旗标
  --l0-only / --l05-only 保留为 argparse 别名**(肌肉记忆与既有脚本片段不断档,
  实测 --help 两名列出)。
- .gitea/workflows/ci.yml 42 站点:job id l0-gates → static-gates、
  l05-host-unit-tests → host-unit-tests;步骤名与 step-summary 标题改语义名;
  日志名 l0-pre-commit.log → static-pre-commit.log、l05-<模块>.log →
  host-unit-<模块>.log;::error::/::notice:: 文案同步。yaml.safe_load 核过
  两个 job id 与步骤名。
  host-unit-tests;步骤名与 step-summary 标题改语义名;日志名 l0-pre-commit.log →
  static-pre-commit.log、l05-<模块>.log → host-unit-<模块>.log;::error::/::notice::
  文案同步。yaml.safe_load 核过两个 job id 与步骤名。
- 门禁脚本 18 站点:check_registration(登记簿理由串 7)、check_test_coverage 5、
  README 8、check_generated_fresh 2、ram_baseline 2、check_size_gate 1、
  ci_find_python.ps1 2、ci_runner_bootstrap.ps1 2、.pre-commit-config.yaml 2、
  requirements.txt 1(保持纯 ASCII)。
- skills 7 站点:task-worktree(含 [SUMMARY] 样例两行)、mem-budget、ui-verify、
  task_worktree.py 的实跑标签。
- AGENTS.md 3 站点:CI 段「只跑静态门禁 + 主机侧纯逻辑单测」、自查命令段、
  「2026-10-11 静态门禁全灭」事件名。
- 归档:编号治理历史.md 新增 §10 换算表 + **撞族警示**(同形 L0/L1/L2/L3 还属 UI 设计
  令牌层 / UI 菜单层级 / 采集链 / 链路时延段 / CubeMX 三层 / 硬件位号与 FTP 应答字面量
  等六个族,其中 6 处在字符串字面量里,改了就是改行为——故全程只按行内置换、先判族)。
- docs/产品需求 §7.4 测试分层表:去号 + 顺带修掉上一批**错族替换疤**(该表 L1/L2 行曾被
  采集链层名「语义取数与有效性 / 全周傅氏相量」「保护判据」顶替,现按内容改写为板端测试
  套件 / 主机侧回归两行)。同文档 §1.5 G5 判据行同步。

门禁:ci_local --help 两面旗标并列;py_compile 7 个 .py 全过;yaml 解析通过;
check_ids_new --worktree rc=0;git diff --check 干净;17 个改动文件 FFFD=0、无 CR、
BOM 与原文件一致(含 requirements.txt 纯 ASCII)。本族无机器识别面(单字母+数字是
新增行门禁的自述盲区),口径来自自建逐行扫描器,复扫本族形态归零。
- 交接说明:文档道 teammate 在改 CI 指南时中断,剩余 9 处双写疤与 29 处 CI 标识
  (job id / 日志名 / 汇总行字面量)由 Lead 接手改完,逐处仍走断言式行内置换。
2026-10-28 17:46:52 +08:00
wandering1 3557b60ceb CI runner 修日志噪声与 -Status 假警:PS5.1 把原生 stderr 包成 ErrorRecord
双看门狗缺陷已实测收敛:管理员 -StartNow 清掉 3 个残留(孤儿看门狗 26900/19716 +
占锁 daemon 53848)→ "daemon up: pid 40360 (single instance)",监管链恢复为
svchost(任务) → 看门狗 → daemon,看门狗日志 25 秒零增长,runner 回 online。
切换瞬间新看门狗先失败 1~2 次(旧 daemon 刚死、锁未释放)后自愈,属预期。

顺带查出并修掉两个由验证动作暴露的问题:

1) 日志噪声:daemon 把日志写到 stderr,PS 5.1 的 2>&1 会把每行原生 stderr 包成
   ErrorRecord,Out-File 渲染出 "gitea-runner.exe : " 前缀 + 4 行 CategoryInfo 块。
   实测对比(用无效子命令产生真实 stderr):& exe 2>&1 | Out-File 把 2 行真日志写成
   8 行——每 4 行有 3 行是 PowerShell 噪声,而且就在文档让大家第一个打开的文件里。
   改为 2>&1 | ForEach-Object { "$_" } | Out-File -Encoding utf8:实测与 cmd 包装等价
   但不用操心 cmd 对含空格路径的引号剥离,ErrorRecord.ToString() 即原始行,
   $LASTEXITCODE 不受影响(看门狗靠它打印退出码)。§7.2 方式 B 的示例原本正是
   "> log 2>&1"(UTF-16LE + ErrorRecord 双坑),已改;新增 §7.3 汇总这两条陷阱。

2) -Status 两处不诚实:① 非管理员读不到 SYSTEM 进程的 CommandLine(返回 null),
   过滤器静默匹配 0 个 → 会谎报"没有看门狗"(今天两次被这个假象误导),改为明说
   "需提权";② 重启循环判据原本靠"日志尾部 40 行里有没有 lock 字样",而日志不轮转,
   修好之后旧失败仍留在尾部 → 对健康 runner 报假警。改看 daemon 进程存活时长
   (活过 10 秒重拉间隔就不可能在循环里);用 CIM CreationDate,因为
   Process.StartTime 对 SYSTEM 进程不可读。

验证:bootstrap parse 0 错 / 纯 ASCII / -Status 与 -DryRun 均正常;
check_doc_links.py --all 125 篇 0 问题;pre-commit run --all-files 17 项全 Passed。

注:磁盘上的 run_runner_watchdog.ps1 仍是旧模板,噪声修复要下次管理员 -StartNow
(或开机自启)时才生效,纯观感问题,不必专门再重启一次 runner。
2026-10-12 17:59:45 +08:00
wandering1 49f3e2dac5 CI runner 修"双看门狗抢 .runner.lock":-StartNow 先清残留进程再启动
实测发现(比文档问题更要紧):runner 网页 online、-Status 说 daemon 在跑,
但 runner-watchdog.log 每 10 秒刷 "starting daemon → daemon exited, exit code 1",
daemon 日志写 "another gitea-runner process is already using .runner" /
"runner file is already locked by another process"。

根因:Unregister-ScheduledTask 不会带走旧实例启动的进程。13:22 重跑 bootstrap 时,
12:53 起的旧看门狗成为孤儿并继续养着旧 daemon,旧 daemon 占住 .runner.lock,
新注册任务启动的看门狗永远抢不到锁。online 是旧 daemon 在硬撑——任务实际谁也没管,
日志还在以约 20 MB/天 增长。

- ci_runner_bootstrap.ps1:-StartNow 新增 Stop-StaleRunnerInstances,先停孤儿看门狗
  再停残留 daemon(顺序不能反:只杀 daemon 会被活着的看门狗 10 秒内重拉),启动后
  等 12 秒回显单实例确认;-Status 新增重复实例计数 + daemon 日志锁冲突检测
- 指南 §3.4 补注销不停进程的说明与"纯注释改动不需重启任务";§7 排障表加
  "online 却每 10 秒重启"一行(含手工应急命令)
- §3.2 / README:deploy_runner_task.ps1 与 run_runner.cmd 状态由"仍在磁盘、建议删除"
  改为"已删除";README 补重跑部署前的锁冲突警示

机器侧同步(不在版本库):config.yaml 头部"常驻改用 sc.exe / New-Service"是 §3.0
已证伪的错误指引,改为看门狗口径并指向本文——改后 YAML 可解析且所有配置值逐项与
改前一致(只动注释);删除两个废弃脚本前核实计划任务动作目标是
run_runner_watchdog.ps1,删除不影响在跑 runner;check_env.ps1 指向废弃脚本的提示
改指 bootstrap(带 BOM 文件,改后 BOM 完好、语法 0 错)。

验证:pre-commit run --all-files 17 项全 Passed;bootstrap parse 0 错、纯 ASCII、
-DryRun 正常。当前 runner 仍 online(旧 daemon 硬撑),彻底归一需管理员跑一次
-StartNow 清残留。
2026-10-12 17:37:19 +08:00
wandering1 e6bcad86cb 修看门狗日志编码:*>> 在 PS5.1 默认写 UTF-16LE,污染同一个日志文件
现场(2026-10-12 注册计划任务后实测):runner-stdout.log 尾部按 UTF-8 读出来
是 "t i m e =   2 0 2 6 - 1 0 - 1 2 ...",即每个字节后面跟一个 NUL。

根因正是我自己刚写进文档的那条坑:PS 5.1 的 *>> 重定向由 Out-File 实现,而
Out-File 的默认编码是 UTF-16LE。同一个文件里 Log() 用 Add-Content -Encoding
ascii 写 ASCII 行、daemon 输出却以 UTF-16LE 追加,于是"一个文件两种编码",
排障时按 UTF-8 读就是乱码——等于把唯一的 runner 现场日志弄成不可读。

- daemon 输出改到独立文件 runner-daemon.log,显式 Out-File -Encoding utf8
  (不用 ascii:提交标题与作业输出可能含非 ASCII,ascii 会打成问号)
- 看门狗自身日志改名 runner-watchdog.log,与 daemon 输出彻底分离
- 模板与生成物均校验通过:parseErrors=0、nonASCII=0
- 旧 runner-stdout.log 保留作历史,不再写入
2026-10-12 13:21:06 +08:00
wandering1 0f0ea03ff4 修复bootstrap注册崩溃:StartWhenAvailable属任务设置而非触发器
现场:用户以管理员跑 -SetEnv -StartNow 时脚本抛
SetValueInvocationException(触发器上没有 StartWhenAvailable 属性),
而它是在"已注销旧任务、尚未注册新任务"之间抛的,等于把 runner 任务删没了。

- StartWhenAvailable 改设到 settings(MSFT_TaskSettings 继承属性,
  CIM 属性列表里看不见但可直接赋值,实测 StartWhenAvailable=True)
- 任务对象改由 New-WatchdogTaskPlan 统一构建,先构建、后注销旧任务
- Register-ScheduledTask 失败时显式告警"旧任务已删、CI 裸奔"并 exit 1
- 新增 -DryRun:免管理员即可全量校验 action/trigger/settings
- -Status 增补上次运行时间与返回码,并提示"非管理员看不见任务"

同时更正根因:旧计划任务其实一直存在(非管理员会话看不见,先前误判为
"从未注册"),但它跑的是单次 run_runner.cmd——daemon 属"正常退出"而非
"失败",计划任务的失败重启根本接不到,必须靠看门狗循环重拉。
2026-10-12 12:52:27 +08:00
wandering1 20ee35b76a 修复CI门禁三因:runner掉线致12个job零日志、L0探测回归全灭、gitlint在CI从不执行
1) runner 掉线:run 16~21 共 12 个 job 零日志。gitea-runner v4 的
   daemon 无服务支持、首次 Declare 失败即退出进程,Gitea/机器重启
   一次 CI 就静默停摆;叠加 cancel-in-progress 后症状是"任务凭空
   消失"。新增 scripts/ci_runner_bootstrap.ps1:等 Gitea 就绪 +
   崩溃自拉起看门狗 + 开机计划任务 + -SetEnv 写 MACHINE 级 DTU_*。
2) L0 自 33a4aa4 起在 runner 上必挂:Python 候选被收窄成 PATH python
   (msys64,无 pre-commit) + 仓库 .venv(gitignore),cppcheck 目录兜底
   亦被删,而机器级 DTU_* 从未设置。探测收进 ci_find_python.ps1
   (两 job 共用、可离线自测、恢复机器级安装兜底)。
3) gitlint 声明 stages:[commit-msg],而 --all-files 只跑 pre-commit
   stage → 17 个钩子定义 CI 只报 16 个且全绿。新增
   ci_gitlint_range.ps1 逐条校验本次范围,ci_local.py 增 L0b 段。
另:GITHUB_ENV/PATH/OUTPUT 写入显式 -Encoding ascii(PS 5.1 的
   Out-File -Append 默认 UTF-16LE,会把带 NUL 的行追加进 UTF-8 文件)
2026-10-12 12:39:27 +08:00