feat(V4B): V4.25 — 环境异常黄灯预判: 高位持续5s即常亮(将进入重学)

背景: V4.24 黄灯只在60s进入学习后才亮, 前60s操作员无可视反馈
改动: poll_yellow_led 模式4条件放宽 = g_env_resync || g_env_wait_cnt>=ENV_WARN_WAIT
  - ENV_WARN_WAIT=500tick(~5s) 放 TaskLoop.h 文件级(poll_yellow_led 可见)
  - dev>+4dlt 高位连续5s未回摆 → 黄灯预判常亮; 累计60s才真正学习(黄灯保持)
  - 预判≠学习: 回摆/目标靠近(wait清零) → 黄灯即灭, 不触发学习
tests/test_env_resync.c 扩展: 预判点亮时刻=500tick / 瞬态4000tick预判亮但不学
  / 打断回摆后预判灭; 5场景ALL PASS + 语法0 error
docs: devlog V2.23 + spec V2.4(ENV_WARN_WAIT行) + 产品手册 V2.8 同步
This commit is contained in:
wangfq
2026-09-02 18:40:39 +08:00
parent 672f143e99
commit 7fd120fdf3
7 changed files with 69 additions and 17 deletions
+23 -6
View File
@@ -21,6 +21,7 @@
#define STABLE_SETTLE_WINDOWS 2 // 连续 2 窗漂移达标
#define FREEZE_TIMEOUT 1000 // 打印饱和(dev>0 不再超时更新 Origin)
#define ENV_RESYNC_WAIT 6000 // V4.24: dev>+4dlt 高位连续 60s → 判定永久环境变化
#define ENV_WARN_WAIT 500 // V4.25: 高位连续 ~5s → 黄灯预判常亮 (TaskLoop.h)
#define ENV_LEARN_WINDOW 200 // V4.24: 环境学习窗口 2s
#define ENV_LEARN_MAX_TICKS 3000 // V4.24: 学习预算 30s, 超时放弃
@@ -54,6 +55,12 @@ static void env_reset(void)
g_env_tick = 0;
}
/* V4.25: 黄灯模式4 条件镜像 (TaskLoop.c poll_yellow_led) */
static int env_warn_active(void)
{
return g_env_resync || g_env_wait_cnt >= ENV_WARN_WAIT;
}
/* 与 TaskLoop.c env_resync_abort/apply 逐行一致 */
static void env_resync_abort(void)
{
@@ -155,11 +162,16 @@ static void test_permanent_change_recovers(void)
t_set(128095UL, 128856UL, 48);
int tick = 0;
for (; tick < 7000 && !ev_applied; tick++)
int warn_at = 0;
for (; tick < 7000 && !ev_applied; tick++) {
sim_tick();
if (!warn_at && env_warn_active())
warn_at = tick + 1; /* 首次黄灯预判条件成立 (wait>=500) */
}
printf("常量高位稳定: 学习启动=%d 替换=%d 替换tick=%d resync=%d\n",
ev_learn_start, ev_applied, tick, g_env_resync);
printf("常量高位稳定: 黄灯预判=%d 学习启动=%d 替换=%d 替换tick=%d resync=%d\n",
warn_at, ev_learn_start, ev_applied, tick, g_env_resync);
assert(warn_at == 500); /* V4.25: 高位 5s 即黄灯常亮预判 */
assert(ev_learn_start == 1);
assert(ev_applied == 1);
assert(tick == 6600); /* 6000 等待 + 3×200 窗 */
@@ -175,16 +187,20 @@ static void test_permanent_change_recovers(void)
static void test_transient_never_learns(void)
{
/* ② 瞬态高位短停 (铁块模拟): 40s(4000tick) 高位后回摆 → 不学习 */
/* ② 瞬态高位短停 (铁块模拟): 40s(4000tick) 高位后回摆 → 不学习
* 但 5s 后黄灯预判已亮 (wait>=500) — 预判亮 ≠ 进入学习 */
t_set(128095UL, 128856UL, 48);
for (int i = 0; i < 4000; i++)
sim_tick();
assert(ev_learn_start == 0);
assert(env_warn_active() == 1); /* 黄灯预判已亮 (wait=4000) */
printf("瞬态高位短停: 4000tick 时黄灯预判亮=%d (未学习)\n", env_warn_active());
/* 回摆进窗口 (CAPVD 回 Origin 附近), wait 清零 */
/* 回摆进窗口 (CAPVD 回 Origin 附近), wait 清零 → 黄灯预判灭 */
sim_CAPVD = 128100UL; /* dev=+5 窗口内 */
sim_tick();
assert(g_env_wait_cnt == 0);
assert(env_warn_active() == 0); /* 回摆解除, 黄灯灭 */
/* 再次高位 59s(5900tick) — 仍不足 60s 连续 → 不学 */
sim_CAPVD = 128856UL;
@@ -210,8 +226,9 @@ static void test_learn_interrupted_restarts(void)
sim_tick(); /* 学习窗1 未完 */
sim_CAPVD = 128000UL; /* dev=-95 窗口内(B 目标) */
sim_tick();
assert(g_env_resync == 0); /* 打断退出, 黄灯灭 */
assert(g_env_resync == 0); /* 打断退出 */
assert(ev_abort == 1);
assert(env_warn_active() == 0); /* wait 清零, 黄灯预判灭 */
/* 目标离开, 高位重新 60s → 学习 3 窗 → 替换 */
sim_CAPVD = 128856UL;