diff --git a/docs/DATA.md b/docs/DATA.md
index 894a7461..5528c29e 100644
--- a/docs/DATA.md
+++ b/docs/DATA.md
@@ -194,7 +194,7 @@ Top level: `{ season, seasonName, modes, economy, lpCapPerRound, bossOvertimeAft
### 2.1 Combat classification heuristic (`dmgType` / `attackKind` / `projectile` / `canHitFly`)
- `dmgType`: MEDIC (except `incantationmedic`) and `bard` → `heal`; trait text containing 法术伤害 or profession CASTER → `arts`; else `phys`.
- `attackKind`: `bard`, `phalanx`, `librator` → `none` (no normal attack); heal → `heal`; position RANGED or melee sub-professions with a ranged normal attack (`lord`, `fortress`, `shotprotector`, `agent`, `hookmaster`) → `ranged`; else `melee`.
-- `canHitFly`: ranged attackers unless the trait says 地面敌人 (投掷手); `skywalker` (蒂比) true.
+- `canHitFly`: ranged attackers unless the trait says 地面敌人 (投掷手) or the sub-profession is `fortress` (要塞: 灰毫, 号角 — DESIGN §22.13); `skywalker` (蒂比) true.
- These are defaults for the generic engine; kits may override.
### 2.2 Loadout choices: skills & modules (DESIGN §16)
@@ -493,9 +493,9 @@ Glyph legend (`rows`):
5. **Every non-DIY chess (258 records: 129 normal + 129 golden) has a resolvable default skill, stats and range** — no
skill anomalies.
6. **Skill triggers** (§2.2): the class rows cover every MANUAL skill of the class (all 重装 MANUAL skills are
- `TAKE_DAMAGE` but the six of the deliberate deviation, DESIGN §21.29, which are `DEFAULT` with `rawRule` `TAKE_DAMAGE`; 薄绿 / 卡涅利安 / 蜜蜡 / 玛恩纳 S2 `SEARCH`; 伺夜 / 魔王 / 浊心斯卡蒂 S3 `SP_FULL`) and no AUTO skill (古米 /
+ `TAKE_DAMAGE` but the six of the deliberate deviation, DESIGN §21.29, which are `DEFAULT` with `rawRule` `TAKE_DAMAGE`, and 余 S2, `SKILL_RANGE` on its x-1 (DESIGN §22.10); 薄绿 / 卡涅利安 / 蜜蜡 / 玛恩纳 S2 `SEARCH`; 伺夜 / 魔王 / 浊心斯卡蒂 S3 `SP_FULL`) and no AUTO skill (古米 /
雷蛇 / 瑕光 / 塞雷娅 / 号角 / 信仰搅拌机 S1, 伺夜 S1/S2, 魔王 S1); 13 MANUAL skills (26 normal + elite records) with
- their own 技能范围 are `SKILL_RANGE` (德克萨斯 S2, 凛御银灰 S2, 锏 S2/S3, 异客 S3, 忍冬 S2, 焰尾 S2 …).
+ their own 技能范围 are `SKILL_RANGE` (德克萨斯 S2, 凛御银灰 S2, 锏 S2/S3, 异客 S3, 忍冬 S2, 焰尾 S2 …); 余 S2 joins them by the §22.10 deviation, 14 skills / 28 records in the data.
7. **Trait candidate `rangeId`** (送葬人, 松果 1-3; 风丸, 归溟幽灵鲨 x-4) is the trait-effect area, exposed as
`trait.rangeGrid`, not the attack range.
8. **Passive skills** use numeric `spType 8` in skill_table → normalized to `ON_DEPLOY`.
diff --git a/docs/DESIGN.md b/docs/DESIGN.md
index 6b8727fd..98ce0134 100644
--- a/docs/DESIGN.md
+++ b/docs/DESIGN.md
@@ -280,7 +280,7 @@ Engine helpers (content must use these, never touch internals): `battle.dealDama
SP: `spType` `INCREASE_WITH_TIME` (+`spRecovery`/s), `INCREASE_WHEN_ATTACK` (+1 per attack), `INCREASE_WHEN_TAKEN_DAMAGE` (+1 per hit taken); starts at `initSp`; no SP gain while a duration skill is active. `maxChargeTime > 1` ⇒ charges.
-Auto-trigger rules (`skillTrigger.rule` in data — the official 技能策略, PRTS 卫戍协议/帮助 §作战阶段 技能操作; §20.2): `DEFAULT` (SP ready AND about to attack/heal AND an enemy/injured ally inside the **initial** range, or an enemy the unit blocks; with `trigger.allies` + `hpAtMost` an ally of the skill grid at or below that HP ratio — 塞雷娅 S1 急救, whose cast replaces that attack and is withdrawn with its charge if the ally recovers first), `SKILL_RANGE` (a MANUAL skill with a 技能范围 of its own, not an attack-range change: any living enemy, stealthed ones included, on the skill range, checked every tick — "仅在技能范围内存在敌人(无视其不可选中)时释放技能"; 13 skills / 26 records), `TAKE_DAMAGE` (on taking damage — any damage, 无来源 included, never a 流失; every MANUAL 重装 skill, §21.12 — but the six of the deliberate deviation, §21.29: 深巡 / 雷蛇 S2, 号角 S2 / S3 and 灰毫 S1 / S2 are `DEFAULT`, `rawRule` keeping the official TAKE_DAMAGE), `SP_FULL` (immediately — 执旗手 / 战术家 / 吟游者 MANUAL skills, and AUTO DP skills such as 伺夜 S1, 焰尾 S1, 凛御银灰 S1), `CUSTOM_RANGE` (enemy inside the custom grid), `SEARCH` (an enemy inside the initial range, checked every tick — no attack needed; 解放者 / 阵法术师 MANUAL skills), `GDGLOW_SKILL_2` (a valid target anywhere on the field: 荒芜拉普兰德, 纯烬艾雅法拉 S3), special ids. The class rows cover **every MANUAL skill** of the class and never an AUTO skill (AUTO skills keep their own rule — an inference: PRTS names whole classes; the data's `skillIndex 0` / `-1` sentinel argues the other way, §20.2). **Operation cooldown**: the engine auto-casts a MANUAL skill no sooner than `AUTO_OP_COOLDOWN` (3 s) after its previous cast and after the unit's battle-start deployment ("自动操作具有3s冷却,在完成一次操作或作战开始时部署的单位将进入冷却"; `Battle._deploy` initial, `battle.flags.startOpCooldown`); kits with an automatic cast of their own check `skill.opCooling`; a pending "next attack" never takes a second charge. PASSIVE skills are always on.
+Auto-trigger rules (`skillTrigger.rule` in data — the official 技能策略, PRTS 卫戍协议/帮助 §作战阶段 技能操作; §20.2): `DEFAULT` (SP ready AND about to attack/heal AND an enemy/injured ally inside the **initial** range, or an enemy the unit blocks; with `trigger.allies` + `hpAtMost` an ally of the skill grid at or below that HP ratio — 塞雷娅 S1 急救, whose cast replaces that attack and is withdrawn with its charge if the ally recovers first), `SKILL_RANGE` (a MANUAL skill with a 技能范围 of its own, not an attack-range change: any living enemy, stealthed ones included, on the skill range, checked every tick — "仅在技能范围内存在敌人(无视其不可选中)时释放技能"; 13 skills / 26 records by the official rule, 14 / 28 in the data with 余 S2's deviation, §22.10), `TAKE_DAMAGE` (on taking damage — any damage, 无来源 included, never a 流失; every MANUAL 重装 skill, §21.12 — but the six of the deliberate deviation, §21.29: 深巡 / 雷蛇 S2, 号角 S2 / S3 and 灰毫 S1 / S2 are `DEFAULT`, `rawRule` keeping the official TAKE_DAMAGE; and 余 S2, `SKILL_RANGE` on its x-1 (§22.10)), `SP_FULL` (immediately — 执旗手 / 战术家 / 吟游者 MANUAL skills, and AUTO DP skills such as 伺夜 S1, 焰尾 S1, 凛御银灰 S1), `CUSTOM_RANGE` (enemy inside the custom grid), `SEARCH` (an enemy inside the initial range, checked every tick — no attack needed; 解放者 / 阵法术师 MANUAL skills), `GDGLOW_SKILL_2` (a valid target anywhere on the field: 荒芜拉普兰德, 纯烬艾雅法拉 S3), special ids. The class rows cover **every MANUAL skill** of the class and never an AUTO skill (AUTO skills keep their own rule — an inference: PRTS names whole classes; the data's `skillIndex 0` / `-1` sentinel argues the other way, §20.2). **Operation cooldown**: the engine auto-casts a MANUAL skill no sooner than `AUTO_OP_COOLDOWN` (3 s) after its previous cast and after the unit's battle-start deployment ("自动操作具有3s冷却,在完成一次操作或作战开始时部署的单位将进入冷却"; `Battle._deploy` initial, `battle.flags.startOpCooldown`); kits with an automatic cast of their own check `skill.opCooling`; a pending "next attack" never takes a second charge. PASSIVE skills are always on.
**SkillSpec** (authored per chess in `sim/content/kits/tierN.js`; values come from the chess's skill blackboard at its level — normal Lv4, elite Lv7 — so a spec is a *function of the blackboard*):
```js
@@ -848,7 +848,7 @@ Eight workstreams were merged into `playtest6` (WH → WG → WD → WC → WB
- **#15 seen**: a skill whose range is wider than the attack range did not fire when an enemy entered it (德克萨斯 剑雨 13 tiles vs 2; 凛御银灰 S2; 锏 S3). **Cause**: every MANUAL skill used the basic rule, and research 03 C1 read the class rows (`skillIndex 0`) as "skill 1 only" (BWIKI).
- **Official** (PRTS 卫戍协议/帮助 §作战阶段 技能操作): basic rule "技能就绪,且即将进行普通攻击/治疗"; a skill with its own 技能范围 (not an attack-range increase) "不通过普通攻击/治疗触发技能,仅在技能范围内存在敌人(无视其不可选中)时释放技能"; class strategies — 重装 "不受技能范围影响,受到伤害时释放技能" (下半, 2026/3/14), 战术家 / 执旗手 / 吟游者 when ready, 解放者 / 阵法术师 an enemy in the initial range, 澄闪 / 纯烬 / 荒芜 S3 "全场存在可选目标时"; "自动操作具有3s冷却,在完成一次操作或作战开始时部署的单位将进入冷却".
-- **Now** (§5.6): the class rows cover **every MANUAL skill** of the class and never an AUTO one — an inference (PRTS names whole classes; under the old reading the 阵法术师 row could never cover 薄绿's default S2, a phalanx never attacks with its skill off); counter-evidence kept: BWIKI's "技能1" and the data's `skillIndex 0` / `-1` sentinel. `SKILL_RANGE`: 13 skills (26 records with the elites), any living enemy on the skill range, checked every tick (attack-range changes keep the basic rule). `GDGLOW_SKILL_2`: a valid target anywhere. The 3 s operation cooldown after each automatic cast and after the battle-start deployment (`flags.startOpCooldown`; the test harness sets it to 0); kit-driven casts of MANUAL skills (波登可 S1, 雪猎 bullets, the 流形 copy) check `skill.opCooling`; AUTO skills are exempt; a pending "next attack" never takes a second charge. Players notice: every 重装 manual skill (号角 S3, 瑕光 S3, 灰毫 S2 — reversing §19.2 —, 古米 S2 …) now waits for the operator to be hit — **partly reverted by §21.29**: by the owner's deliberate deviation (2026-10-03, community feedback) 深巡 / 雷蛇 S2, 号角 S2 / S3 and 灰毫 S1 / S2 cast with an enemy in range (DEFAULT) again.
+- **Now** (§5.6): the class rows cover **every MANUAL skill** of the class and never an AUTO one — an inference (PRTS names whole classes; under the old reading the 阵法术师 row could never cover 薄绿's default S2, a phalanx never attacks with its skill off); counter-evidence kept: BWIKI's "技能1" and the data's `skillIndex 0` / `-1` sentinel. `SKILL_RANGE`: 13 skills (26 records with the elites; 14 / 28 in the data since 余 S2's deviation, §22.10), any living enemy on the skill range, checked every tick (attack-range changes keep the basic rule). `GDGLOW_SKILL_2`: a valid target anywhere. The 3 s operation cooldown after each automatic cast and after the battle-start deployment (`flags.startOpCooldown`; the test harness sets it to 0); kit-driven casts of MANUAL skills (波登可 S1, 雪猎 bullets, the 流形 copy) check `skill.opCooling`; AUTO skills are exempt; a pending "next attack" never takes a second charge. Players notice: every 重装 manual skill (号角 S3, 瑕光 S3, 灰毫 S2 — reversing §19.2 —, 古米 S2 …) now waits for the operator to be hit — **partly reverted by §21.29**: by the owner's deliberate deviation (2026-10-03, community feedback) 深巡 / 雷蛇 S2, 号角 S2 / S3 and 灰毫 S1 / S2 cast with an enemy in range (DEFAULT) again.
- **Integration follow-up (WE review round 2)**: the AUTO DP skills 焰尾 S1 迅敏直觉 and 凛御银灰 S1 周旋的谋略 ("立即获得…部署费用") are `SP_FULL` like 伺夜 S1 and 德克萨斯's 冲锋号令·γ型 — an AUTO skill takes no 技能策略 (they used to wait 12–16 s for the next attack).
- **#16**: 古米 备用军粮 (AUTO) had picked up the 重装 row. PRTS 备注 "存在生命值不满的可治疗角色时可触发;…切换至治疗模式…直至古米完成一次普通攻击的治疗": it fires on an injured ally of its x-4 area and her next attack heals the most injured ally there (`heal_scale` × ATK); S2 食粮烹制 is MANUAL, so the 重装 rule. Audit: 塞雷娅 S1 急救 — PRTS 备注 "仅在周围有符合血量条件的友方单位时可触发,触发时会替换当次攻击", 修正 "血量小于等于一半" — is checked at her attack (DEFAULT + `allies` + `hpAtMost` 0.5) and that attack becomes the heal; a cast whose ally recovered first is withdrawn with its charge.
- **#8**: 新约能天使 S2 gave the shield to the fastest attacker; official (PRTS 备注) "攻击范围内仇恨值最高的我方干员" — now `aggroCmp` (taunt, then the latest deployed), through `battle.alliesInGrid` (孤立 units skipped). The amounts were already right: 180 % (精锐 200 %) of each holder's own max HP, decaying by initial / 30 per s.
@@ -859,7 +859,7 @@ Eight workstreams were merged into `playtest6` (WH → WG → WD → WC → WB
| Skill (examples) | type | before → after | why |
|---|---|---|---|
| 德克萨斯 S2 剑雨, 凛御银灰 S2, 锏 S2 / S3, 异客 S3, 焰尾 S2, 忍冬 S2, 诗怀雅 S1, 山 S3, 小满 S2, 归溟幽灵鲨 S1, 崖心 S2, 见行者 S2 | MANUAL | DEFAULT (kit CUSTOM_RANGE) → SKILL_RANGE | own 技能范围 |
-| 深巡 S2, 古米 S2, 折桠 S2, 瑕光 S2 / S3, 信仰搅拌机 S2 / S3, 泥岩 S3, 塞雷娅 S3, 余 S2, 角峰 / 雷蛇 / 泡泡 / 菲莱 / 蛇屠箱 S2, 灰毫 S2, 星熊 S3, 号角 S2 / S3 | MANUAL | DEFAULT → TAKE_DAMAGE (深巡 / 雷蛇 S2, 号角 S2 / S3, 灰毫 S1 / S2 back to DEFAULT, §21.29) | 重装 row (§21.29: a deliberate deviation for six skills) |
+| 深巡 S2, 古米 S2, 折桠 S2, 瑕光 S2 / S3, 信仰搅拌机 S2 / S3, 泥岩 S3, 塞雷娅 S3, 余 S2, 角峰 / 雷蛇 / 泡泡 / 菲莱 / 蛇屠箱 S2, 灰毫 S2, 星熊 S3, 号角 S2 / S3 | MANUAL | DEFAULT → TAKE_DAMAGE (深巡 / 雷蛇 S2, 号角 S2 / S3, 灰毫 S1 / S2 back to DEFAULT, §21.29; 余 S2 now SKILL_RANGE on its x-1, §22.10) | 重装 row (§21.29: a deliberate deviation for six skills) |
| 薄绿 S2, 蜜蜡 S2, 卡涅利安 S2 / S3, 玛恩纳 S2 | MANUAL | DEFAULT → SEARCH | 阵法术师 / 解放者 row |
| 伺夜 S3, 魔王 S2 / S3, 浊心斯卡蒂 S3 | MANUAL | DEFAULT → SP_FULL | 战术家 / 吟游者 row |
| 古米 S1, 瑕光 S1, 塞雷娅 S1 | AUTO | TAKE_DAMAGE → own rule (古米: injured ally; 塞雷娅: at her attack, ally ≤ 50 %) | AUTO: no 技能策略 |
@@ -1338,7 +1338,7 @@ Settled by the user:
| Bounty drafts (§21.2) | the official structure of each round from the user's 66 screenshots of 22 matches (R3 fixed sets, R9 boss groups, R11 seen 7-card lists; no multi-round card in a draft) | add a newly seen set / group / list to `tools/build-data.mjs BOUNTY_INITIAL_SETS / BOUNTY_BOSS_GROUPS / BOUNTY_HUNTER_GROUPS` and rebuild |
| 机密商店 / 战术决策 repeats (§21.2) | the same card can be offered twice, as officially (the user, 2026-10-03: "机密商店按官方改成可以重复吧", "战术决策也按官方改成可以重复吧"); R11 机密商店 = two VI, ≥ 1 V, ≥ 1 盟约之币 | `choices.json shopDraft` / `tacticDraft` removed (choices.js falls back to the previous draws, still with replacement) |
| 坚固维式重锤's scope (§21.21) | one 不死 lock per DEPLOYMENT: the carrier's own redeploy (after a knock-out, a 突袭 retreat + redeploy) re-arms it and ends a window still running (the user, 2026-10-03: "每次部署一次"; the text says only 首次); the lock belongs to the deployment, so a borrowed hammer (萨尔贡 × 娜仁图亚) follows the same rule | `content/items/battle.js deploymentOf` returning one key for the whole battle (one lock per battle) |
-| Six 重装 skills' trigger (§21.29) | 深巡 S2, 雷蛇 S2, 号角 S2 / S3 and 灰毫 S1 / S2 cast with an enemy in range (the basic strategy, DEFAULT) instead of the official 下半 TANK row's TAKE_DAMAGE — a deliberate, documented deviation (the owner, 2026-10-03: "反馈的人太多了"; GitHub issue #4, PR #12); every other MANUAL 重装 skill, 深巡 S1 included, waits for a hit | remove the entry from `tools/build-data.mjs TRIGGER_DEVIATIONS` (for 深巡 / 雷蛇 also PR #12's `trigger: 'DEFAULT'` kit line) and rebuild |
+| Six 重装 skills' trigger (§21.29) | 深巡 S2, 雷蛇 S2, 号角 S2 / S3 and 灰毫 S1 / S2 cast with an enemy in range (the basic strategy, DEFAULT) instead of the official 下半 TANK row's TAKE_DAMAGE — a deliberate, documented deviation (the owner, 2026-10-03: "反馈的人太多了"; GitHub issue #4, PR #12); every other MANUAL 重装 skill, 深巡 S1 included, waits for a hit (余 S2 excepted since 2026-10-04: the owner extended the deviation to 余 S2, which casts with an enemy on its x-1 — `SKILL_RANGE`, §22.10) | remove the entry from `tools/build-data.mjs TRIGGER_DEVIATIONS` (for 深巡 / 雷蛇 also PR #12's `trigger: 'DEFAULT'` kit line) and rebuild; for 余 S2 remove its `TRIGGER_DEVIATIONS` entry (`chess_char_6_03_a`) and rebuild |
| Multi-round bounties (§20.6, unchanged) | last two battles — now only 教鞭's card | `server/match/choices.js MULTI_ROUND_BOUNTY_BATTLES = null` |
| §20.9's decisions | unchanged (start-deploy summons, 凯瑟琳's hand card, every blocker hits, the collider reach, the elite to the board, the fixed leader pool, the watched bond strip) | as §20.9 |
@@ -1456,11 +1456,11 @@ Two public GitHub issues after 0.1.0, both client-only. Normative lines rewritte
- One-line flip: remove the entry from `TRIGGER_DEVIATIONS` (for 深巡 / 雷蛇 also the kit line) and rebuild.
- Normative lines rewritten with it: §5.6 (`TAKE_DAMAGE`), §19.2 (灰毫 S2), §20.2 (players notice, the table), §21.20 (a settled row), §21.23 (深巡 on a fenced tile).
- Tests: `test/sim/feedback1-tank-triggers.test.js` (the data, kit = data, the real battle for the six and for every other MANUAL 重装 record), `test/data.test.js`, `kits_t1t2` / `kits_alt_t1` (PR #12's), `kits_alt_t2` (灰毫 S2), `kits_t5` / `kits_alt_t5` (号角), `test/docs-consistency.test.js`.
+- Extended 2026-10-04: 余 S2 (SKILL_RANGE on its x-1, §22.10); 14 records deviate now.
## 22. GitHub issues after 0.1.1 (v0.1.2)
-TBD-22-intro
-
+Public GitHub issues filed after the 0.1.1 release (2026-10-03), each triaged against 0.1.1 first; the real ones were fixed for 0.1.2 in fix branches WA–WL, each independently reviewed before it was merged into `feedback2`. Where each is handled: #25 back-facing operators keep their attack pose when knocked out → §22.1; #51 突袭's idle redeploy → §22.2; #33 items 1–2 阿戈尔's devour and 乌尔比安 S3 → §22.3; #33 item 6 活性源石, with the 沼泽 and 深水区 terrain → §22.4; #42 emotes and guide pages without a local client, and the English title (#38) → §22.5; #32 item 4 钩索师 / 推击手 on 高台 → §22.6; #52 史尔特尔's 余烬 → §22.7; #43 an enemy's 隐匿 after a block, and the 深池逐火 ember window → §22.8; #32 item 7 荒芜拉普兰德 S3's drones → §22.9; #32 item 1 余 S2 → §22.10; #44 归溟幽灵鲨's 替身 → §22.11; #32 item 6 enemy splash against a 隐匿 operator → §22.12; #35 / #16 (PR #48) 要塞 against air units and 莫斯提马's slow icon → §22.13; #58 / #60 / #64 follow in §22.14–§22.16. Decisions of the owner, 2026-10-04: 荒芜拉普兰德's drones measure the distance to an enemy's position, a huge enemy's centre (§22.9); 余 S2 casts with an enemy on its x-1 — a deliberate deviation from the official TAKE_DAMAGE row, added to §21.29's six (§22.10); 乌尔比安 keeps the devour gains through his 【移动】 — the deviation stays (§22.3).
### 22.1 Back-facing operators play their fall (GitHub #25) — `render/units.js _wantsBack / _syncModel / die / revive / _acquireSpine / _dropActor / dieClipDur`, `render/spine.js SpineActor.die / dieClip / deployElapsed`
@@ -1477,7 +1477,6 @@ TBD-22-intro
- [ASSUMED]: the Front model for the fall and the knocked-down pose (above); the Back skeleton's own Die clip when it has one; the held first idle frame of a skeleton without a Die clip.
- Tests: `test/render/issue25-downback.test.js` (fake PIXI with the real manifest and asset helpers: the manifest counts; the five operators of the report lie down with their Front model's Die; an UP knock-out mid-attack — the Back model holds still, then the Front model's Die is held under the ring, greyed, every acquire paired with a release; RIGHT unchanged; the redeploy back to the Back model with the deploy clip carried over; the snapshot's DIE anim and a snapshot revive; a death and a redeploy in one frame load nothing; a view built for an operator already down and the 联防 entry lie on the held end; a withdrawn one fades like a RIGHT one; 薄绿 keeps its Back Die clip; the SpineActor safety net; enemies and summons unchanged); `downring`, `feedback1f-down-tile`, `unitview`, `forms`, `test/ui/unitFacing.test.js` unchanged.
-
### 22.2 突袭's idle redeploy lands where it can attack (#51) — `content/bonds/addon/battle.js raidPoll / raidTile / raidReach / raidTargets`, research 02 §3.18
- **Seen** (GitHub issue #51, on 0.1.0): a 突袭 member idle for 10 s was redeployed even when no landing tile let it attack an enemy, so it hopped every 10 s between useless tiles; and the idle trigger always went for the most advanced enemy, even when another ground enemy could have been reached. **Real** (reproduced on 0.1.1): with one speed-0 enemy that no landing tile reaches (it stands on plain floor, and a RIGHT-facing melee member reaches it only from that tile or the floor tile behind it), the member jumped at 10 / 20 / 30 / 40 s between (10,9) and (10,8) beside it and never attacked; a second, reachable enemy was ignored. On the five real runs of the F5 test (`test/sim/feedback1f-downed-tile.test.js`) 26 of 60 jumps landed with no enemy in range — e.g. three members jumping to one enemy whose two reachable tiles the first two took.
@@ -1489,7 +1488,6 @@ TBD-22-intro
- [ASSUMED]: "never a useless landing" (the text says only 再部署至一名地面敌人周围; issue #51); the cap of 8 candidates (a member waits when the 8 most advanced ground enemies are all out of reach — the 技能就绪 path's bound since 0.1.0, kept for the cost); the target order and the 2-tile search (research 02 §3.18, now written as above). Issue #49 (a passive skill never counts as 技能就绪) is unchanged and separate: it decides when a member may jump, this section where it lands.
- Tests: `test/content/bonds_addon.test.js` "突袭 #51" ×2 (no reachable landing: neither trigger jumps in 45 s, then a reachable enemy → both jump within one poll; an unreachable leading enemy is passed over for the second, which it attacks, and the next jump comes the idle time after its last attack); the other 突袭 tests (`bonds_addon`, `feedback1-water`, `feedback1f-downed-tile`, `facing-invariance`) unchanged.
-
### 22.3 阿戈尔's devour skips members it has already knocked out (#33 item 1) — `content/bonds/core.js devour`, `content/items/battle.js deploymentOf` (exported through `content/items.js`), `kits/tier5.js` (乌尔比安 S3, #33 item 2)
- **Seen** (GitHub #33 item 1, "阿戈尔阵营复活机制看起来不会触发"): the 5-tier revive works on its own (5 distinct 阿戈尔, one lethal hit each: the first 3 come back on their tile at full HP, normal and 联防 battles alike), but the usual food chain used it up at t = 0. One row, all facing right, 浊心斯卡蒂 → 乌尔比安 → 幽灵鲨 → 海霓 → 深巡 → 隐现: the battle-start devour knocked out 幽灵鲨, 海霓 and 深巡, the revive brought each straight back (all 3 charges), and 乌尔比安's marks still pending on them knocked them out a second time — down until their 70 / 80 s redeploy, no revive left for the fight (联防 battles alike).
@@ -1502,7 +1500,6 @@ TBD-22-intro
- [ASSUMED]: (1) a marker revived during the pass keeps the base ATK / block it gained at marking (a persistent buff, as through every knock-out since 0.1.0). (2) With the anchor on his own tile, 乌尔比安's 【移动】 does not try "the tile one beyond the landing" (he would otherwise step one tile forward).
- Tests: `test/content/bonds_core.test.js` (the chain in a normal and a 联防 battle: one knock-out and one revive each, all five standing, the next knock-out final; a marker revived by the 5-tier revive still gives its marks; a target 埃芒加德 revived in place takes none — one revive spent, not two; a target 不屈 redeployed takes none and stays standing), `test/content/kits_t5.test.js` (乌尔比安 S3 while he blocks: the anchor on his own tile, no move, no marker; a flyer over his tile, not blocked: the anchor ahead and the move, as in 0.1.1).
-
### 22.4 活性源石 stays on an enemy after it leaves the tile (#33 item 6) — `server/sim/content/devices.js` (`touchInfection`, `enterTerrain`, `terrainFor`, `tickMire`, `deepWaterDamage`), `content/enemies.js` (`rebirthCleanse`, `kitDeepsea`), `tools/build-data.mjs` (`special.mire`)
- **Seen** (public issue #33, other part 3: 「红地板图敌方单位经过后,红地板附带的效果会消失」): on 战场#04 an enemy lost the red floor's effect the moment it walked off it. Measured on v0.1.1 (the real stage): an enemy on (10,6) from 15.67 s to 19.67 s lost 4 × 70 HP; 12 s later it still had 99720 / 100000 HP and no ATK / ASPD bonus.
@@ -1516,7 +1513,6 @@ TBD-22-intro
- **深水区, official** (PRTS 涨潮控制 技能3 深水: "【水蚀】的敌方单位每秒受到40点无来源真实持续伤害(不属于环境伤害,不会触发受击回复)"; PRTS 自然环境: 涨潮's damage to enemies "并非环境伤害"; PRTS 伤害分类 lists 深水区/涨潮水蚀 as BUFF damage). **Cause**: the deep-water tick shared the `terrain` tag with 活性源石, so 纠缠藤蔓 turned ×2 fragile in deep water (360 HP lost in 5 s instead of 200) and 锡人's 凋敝魂灵 ("受到的持续伤害提高") never raised it. **Now**: `deepWaterDamage` — 无来源 true, `canDodge: false`, `sourceless`, `noSp`, tags `dot` / `periodic` / `deepsea`, no `terrain`. The 免疫水蚀 swimmers (潜水员) cancel only `deepsea` / `drown` damage, not 环境伤害.
- Tests: `test/content/tokens_devices.test.js` — 活性源石 (the operator and the enemy standing on it), an enemy keeps the effect after leaving the tile (20 s later: 70/s, ATK, ASPD, the time left), one effect per unit (two passes give one effect that ends `duration` s after the last contact, 70/s while it lasted; an operator drains for 3 × `duration`, keeps the effect after `Battle.relocate` and loses it `duration` s later), a 重生 clears it (a 深池逐火战士 that crossed the tile stands up from its ember after 1 + 10 s), 沼泽 (the data; operators ASPD only; 重量 1 vs 3: 1 vs 2 layers a second, at most 10; cleared on leaving), 深水 (the tick's tags; 纠缠藤蔓 not fragile); `test/content/enemies_bosses.test.js` (潜水员: the deep-water tick is cancelled, 环境伤害 is not).
-
### 22.5 Emotes and guide pages without a local client; deployment docs (#42); the English title (#38) — `tools/assets/plan.mjs UI_EXTRAS / GUIDE_PAGES`, data/assets.json `ui['emoticon/
/']` / `ui['guide/']`, `data.js artUrls / nextArtUrl`, `ui/emotes.js emoteArtUrls / EmoteArt`, `ui/guide.js guidePages / GuideHost`, `tools/setup.mjs LOCAL_ART_FALLBACK / LOCAL_ART_COPY_HINT`, `tools/doctor.mjs`, README, docs/DEPLOY.md §6, `server/index.js` banner, package.json `name`
- **#42 seen**: "游玩时左下角的六页表情全部显示为默认图标" — a Linux server deployed from source (git clone, setup with the asset download, Node 22); copying `public/assets/local/` and `data/local-assets.json` from the release bundle fixed it. **Real**: both are extracted from a locally installed client (§13; setup extracts only when it finds one), and the emote art and the 玩法说明 pages came from there only, so a source deploy without the client drew the neutral glyph for all 36 emotes and the official tips text instead of the 19 pages. README, DEPLOY.md, setup and doctor said the local art did not matter ("不影响游戏", "其他功能不受影响") — wrong: the 3D board, part of the official HUD art and two enemy models fall back too.
@@ -1529,7 +1525,6 @@ TBD-22-intro
- [ASSUMED]: none.
- Tests: `test/assets.test.js` (the 55 plan entries and URLs, a rebuilt manifest, the committed manifest lists them), `test/ui/localArt.test.js` (the lookup order, a server without the client, `guideStage`, GUIDE_PAGES = GUIDE_CHAPTERS), `test/fetch-assets-shrink.test.js` (a failed mirror run keeps the manifest), `test/static-local-art.test.js` (the docs and messages), `test/version.test.js` (the English title), `test/doctor.test.js`.
-
### 22.6 钩索师 and 推击手 on 高台 (#32 item 4) — `tools/build-data.mjs PLACE_ON_RANGED_RE / branchTraitText / validateAll`, chess.json `placement`, `match/board.js positionClass / basePositionClass`, `ui/gameLogic.js piecePosition`, `match/bot.js isBlocker / planLayoutSteps`, `tools/balance.mjs`
- **Seen**: public issue #32 item 4 — "哥蕾蒂娅无法部署到高台". 0.1.1 refused every 高台 tile for her (server `BAD_TILE`; the client lit no 高台 and said 近战单位只能部署在地面), and the same for 崖心 (钩索师) and 见行者 (推击手), normal and elite.
@@ -1541,3 +1536,112 @@ TBD-22-intro
- On a 高台 she is not a 地面干员 for the effects that read the tile (`unit.ground`: the 战栗维式重锤 proc, 休谟斯 回收利用, 不屈, the 只攻击地面单位 enemy, 污染秽蚀's 高地 rate), like a ranged operator up there; position-based effects keep her 近战 (精准 tier 2, 诗怀雅's talent) [ASSUMED: the official texts may mean the position class by 地面干员].
- Normative lines rewritten with it: §3 (placement), §6.6 (the bot); research 03 C2; DATA §2 (`placement`).
- Tests: `test/match/feedback1-placement.test.js` (#32-4: the data rule, cross-checked against character_table when the cache exists; `g.move` onto (10,4) / (11,4) / (12,4) of 战场#01(下半) for the six records; a 重装 refused with its text; ranged unchanged; client highlights = the server's tiles; swaps; the merge's elite on the 高台; the battle input and the sim on / off the 高台; bots), `test/match/board.test.js` (`positionClass` / `basePositionClass`), `test/ui/gameLogic.test.js` (the client mirror).
+
+### 22.7 史尔特尔's 余烬 holds 禁疗 (GitHub #52) — `kits/tier5.js` (史尔特尔 余烬 / S3), `sim/damage.js heal`, `sim/buffs.js` (`healFree`), `render/style.js STATUS_ICON`, `render/textures.js STATUS_KEYS / drawStatusIcon`
+
+- **Seen** (GitHub #52 「史尔特尔进入锁血后仍能被治疗」): during the 8 s of 余烬 medics kept healing her. v0.1.1 measured: a 赫默 beside her healed her twice for 738 HP; with a 50 % HP 深巡 also in range, 赫默 spent 1,107 of its 1,845 HP of healing on her — on a unit that leaves anyway.
+- **Official** (checked on PRTS 2026-10-03): chess talent 余烬 (`chess_char_5_07_a` / `_b`) 「受到致命伤害时持续使生命值不低于1,8秒后强制退出战场」 (bb `surtr_t_2[withdraw].interval` 8); PRTS 史尔特尔 天赋备注 "持有不死的情况下不会触发此天赋" / "触发本天赋后,获得禁疗与不死" / "强制退出战场视为撤回干员"; PRTS 异常效果 禁疗 (HEAL_FREE) "无法成为治疗类能力的目标,且受到的治疗量变为0 ※…增减生命回复速度或生命回复速度(百分比)属性的效果不会被识别为治疗类能力"; PRTS 史尔特尔 技能3 备注 "生效后立刻治疗自身当前最大生命值100%的生命值(无视禁疗)".
+- **Cause**: the talent only prevented the blow and scheduled the retreat. Nothing marked her 禁疗, so every heal pick (`Battle.injuredAlliesInKeys` and the kits' own) chose her as the lowest HP ratio and `heal()` let the heal through. The sim's `noHeal` (the 禁疗 summons, 孤立, 武者 / 收割者 / 不屈者, 艾丝黛尔 S1, 烛煌's 倒地) stops only heals from other units (`!self` in `damage.js heal`), the "不能被其他…治疗" of those traits.
+- **Now**: the trigger adds `surtr:ember` = flags `noHeal` + `healFree` with the status `'healFree'` (a green cross struck through in the unit's status row) until she leaves; the retreat drops it. `healFree` in `damage.js heal`: no heal reaches the unit, its own included (休眠子裔's heal on attack, …), except an HP-regen attribute tick (`regen`: the engine's natural regeneration from `hpRegen` / `hpRegenRatio`, e.g. 安洁莉娜's 兼职工作) and a heal flagged `ignoreHealFree` (her S3's start heal, "无视禁疗": S3 starting inside the window heals her to full). Every heal pick already skips `noHeal` units, so medics heal the next injured ally. 不死 (a later lethal blow inside the window changes nothing and does not restart the 8 s) and the retreat at 8 s are unchanged. Other `noHeal` users are unchanged: the summons' 禁疗 (tokens.json `abnormal` `healFree`) keeps `noHeal` only — no self-heal reaches them but 伺夜 S2's 恢复 of its 禁疗 狼群, which the skill text grants.
+- **Measured** (the same layout): 0 heals reach her (v0.1.1: 2 heals, 738 HP); 赫默 heals the 50 % 深巡 instead (1,107 HP in 12 s); she leaves 8.03 s after the blow.
+- [ASSUMED]: on the same first lethal blow 余烬 (`fatal` −60) runs before 坚固维式重锤's lock (`PRIO_REVIVE` −100), so the hammer never starts while 余烬 is unused (PRTS gives no order); the status lasts until the retreat rather than a fixed 8 s. Known deviations, outcome-neutral (she is 不死 and leaves at 8 s anyway): 余's 闲云隐市 and 天马之盔's 8 %/s use `hp_recovery_per_sec_by_max_hp_ratio`, the 生命回复速度(百分比) attribute that PRTS 禁疗 exempts, but they run as kit heals (`battle.heal`) here, so 禁疗 stops them on her (moving them to the regen attribute would also change the bleed removal and heal-bonus hooks of other units); the forced exit's 「返还部分部署费用」 DP refund is not modelled (no retreat in the sim refunds DP); a chain healer's bounces skip her (ai.js `doHeal` chain filter, review of #52).
+- Tests: `test/sim/feedback2-surtr-stealth.test.js` (the medic beside her, her own heals / regen / S3's start heal, the status events), `kits_t5`, `items`, `playtest6-combat` (the 禁疗 summons), `render/tiles` / `boardart` / `fxproj` (the status atlas).
+
+### 22.8 An enemy's 隐匿 returns 3 s after a block; the 深池逐火 embers (#43 follow-up, players' "the stealth monster revives forever") — `sim/Battle.js _stealthSwitch / _unblock / releaseBlocked / foesInRadius`, `sim/ai.js enforceBlockCapacity`, `sim/targeting.js enemyStealthed / stealthOffKey / canTargetEnemy`, `sim/snapshot.js flagsOf`, `sim/constants.js STEALTH_RESTORE`, `sim/buffs.js` (`stealthOff`), `content/enemies.js` (stealth, STEALTH_RESTORE_BY_KEY, husk, kitInvisShield, kitShadowKiller, kitJazz, kitBoneSpike)
+
+- **Seen**: §21.4 left "隐匿 returns at once after a block (PRTS: 3 s)" [ASSUMED]; v0.1.1 hid an enemy again one tick after its block ended (a 潜伏者 whose blocker falls: untargetable 0.03 s later). Players reported (via the owner) that the 深池逐火 "stealth monster revives forever and can't be killed": a warrior knocked out while blocked releases its block through the 重生's 无法阻挡, its blocker takes the next warrior at once, and when the 重生 ends the ember is not blocked again — 隐匿, out of reach of ranged operators and operator splash — walks on and stands up with full HP 10 s later.
+- **Official** (checked on PRTS 2026-10-03): 作战机制 §隐匿 "对于绝大部分可隐匿的敌人而言,在被我方单位阻挡后会解除隐匿,不被阻挡的3秒后重新进入隐匿。这是敌方单位的隐匿所拥有的特殊机制,我方干员并不会因为阻挡而解除隐匿" and "少部分的隐匿表现上与我方干员相同…可能不具有这样的特殊机制"; §隐匿与Buff的关系 "在被阻挡时开关会被关掉从而失去隐匿,阻挡状态解除后3s开关重新被开启而恢复隐匿"; 异常效果 隐匿 "与'阻挡时解除'没有直接关系,该机制通常由其他效果实现". The enemy pages' 天赋 "隐匿(解除阻挡N秒后恢复)" (PRTS text search): 0 s on 21 enemies — here 业余竞演者, 节日爵士乐手, 假想敌:骨刺, 流泪小子 (both), 访问团强攻冠军, and the veil of 清明 / 堂皇 ("获得隐匿(解除阻挡0秒后恢复)"); 1 s on 家族灭迹人 / 家族暗影灭迹人; no page names another time. Every other stealthy enemy here has a plain 隐匿: 潜伏者, 隐形弩手 (+组长), 隐形术师, 山海众头目 / 秘使, 重弩突袭者, 架桥船工 / 扶桥老手, 深池伙友影刃精英, 潜水员 (in water), 锏's second form and the 深池逐火 embers (PRTS 深池逐火战士 / 精锐战士 / 护卫 "获得隐匿、缴械"). 山海众头目 / 秘使 天赋 "该隐匿每次生效后自身获得强击标记(不可叠加)", 技能 破隐一击 "仅持有强击标记且被阻挡时可触发…技能开始时消耗强击标记".
+- **Cause**: `targeting.js canTargetEnemy`, `snapshot.js flagsOf` and `Battle.foesInRadius` read `blockedBy` live, so the 隐匿 came back with the block's end.
+- **Now**: every block release — `Battle._unblock`, `releaseBlocked`, `ai.js enforceBlockCapacity` (a blocker's death, retreat or stun, a block-count drop, a push, 无法阻挡 / 浮空 / 恐惧, a teleport) — calls `Battle._stealthSwitch(e)`: each 隐匿 source buff the enemy holds gets a `stealthOff:` buff for its restore time, `constants.js STEALTH_RESTORE` (3 s) or the source's `data.stealthRestore` (`content/enemies.js STEALTH_RESTORE_BY_KEY`: the 0 s / 1 s enemies above; the veil 0 s). `targeting.js enemyStealthed(e)` — 隐匿 flag, not revealed (反隐), not blocked, and some source not switched off — is the one test for ally targeting (`canTargetEnemy`), operator area damage (`foesInRadius`), the b.snap stealth bit (drawn solid meanwhile), 节日爵士乐手 (attacks only without its 隐匿), 假想敌:骨刺 (3 targets only in 隐匿) and 山海众头目 (the mark comes at the spawn and whenever its 隐匿 turns on again, the next blocked attack spends it: a new block inside the 3 s gives no second ×2 hit — until 0.1.2 every block did). A new block inside the window lifts the 隐匿 again and its end restarts the window; a 反隐 that ends outside a window hides it at once, as before; a veiled 潜伏者 hides as soon as its block ends (the veil) and, if the veil runs out inside its own 3 s, is revealed until they end. Our operators' 隐匿 / 迷彩 are untouched (allies get no switch).
+- **The 深池逐火 embers** (all three, `husk()` with `stealthy`): the knock-out releases the warrior's block at once (`_unblock` right after the 重生's 无法阻挡, as `applyStatus` does for a status) once the ember's 隐匿 is on, so the ember is revealed until 3 s after the knock-out — the 1 s 重生 stays 无敌 and untargetable, then about 2 s in which ranged operators and operator splash can hit it even though its blocker took the next warrior. An ember knocked out while not blocked is 隐匿 as soon as its 重生 ends (the switch only follows a block).
+- **Measured** (before = the v0.1.1 sim, after = this change; the flat stage with its row-9 lane, and real rounds on 战场#01 built like the match — an official wave with the TIMES pick, full content): the integrator's seven lineups (艾丝黛尔 / 角峰 / 隐现 / 幽灵鲨 against 1–4 战士 or 护卫): identical — 艾丝黛尔 alone against four 战士 2 s apart stays 0 / 4 because only one warrior is ever knocked out, and no lineup there knocks out a 护卫. 28 runs of a blocker + 2–3 ranged / splash operators against 4–6 战士 / 精锐战士 0.5–3 s apart: 81 → 84 of 126 killed, stand-ups 12 → 7 (23 runs unchanged, 4 one more kill, 1 one fewer — its blocker fell in the changed fight). Real rounds (R3 / R5 精锐战士 pick, R9 / R11 护卫 pick, three lineups up to the tier-4 four of §21.4's test): unchanged (R3 7 / 7, R5 5 / 16, R9 0 / 18, R11 0 / 28 for the tier-4 lineup; 0–1 for the weak ones). Why so little: in real rounds most knock-outs happen while the warrior is NOT blocked — ranged operators finish it on the way after it passed a full blocker (R5, tier-4 lineup: 10 of its 18 knock-outs, and 10 of the 13 embers that stood up again) — so its ember is 隐匿 at once, which is official; an ember freed by its own knock-out gets about 2 s after the 重生 and still needs 5 separate hits (火灰 10). What beats embers, officially: a free block slot where they walk (a second blocker behind the first), 反隐 (银灰 鹰眼视觉, 伊内丝 影哨, the SPT-X modules, 信仰搅拌机's module), or many fast hits.
+- [ASSUMED]: at the knock-out the 重生's cleanse comes first, then the ember's 隐匿 with the block-end switch, which outlasts the 重生 (PRTS documents neither the order nor whether the switch survives a 重生); 深池伙友影刃精英 and 锏's second form (PRTS writes their 隐匿 as the plain 异常效果 with no restore note) follow the general 3 s, not the "表现上与我方干员相同" kind; one switch per 隐匿 source — with several sources the enemy hides as soon as any is back on; a push or a teleport (DISAPPEAR) ends a block like any other release; a warrior released by its blocker less than 3 s before its knock-out leaves an ember that is 隐匿 straight after its 重生 (the window is opened by the knock-out's own release only — 4 of 55 knock-outs in the measured rounds, no outcome changed when prototyped).
+- Tests: `test/sim/feedback2-surtr-stealth.test.js` (the 3 s window and its consumers, a new block inside it, the release paths, the 0 s / 1 s enemies and the veil, our operators, 山海众头目's mark, the three embers' window, an ember knocked out unblocked), `enemies_bosses`, `feedback1-transform`, `feedback1-followups`, `combat`, `playtest5-targeting`.
+
+### 22.9 荒芜拉普兰德 S3's drones attack (#32 item 7) — `kits/tier6.js whitw2` (`WHITW2_SPREAD / WHITW2_CHASE / WHITW2_REAPPEAR_SIDE / WHITW2_ORBIT`, `releaseDrones / pickTarget / flyDrone / circle`)
+
+- **Seen** (GitHub #32, item 7): 「易拉三技能浮游单元无法造成伤害,只能造成三技能自带dot伤害」 — 荒芜拉普兰德's S3 终幕·浩劫 dealt only its once-per-second area damage.
+- **Official**: PRTS 荒芜拉普兰德 S3 备注, 技能流程: ① for 1.3 s after the cast or after a drone is added ("开启技能/补充浮游单元1.3s内") the drones spread evenly outward from her, one along her facing (初速度 0.1, 加速度 1.9, 最大速度 2.0); ② each then locks the target "距离自身最近>距离本体最近" anywhere on the field and flies at it (初速度 2.0, 加速度 1.0, 最大速度 4.0, 转向速度 1/6 per frame; a target that leaves or turns unselectable on the way → a new pick, the speed back to 2.0); ③ at the target it "锁定目标持续进行攻击,此状态下的攻击行为同正常浮游单元"; when that target leaves or turns unselectable it reappears at a random point of the 1.5-side square around it and picks again; with nothing selectable it circles (radius 0.9, 1.0 线速度, counter-clockwise, the circle on its left). Also: "该技能释放的浮游单元造成的伤害不属于普通攻击/技能直接伤害"; the area damage / slow has radius 0.9, does not stack and carries 头狼's 沉默. PRTS 分支特性信息 驭械术师: a drone starts at 20 % of the operator's ATK, +15 per hit on the target it hit last, up to 110 %, back to the start on a different target; drones released by a skill "不受缴械类效果制约" — the same note says they "造成技能直接伤害", which S3's own 备注 overrides for this skill. skill_table skchr_whitw2_3 at the chess levels (Lv4 / Lv7): atk +0.45 / +0.6, attack@cnt 2, attack@times 1.3 (PRTS ①'s 1.3 s), attack@move_speed −0.3 / −0.4, attack@magic_atk_scale 1, attack@fear 2, attack@range_radius 0.9, attack@projectile_turn_speed 5 (× 1/30 s = PRTS's 1/6 per frame); trait init 0.2 / 0.35 (elite: module 狼时), delta 0.15, max 1.1; 头狼 every 20 s: cap × 1.1 (PRTS 备注: 121 %), 2 s 沉默, 数量+1.
+- **Cause**: the S3 spec switched her attack off for the whole skill (`attack: { noAttack: true }`) and its tick only moved the drones (at attack@projectile_move_speed, 1 tile/s), feared a target the drone came within 0.9 of and dealt the area hit; no drone ever attacked. The kit's header said so ("she stops attacking while they roam"). The drones also preferred enemies no other drone held — an [ASSUMED] rule PRTS does not have.
+- **Now**: her own attack stays off — every drone is out (浮游单元 +attack@cnt with her own one; +1 from 头狼 stage 3, and a drone added when stage 3 comes during the skill spreads along her facing). The drones fly ① ② ③ with PRTS's numbers (spread for attack@times s; the distance covered at the mean of the old and new speed, exact under constant acceleration; the reappearance point is drawn in her facing frame, so a battle turned with her direction plays the same). A drone that reaches its target fears it (attack@fear s) and stays on it; it attacks every attack interval of hers (her live ASPD) for ATK × its own funnel ramp (trait init, +delta per hit on the same target, the cap — raised by 头狼 stage 1 —, back to init on a new target), arts. That damage is neither a normal attack nor skill damage: no `attack` hook, `isAttack` / `isSkill` false, tag `droneAttack` — the 叙拉古 6 assassin chance ("对敌人攻击时") and the on-attack items skip it, 头狼's 沉默 ("造成伤害时") applies; 缴械 does not stop it. The once-per-second area hit and the slow are unchanged (around every drone, one hit per enemy; tags `skill` + `drone`). A wolf knocked out or withdrawn in the middle of a tick (a kill hook, say) deals nothing more in that tick. fx: `droneLock` (the wolf-eye mark) when a drone picks its target, `drone` at a drone for each of its attacks and once per second for drones still roaming; the client draws them already.
+- **Distance to a huge enemy** [ASSUMED] — the owner's decision of 2026-10-04: a drone measures every enemy's distance to its position (a huge enemy's centre, its 判定中心), so leader rounds stay close to 0.1.1. Considered and set aside: the sim's general convention for operator-side distance picks, the hit rectangle (body.js `bodyDist`: `targeting.js:135` `sortEnemyTargets` 'nearest' / 'farthest', `kits/tier3.js:86` `enemiesAround`, `kits/tier6.js:1108` 异客's storm chain, `kits/tier6.js:2525` / `:2549` 溯光星源's bounces and links, `kits/tier4.js:526` / `:995`; only the profession chain bounce, `ai.js:257`, takes the nearest by position) — with it a huge leader (胄, 管) was the nearest enemy of every drone around it and drew them all for the whole skill (胄 h07_01: her damage on the leader 106 309, on the other enemies 3 036, 2 deaths). A drone on a huge enemy sits at its centre; it reaches it on touching the hit rectangle.
+- **Players notice**: once a drone reaches a target that stays alive, its hits outweigh the area damage (3 parked 重装防御者, RES 0, the full 40 s: drone hits 38 411 of 54 640); against streams of weak enemies the area hit still does most of it (the flat stage's two lanes, 10 + 10 walkers, 40 s: drones 11 049, area 50 188 of 61 236). All drones may lock the same enemy — each takes the one nearest to itself — so against a cluster the area hit covers fewer enemies than before. Measured, old → new: parked, first 12 s normal 12 901 → 12 089 (drone hits 7 512 + area 4 578), elite 17 658 → 18 085; the whole 40 s 47 857 → 54 640 and 65 504 → 77 369; the lanes 15 481 → 61 236 (kills 1 → 14), elite 49 213 → 72 224 (9 → 18). **Leader rounds** (one elite 荒芜拉普兰德 per side, S3 at once, kept alive, 60 s; her damage on the leader / on the other enemies / enemy deaths, 0.1.1 → now): 假想敌:胄 (act1 h07_01) 32 467 / 80 186 / 9 → 84 880 / 44 391 / 6; 假想敌:管 (h07_03) 19 936 / 62 176 / 5 → 37 520 / 69 927 / 5; 假想敌:铳 (h07_02) 31 260 / 49 982 / 4 → 62 794 / 30 221 / 0; 卢西恩 (act2 h07_05) 37 957 / 58 512 / 6 → 75 094 / 40 881 / 2 (both of normal size: a drone that picks the leader because it is nearest keeps the lock, and a leader never falls); the heavy two-player 胄 scene of robustness.test.js (the review bench: 4 wolves per side, 120 extra enemies at ×20 HP, 60 s): the wolves' damage 1 315 038 → 1 291 567, on the leader 50 170 → 42 907, enemies killed 12 → 13. With the hit-rectangle distance it would have been 胄 106 309 / 3 036 / 2, 管 57 202 / 36 427 / 2 and the heavy scene 406 075 / 125 271 / 2.
+- [ASSUMED]: the centre distance above (the owner's decision); reading ① "补充浮游单元" as: after an addition only the added drone spreads, along her facing, while the others carry on; the turn rate (转向速度) is not modelled — a chasing drone heads straight at its target; a drone's attack clock runs all the time and its first hit lands on arrival when the clock is ready; the drones keep flying and attacking while she is stunned, frozen or silenced (PRTS only names 缴械); a drone reaches a huge enemy when it touches the hit rectangle and then sits at its position; the fear's source is her (they flee from her, as before); the area hit keeps `isSkill` (a skill DoT; PRTS's line speaks of 直接伤害).
+- Tests: `test/sim/feedback2-whitw2-yu.test.js` (spread and chase numbers; per-drone hits, ramps and intervals, no normal attack, the damage flags, 缴械; nearest-target picks, the reappearance square and the ramp restart, the circle; 头狼 stage 3 mid-skill; a wolf knocked out mid-tick; facing UP / LEFT / DOWN = RIGHT with a reappearance), `test/content/kits_t6.test.js` (the S3 test now has one enemy: a nearer one would draw every drone).
+
+### 22.10 余 S2: leaders teleported, no pull effect without a pull, cast with an enemy on its x-1 (#32 item 1) — `kits/tier6.js teleportEnemy / yu (skchr_yu_2)`, `tools/build-data.mjs TRIGGER_DEVIATIONS / resolveTrigger / validateAll`, data/chess.json `skills[].trigger`
+
+- **Seen** (GitHub #32, item 1): 「余二技能有伤害和特效,但不能拉怪」.
+- **Official**: PRTS 余 S2 厚礼上宾 (技能范围 x-1): "立即对周围所有敌人造成相当于攻击力100%的法术伤害并将其中的地面可达目标传送至自身位置"; 备注: "可达目标" = a target that can reach his tile by ground pathing, not through impassable tiles — "如果余或目标所在位置已经是一个不可通行地块(例如围栏、高台等),传送效果会因此失效"; "处于消失状态的/持有自缚的单位不视为可达目标"; 免疫传送 / 传送免疫 units are not teleported; the teleport is judged 0.13 s after the damage, the target is unblocked first and lands at a random point near one of the four corners of his tile. PRTS 卢西恩,“猩红血钻” and 假想敌:铳 (both sections): 传送抗性 无. Trigger: the 下半 TANK class row `TANK | | | 0 | TAKE_DAMAGE` and PRTS 卫戍协议/帮助's 重装 strategy "不受技能范围影响,受到伤害时释放技能" (§20.2, §21.29).
+- **Mostly not a bug** (triage on the 0.1.1 sim): ordinary ground enemies inside x-1 are teleported — 余 in a lane of the flat stage pulled all 3 enemies inside x-1, on 战场#01(下半) all 3; on a 围墙 tile none (the official rule). The usual first hit came from a ranged enemy outside x-1 (a 深池暗影术师 2.7 tiles away): under TAKE_DAMAGE the skill fired with nobody to pull, so only its damage and effect showed.
+- **Cause** (two real faults): `teleportEnemy` skipped every leader (`isBoss`) — no PRTS basis; and S2 played its `pull` fx even when nobody was teleported (n = 0).
+- **Now**: a leader is teleported like any ground enemy unless it is 自缚 — the 7 huge leaders (`SELF_BOUND`), 守墓石像's 转换模式 and the 胄 parts' anchor keep `selfBound` (§21.19), so 卢西恩 and 假想敌:铳 are the leaders it can pull. A teleported leader re-plans from his tile: on the real rounds 假想敌:铳 (不可阻挡) walks on to its next patrol checkpoint and 卢西恩 is blocked by 余 (block +2), blinks past and resumes its loop. 静态刚体 is no exemption (the 备注 names 消失 / 自缚 / 免疫传送; PRTS 静态刚体 forbids physical movement) and every 静态刚体 of the mode flies or is 自缚 anyway (§21.9). The `pull` fx plays only when at least one enemy was teleported (each still gets its own `teleport` fx).
+- **Deliberate deviation — S2 casts with an enemy on its x-1** (the owner's decision of 2026-10-04; it joins §21.29's six): players saw it fire from a ranged hit with nobody to pull, so instead of the official row's TAKE_DAMAGE it casts once its SP is ready and an enemy stands on its own 技能范围. Not the basic strategy (`DEFAULT`, §21.29's rule): his attack range is his own tile (0-1), so "about to attack with an enemy in the initial range, or one he blocks" fires only once an enemy is already on his tile — measured, an enemy parked two tiles away never set it off, under DEFAULT as under TAKE_DAMAGE. It takes `SKILL_RANGE` — the mode's official strategy for a MANUAL skill with a 技能范围 when no class row applies ("仅在技能范围内存在敌人(无视其不可选中)时释放技能", §20.2) — on x-1: `TRIGGER_DEVIATIONS` `chess_char_6_03_a: { skchr_yu_2: 'SKILL_RANGE' }` (per chess, the elite through its baseId); a SKILL_RANGE deviation carries the skill's own range as `customRangeGrid`, and `validateAll` checks both records. The two records read `{ rule: 'SKILL_RANGE', rawRule: 'TAKE_DAMAGE', customRangeGrid: }` (rebuilt with `--offline`: nothing else in data/ changed). His S1 keeps TAKE_DAMAGE, his S3 its official charId row (CUSTOM_RANGE).
+- **Players notice**: S2 never fires from a hit outside x-1 any more; it fires as soon as an enemy steps onto x-1 — any enemy, a flyer or a 隐匿 one too (a flyer alone: the burst hits it, nobody is pulled) — so in a stream it often pulls only the leading enemy where the hit used to come with several bunched up. Measured on the triage lanes (SP full from the start; cast / enemies pulled): flat stage beside the lane 5.90 s by the 深池暗影术师's hit, 0 → 6.33 s, 1; in the lane 8.13 s, 3 → 4.83 s, 1; 战场#01(下半) 11.87 s, 3 → 8.57 s, 1. One-line flip: remove the entry from `TRIGGER_DEVIATIONS` and rebuild.
+- **Checked**: no enemy of the mode is immune to the teleport — every enemy name of data/enemies.json was looked up on PRTS: all list 传送抗性 无 (the four 悬赏 bosses on their "(敌方)" pages, “余音” on its own) except “斩胄之剑”, “破胄之锤” and 刺胄之弹, whose value is empty — they fly (the 剑 / 锤 also stay 自缚-anchored when shot down), so they are never teleported anyway; 碎铳之簧's page has no such row and “炎佑” is an ally-side unit.
+- **Not modelled**: the 0.13 s between the damage and the teleport (same tick) and the corner landing points (the tile centre).
+- Tests: `test/sim/feedback2-whitw2-yu.test.js` (S2 fires with a ground enemy two tiles away and nobody hitting him, the enemy on his tile; a ranged hit from outside x-1 no longer casts it; 卢西恩 and 铳 teleported, “萨米的意志” (自缚) stays, one `pull` fx for two; a flyer alone on x-1 → no `teleport` / `pull` fx; the real 铳 and 卢西恩 rounds), `test/sim/feedback1-tank-triggers.test.js` (the data and the real battle for 余 S2 beside the six), `test/data.test.js` (14 deviated records), `kits_alt_t6` (6_03 S2 now asserts the reason SKILL_RANGE); `feedback1-residuals` (守墓石像) and `playtest6-skills` (#15 audit, 余 S2 now among its SKILL_RANGE skills) pass unchanged.
+
+### 22.11 归溟幽灵鲨's 替身 is drawn and sits the fight out (#44, 「归鲨死了没替身」) — `professions.js installDollkeeper` (`DOLL_SWITCH`, hook `dollSwitch`), `kits/tier5.js` (归溟幽灵鲨: trait `dollNoAttack`, S2 `onEnd`, 拥抱自我), `content/items/battle.js` (`PRIO_UNDYING_HELD`), `render/units.js FORMS` (`doll`, `leave`), `UnitView` (`_dieForm`), `render/spine.js` (`baseRoles`), `render/style.js` / `textures.js` (icon `doll`), `render/fx.js` (`dollEnd`)
+
+- **Seen** (GitHub #44): 「归鲨死掉后没有替身」. The owner's triage: in 0.1.1 the sim did switch her to the 替身, but the client kept drawing her 本体; the 替身 also attacked and could cast S2 生存的渴望, whose end then knocked her out.
+- **Official**: the trait (character_table / chess `trait`) 「受到致命伤时不撤退,切换成<替身>作战(替身阻挡数为0),持续20秒后自身再次替换<替身>」 (bb duration 20; `atk` / `max_hp` are the 替身's bonuses — 0 on both 傀儡师 but for the elite modules). PRTS 分支特性信息/data §傀儡师: "受到足以致命的伤害且未持有不死的情况下" → "一段切换动画", then the <替身> fights for 20 s holding 阻回; at its end a switch animation back; "切换动画开始时会清除自身一切Buff;切换途中重设自身生命至最大值,随后再次清除自身一切Buff"; during a switch animation 不死, 无敌, 阻回, 禁疗, 孤立, 强制缴械, 眩晕 / 冻结 / 睡眠 immunity; block ×0 "从切换至<替身>开始时持续至切换回非<替身>开始"; "部分机制也可以直接让干员切换为<替身>形态". PRTS 归溟幽灵鲨: 特性备注 「<替身>不进行普通攻击」 (and 天赋备注: 伤害与减速不可对空); S2's text corrected to 「技能结束后立刻切换为<替身>」 (原文 视为被击倒); S2 备注 「技能期间持有不死,因此技能期间不会因致命伤而切换为<替身>」. PRTS 风丸: 特性备注 「<替身>状态下可对空」 — her 替身 attacks; her 纸偶 leaves "持有者切换替身时". The 替身's HP: PRTS resets it "至最大值", the trait's 替身 HP bonus is 0, character_table has no 替身 of 归溟幽灵鲨 and 风丸's 纸偶 token (token_10022_kazema_shadow) has her own max HP at every level — so the operator's own max HP. Her skeleton (`char_1023_ghost2.skel`, read with the client's own parser): the `*_B` clips draw the 替身's own slots (`*_T`) and hide the 本体's — Start_B (1 s, fades in), Idle_B, Die_B (1 s, breaks apart and has faded out at its end), Die_B_2 (1 s, collapses and stays); Start_2 (1 s) brings the 本体 back; her Back skeleton has only Idle_B and Start_2. 风丸's: Start_B (its OnAttack at 0.267 s is 折纸生花), Idle_B, Attack_B, Die_B; her Back skeleton Start_B, Idle_B and Attack_B. Neither Back skeleton has the 替身's death clip.
+- **Cause**: the 替身 was only a buff (block −99, HP × 0.5): nothing kept it from attacking or casting; S2's end emitted 'knockout' and `loseHp(hp + 1)` — a lethal HP loss, so the 替身, or the knock-out when she already was one (a cast as the 替身 killed her at its end). On the client an operator had no form: the 'substitute' / 'swap' fx carried no `form`, UnitInfo none, FORMS had no entry for her skeleton, and 'trait:substitute' had no icon. Already in 0.1.1: a running 坚固维式重锤 不死 window did not stop the switch (its battle-level hook and the 傀儡师's sat at the same `fatal` priority, the 傀儡师's registered first).
+- **Now** (every 傀儡师): a lethal hit on the 本体 that nothing prevented before it — a skill's or talent's own 不死 (10 … −60) or a running 坚固 window (`PRIO_UNDYING_HELD` −99; the hammer's lock, a new window, stays at −100 after the switch, as in 0.1.1) — switches her: the running skill ends (reason `substitute`: S1 / S3, 风丸's S2 and its 纸偶) and her statuses are removed; for `DOLL_SWITCH` (1 s) she holds `trait:dollSwitching` (flag `u.trait.dollSwitching`) — 无敌, 阻回, 禁疗, 孤立, 缴械, 眩晕 / 冻结 / 睡眠 refused, a lethal 流失 stops at 1 HP; `trait:substitute` lasts the switch + 20 s: block 0 from the switch on, 阻回, max HP = her 替身 token's (风丸) or her own (归溟幽灵鲨, was 50 %), HP full; `u.form = 'doll'` and fx 'substitute' `{ form: 'doll', dur }`. When it ends, the switch back: the same 1 s animation and clearing, block and HP back, fx 'swap' `{ form: null }`. A lethal hit on the 替身 (after its switch) knocks her out; the form is then reset by fx 'dollEnd' `{ form: null }` after the 'die' event (drawn as nothing), so she redeploys as the 本体. Content switches her at once with the hook `dollSwitch` `{ unit, reason, done }`. 归溟幽灵鲨's kit sets `dollNoAttack`: her 替身 carries 缴械 and 沉默 — no normal attack and no cast (S2 / S3's basic strategy casts on an attack the 替身 never makes). Her S2 end emits `dollSwitch` (no lethal HP loss — so no 不死 / 复活 item takes it — and no 'knockout' fx, gone from the client's table); nothing when it ended with her, by her switch, or she already is the 替身. 拥抱自我 works while the 替身 fights (not during the switch). Client: FORMS `char_1023_ghost2.doll` — Start_B (`change`), Idle_B, Die_B as its closing clip over its last second (timed from the fx `dur`), Die_B_2 to die on, no attack or skill clip, and the new `leave` clip Start_2, played when a form ends (UnitView.setForm; not on a knocked-out view); `char_4016_kazema.doll` — Start_B, Idle_B / Attack_B, Die_B, `leave` Start. A form now ends in the unit's own roles (`SpineActor.baseRoles`: the equipped skill's clip — an operator came back on the manifest's default skill clip). 'trait:substitute' shows the puppet icon `doll`. The fx carry `form`, so no client stage drops them (`keepsState` / `keepEarly` / `isCosmeticEvent`) and a view built later starts from UnitInfo `form`. Facing UP, the Back model shows the 替身 and skips the clips it lacks; knocked out, she lies on the Front model like every operator facing UP (§22.1) — the view keeps the form it died in (`_dieForm`, set by `die()`, cleared when it stands up), so that model, built a frame after the 'dollEnd' reset, and any model rebuilt while she lies down show the 替身's Die_B_2 (风丸: Die_B); she stands up as the 本体 (facing UP: on the Back model, its deploy clip); a revive in the same frame as the knock-out (阿戈尔: die → deploy → 'dollEnd') brings the 本体 back on Start_2 and loads no model.
+- **Players notice**: she turns into her 替身 (a puppet of her, with an icon) for 21 s; it no longer attacks and her SP waits until she is back; S2's end no longer kills her — she becomes the 替身; the 替身 has her full HP; after each switch she cannot be hurt and does not act for 1 s; S1 / S3 running at a lethal hit end; knocked out as the 替身 she lies as the collapsed 替身, facing UP too. With a 坚固维式重锤 whose 8 s window still runs (its lock set off by the 替身's lethal hit), a lethal hit on the 本体 leaves her at 1 HP instead of switching her again. 风丸 likewise (her 替身 drawn, the 1 s switches, 阻回, S2 and its 纸偶 end with the switch). Measured (the report's repro: a harmless enemy parked in her range, lethal hits by hand): 0.1.1 — the 替身 at 1 328 / 2 657 HP made 17 of her 19 attacks and her SP kept filling; with 38 / 40 SP she cast S2 as the 替身 (at 2.4 s, 1.9 s after the hit) and was knocked out at its end (17.4 s); now — 2 657 / 2 657, no attack and the SP held 22 s; S2 cast as the 本体 at 24.9 s, alive.
+- [ASSUMED]: the switch animation lasts 1 s each way (the skeleton's Start_B / Start_2) and the 20 s run after it; the direct switch at S2's end (立刻切换) plays the same 1 s animation; "清除一切Buff" = the running skill and the catalogue statuses — every other buff survives, the remake's bond / item / talent effects (buffs too) and other units' timed buffs and shields alike, and element gauges and 爆发冷却 stay; 无敌 is modelled as damage immunity only, like every ally 无敌 in the code (PRTS also gives "无法被不同阵营选中": enemies may still target her during a switch); no S1 (技能范围) cast as her 替身 either; the 替身 can be healed (PRTS names 禁疗 for the switch only); 风丸's 替身 may still cast a skill that was ready at the switch (it attacks); Die_B over the 替身's last second is visual only; a view built from UnitInfo while she lies down (a field opened later: the sim has reset the form) shows the 本体's fall.
+- Open: 风丸's 替身 attack range (PRTS x-4) and 对空 are not modelled — it keeps her own range and ground-only attack.
+- Normative lines rewritten with it: §5.2 (`form`), §5.4 (`fatal`: `PRIO_UNDYING_HELD`), §8.2 (fx `form`, UnitInfo `form`).
+- Tests: `test/sim/feedback2-doll.test.js` (cases A–D of the repro: the 替身's form, HP, block, 阻回, no attack, 拥抱自我, the switch back; S2's 不死 and its end; a knock-out as the 替身, the event order, the redeploy; no cast as the 替身 for S2 at 38 / 40 SP and a ready S1; S3 ending with the switch; the hook; a running 坚固 window stopping the switch; 风丸's 替身 attacks), `test/render/feedback2-doll.test.js` (the clips in the manifest, Start_B → Idle_B → Die_B → Start_2 with her S3 clip after it, Die_B_2 held through 'dollEnd' and the redeploy, UnitInfo `form`, the Back model, a late fx; knocked out facing UP — the Front model's Die_B_2 with the reset in the same frame or the next, 风丸's Die_B —, a model rebuilt while down, the redeploy on the Back model, a same-frame revive on Start_2 without a model load, a view built while down; 风丸, sim → view, the skeleton's clip meanings), `test/sim/professions.test.js` (the switch windows), `test/sim/fidelity.test.js` (her own max HP).
+
+### 22.12 Enemy splash spares a 隐匿 operator that does not block the enemy (#32 item 6) — `sim/targeting.js areaSelectable / auraSelectable`, `content/enemies.js areaAllies / areaAlliesInTiles / fieldAllies / auraAllies / targetAndArea / zone / dmgZone`, `content/bosses.js`, `sim/Battle.js alliesInRadius`
+
+- **Seen**: 「隐蔽单位仍会受到溅射伤害」. **Real** on the enemy side (the operator side was fixed in 0.1.1, §21.19): every enemy area effect took every ally in its area. Measured on v0.1.1: 碎骨 grenades 角峰 on (10,6); 古米 on (10,7) under a 999 s 隐匿, not blocking, took 4 splashes (2650 damage) and was knocked out. §21.22's audit had listed it ("enemy splash still hits 隐匿 allies").
+- **Official**:
+ - PRTS 作战机制 §隐匿 "隐匿效果使得获得该效果的单位无法被任何敌方的能力索敌选中", "隐匿的我方干员阻挡敌人时,因为“阻挡优先级最高”的效果,敌人会无视一切可选性对该干员进行攻击"; §AOE伤害判定 "AOE的判定是对攻击范围内的每个可以被选中的敌人进行判定"; §隐匿与Buff的关系 "隐匿状态下的单位一般无法被敌方的索敌机制和Buff选择器选中为目标", "目前明日方舟中使用能选中隐匿状态单位的Buff效果一定是无视隐匿状态起作用的" — its one enemy example being 寒霜's 攻速下降 Debuff.
+ - PRTS 异常效果 §无法选择: with 隐匿, 不可选中, 无敌, 塔不可选中 or 对地规避, "常见的、来自不同阵营的“选择”行为将无视这些单位进行(如同范围内不存在这个单位)"; the abilities PRTS marks "无视可选性" skip that check; "'直接选中'的能力不会进行具体的目标选择,故同样不受这些仅在选择时生效的异常效果制约".
+ - gamedata_const ba.invisible 隐匿 "不阻挡时不成为敌方攻击的目标" vs ba.camou 迷彩 "不阻挡时不成为敌方普通攻击的目标(无法躲避溅射类攻击)"; PRTS 异常效果 迷彩 "所有光环类能力、以及涉及中点判定/格子判定的效果均不受迷彩制约,但存在主动排除受迷彩影响单位的情况(此时站内会特别标注)"; PRTS 选择器 "非弹道类型的溅射攻击会自动无视迷彩", "所有触发选择器通常不无视迷彩".
+ - The exceptions are the notes on each PRTS enemy page ("无视无法选择", "无视(目标)可选性", "无视迷彩"); every area site below was checked against its page.
+- **Cause**: `content/enemies.js` and `content/bosses.js` picked their area victims with `battle.alliesInRadius` / `alliesInTiles` / `allies()`; §21.22 had added only a 对地规避 filter, site by site.
+- **Now**: one area selector, `targeting.js areaSelectable(src, a)` (helpers `areaAllies`, `areaAlliesInTiles`, `fieldAllies`): no 隐匿 ally unless it blocks `src`, no untargetable or sleeping (沉睡 = 无敌 + 无法行动) ally, no airborne 起飞 ally for a ground `src` (the damage pipeline's refusal, `evadesGround`; the per-site filters are gone). 迷彩 is not checked. A dead `src` (death blasts) blocks nobody; `src` null (no selecting enemy) keeps 隐匿 out but not 起飞. Buff auras use `auraSelectable` / `auraAllies`: the same without 对地规避. A target the ability locked beforehand — an attack's target, 死亡之眼's channel, a C4, an 爆炸箭 — is a direct pick (`targetAndArea`): a 隐匿 it gained meanwhile does not save it; only the units around it are an area selection. Per site:
+ - **Selects** (a 隐匿 operator that does not block the enemy is spared):
+ - splash — 碎骨's grenades (their DEF down too; its target keeps it), 自制投石机's stones, the 周围四格 of 控潮术师 / 领潮员 / 术师快艇 and 腐败骑士, 暴鸰's 8-tile bomb, 灼藤's first 3×3, the shells of 帝国炮火先兆者 / 中枢先兆者 (their damage stays 无来源);
+ - death and self blasts — 高能源石虫 / 冰爆源石虫 / 卷心籽 (PRTS 死亡爆炸 "…无视迷彩,不可对空", "来源无效" included), 烹泉 / 沏虹 (blast and steam), “巨大的丑东西”'s self-destruct, “庞贝”'s blast while blocked;
+ - area skills and statuses — W's C4, 鼠王's 唱沙 and 沙狱, 凋零骑士's 爆炸箭, 腐败骑士's 蓄力锤, 萨卡兹王庭军精锐术师's 死亡之眼 burst, “自在”'s 纬地经天 and 破桎而出, 锏's 速杀 (those on its way; its former blocker is still hit), 肆虐风雪 and 瞬息杀机, “萨科塔昂首”'s 祈祷邀约, “帝国的甲胄”'s barrage, the 自行炮's shots (each picks inside its 9 tiles — a 迷彩 operator can be shot now);
+ - pulses — the 神经毒素 of 元核孽生者 / 异光体孽生者, 鼎沸, 深溟巢涌者 (its pulse rides on its engine attack, which needs a target: a 迷彩 operator alone in its range is never hit), 水遁忍者's spin; zones — 集团军重型火炮's 燃烧区域 and 假想敌:蚀裂's sourceless 毒雾 (`src` null: a 隐匿 operator is spared, an airborne 蒂比 still reached — §21.22; until 0.1.2 it took everyone inside); jumps — 陷落雪祀's chain, the 碎铳之簧 element bounce;
+ - leaders and parts — the 刺胄之弹 / 斩胄之剑 / 破胄之锤 blasts (the flyer selects, so 对地规避 still does not apply), 铳's 最终之罚 and the springs' 末日布道 tramples, “余音”'s pulse and 合奏, 管's 裂管之奏, 弦's 断弦之奏, 昆图斯's 大潮 and tentacles, 卢西恩 / 不祥幻影's 【aoe】, 阿利斯泰尔's 王权号令 and 斥退, “萨米的意志”'s 冰凌 column and doom.
+ - **Normal attacks on every operator in range** take the targets of a normal attack (`canTargetAlly`: no 隐匿 or 迷彩 operator unless it blocks the enemy — PRTS 选择器: a normal attack does not ignore 迷彩): 斩胄之剑 / 破胄之锤's hover attack ("普通攻击对攻击范围内的所有我方单位…") also took 隐匿 and 迷彩 operators until 0.1.2 (`targetsNear … ranged: false`); “灵幛” already did not.
+ - **Cast conditions** of area skills count the targets of their trigger selection (`targetsNear`): 卢西恩 / 不祥幻影's 【aoe】 ("需要目标"), 锏's CircleAttack — a lone 隐匿 or 迷彩 operator no longer sets them off, as a lone airborne 蒂比 has not since §21.22.
+ - **Buff auras** (`auraAllies`): 深池伙友卫队's field and 扎罗's 远古威慑 no longer slow a 隐匿 operator that does not block them (their PRTS pages carry no 无视 note); an airborne 蒂比 is still slowed [ASSUMED, §21.20 / §21.22's ground-enemy auras].
+ - **Still reach every ally there**: 【污染秽蚀】, 【盲信之誓】, 萨卡兹悖谬暴虐兵长's 暴击, 假想敌:淤困's burst spread (PRTS "无视目标可选性" — now `ignoreSelect`, so it also reaches an airborne 蒂比, which the pipeline used to refuse), 远眺's death 暴露 and 圆仔's facing count ("无视其可选性"); 寒霜's aura (PRTS: "无视隐匿"); map, tile and terrain effects — “墓碑”'s halving (PRTS: "实际属于地图效果"), 【国度】, a chimera's 源石污染区 aura, 深水区 / 活性源石 / 源石污染区 tiles; the ticks of a debuff already on a unit.
+ - **起飞**: 锏's 【瞬息杀机】 no longer reaches an airborne 蒂比 — it used to set her SP to 0 directly, past the pipeline; its area selection now skips her (对地规避: 锏 walks).
+ - The operators' 隐匿 sources all set the flag the selectors read (`stealth`): 伪装服 (`applyStatus('stealth')` on the first damage), 叙拉古 6, 伊内丝 S2 and the 排气格栅 tile (PRTS 特殊地形: "即隐匿"); 迷彩 (`camou`): 忍冬 S3, 寒芒克洛丝 S1.
+- [ASSUMED]:
+ - A 隐匿 operator that blocks the enemy stays selectable for that enemy's area abilities and auras (PRTS states the forced selection for its attacks).
+ - 迷彩 is hit where PRTS gives no basis — no splash type, no 中点判定 / 格子判定 or aura reading, no "无视迷彩" note — as since 0.1.1: 锏's 肆虐风雪, 瞬息杀机 and the bystanders of 速杀, 昆图斯's 大潮 (whole field) and tentacles, “萨米的意志”'s doom and 冰凌 column (a 格子判定 reading), “余音”'s pulse and 合奏, 铳's and the springs' tramples, “巨大的丑东西”'s self-destruct, W's C4 blast, “帝国的甲胄”'s barrage and the 自行炮's zone (格子判定 readings), 陷落雪祀's chain, the 碎铳之簧 bounce.
+ - 【国度】 and the chimera's aura reach a 隐匿 operator (tile / terrain readings).
+ - An airborne 蒂比 is still reached by ground-enemy buff auras and by 蚀裂's 毒雾 (§21.22).
+ - An invulnerable (无敌) operator is still selectable by areas, as by attacks (§21.22's open deviation; its damage is 0).
+- **Found, not changed** (enemy-number gaps against PRTS, queued for a later round):
+ - 碎骨's grenade: PRTS's page gives 3×3, 26 % ATK, DEF −50 % for 5 s; the code has radius 1, 100 % ATK, 3 s.
+ - 扎罗: 远古威慑 radius 1.5 / ASPD −50 (code 2.5 / −30), the second form's range 1.25 (code 2.5), 溶血骇惧's loss curve (up to 30 % max HP/s at 40 s; code 5 %).
+ - “复仇者”'s 冲锋 trigger counts 隐匿 / 迷彩 operators (`targetsNear … ranged: false`).
+ - “庞贝”'s blast radius: PRTS 1.4, code 1.
+ - “巨大的丑东西”: its unblocked ranged 3×3 splash attack is missing; self-destruct radius 3.0 (code 2.5).
+ - “墓碑”, 烹泉 / 沏虹 and 集团军重型火炮: the splash of their normal attacks (3×3, radius 1.0, radius 1.0) is missing.
+ - 碎铳之簧: bounce radius 1.7 and ×0.8 per bounce (code 2 / 0.85), chase trample radius 0.35 (code 0.5).
+ - 锏's 速杀: PRTS hits only its former blocker, 0.3 s after the blink.
+ - W's C4: PRTS installs it on the unit in a 3.2 s cast, 180 % on it (code: 1 s fuse, radius 1).
+ - 管's 裂管之奏: the extra 0.8-radius 凋亡 hit "(无视其可选性)" is not modelled.
+ - “萨科塔昂首”'s 祈祷邀约 "不可对空" does not filter flying allies.
+- Tests: `test/sim/feedback2-stealth-splash.test.js` (9 — the selectors; 碎骨 next to a 隐匿, a 迷彩 and a 伪装服 operator; “庞贝”'s blast on its 隐匿 blocker; 卢西恩's 【aoe】; the 无视无法选择 exceptions; 蚀裂's 毒雾 and the 深池伙友卫队 / 扎罗 auras vs 隐匿 and 起飞; 死亡之眼's locked target; the blade / hammer hover attack, the 自行炮 and 深溟巢涌者 vs 迷彩, 祈祷邀约 vs 隐匿 — every battle case fails on 0.1.1), `test/content/enemies_bosses.test.js`, `test/sim/feedback1f-liftoff.test.js`, `test/docs-consistency.test.js` (卢西恩's / 锏's cast conditions).
+
+### 22.13 要塞 cannot hit air units; 莫斯提马's slow shows its icon (GitHub #35, #16; PR #48) — `tools/build-data.mjs classifyAttack` (fortress no longer in the can-hit-flying ranged set), data/chess.json `canHitFly` false for chess_char_2_18_a/_b (灰毫) and chess_char_5_08_a/_b (号角), `sim/professions.js` (`fortress`, `resolveProfile`), `kits/tier4.js` (莫斯提马's slow pulse `status: 'slow', visible: true`)
+
+- **Seen**: GitHub #35 — the 要塞 operators 号角 and 灰毫 shot at flying enemies and splashed them; #16 — "莫斯提马三技能没有减速".
+- **Official**: PRTS 新人入门 marks the 要塞 branch 不可对空; the 要塞 trait text never mentions air, and no 号角 or 灰毫 skill adds anti-air. 莫斯提马's slow was **not** broken: her talent's move_speed −0.15, ×3 during S3 (`talent_scale`), is 85 % / 55 % of the movement speed per PRTS, and it already applied in 0.1.1 — only no status icon was drawn on the slowed enemy, which is what the reporter saw.
+- **Cause**: `classifyAttack` gave `canHitFly` to every ranged attacker unless the trait says 地面敌人 (投掷手); a 要塞 attacks from the melee position with a ranged normal attack (`MELEE_RANGED_SUBPROFS`), so it counted as ranged and the `fortress` profile did not set `groundOnly`. 莫斯提马's `pulse` carried no status.
+- **Now**: `canHitFly` is false for the sub-profession `fortress` — the only data change is those 4 records of data/chess.json (normal + elite); the `fortress` profile reads `canHitFly: false, groundOnly: true` and `resolveProfile` forces both for any fortress or `groundOnly` profile (the data's generic ranged default cannot re-enable it), so the four records neither target nor splash a flying enemy (`targeting.canTargetEnemy`, the splash loop of `ai.js resolveHit`); ground enemies are still attacked and take the radius-1.0 splash. 莫斯提马's slow pulse passes `{ status: 'slow', visible: true }`, so the existing slow status icon shows on every enemy in her range; the slow itself is unchanged. §21.29's skill-trigger deviation for the six 重装 skills (号角, 灰毫) is untouched.
+- **Players notice**: 号角 and 灰毫 (and their elites) ignore flying enemies completely — no shot, no splash — so flyers need another operator; against ground enemies they play as in 0.1.1. Enemies slowed by 莫斯提马 carry the slow icon.
+- Contributed by the PR #48 author (Paper-Yuan), squash-merged 2026-10-04. Normative lines rewritten with it: docs/SIM.md (the profession table: 要塞 ground only, by the PR), docs/DATA.md §2.1 (`canHitFly`).
+- Tests: the PR's — `test/sim/professions.test.js` (the four records read `canHitFly` false / `groundOnly`; a 要塞 beside a FLY enemy makes no attack and leaves it untouched, beside a ground enemy it attacks and splashes) and `test/content/kits_t4.test.js` (莫斯提马's slow buff carries the `slow` status).
diff --git a/docs/research/00-INDEX.md b/docs/research/00-INDEX.md
index dbbd5156..7544374d 100644
--- a/docs/research/00-INDEX.md
+++ b/docs/research/00-INDEX.md
@@ -84,7 +84,7 @@ The visible chess per tier are 16/17/19/22/19/19. The item slot uses the same ti
| Equipment | 2 per operator (board **or** hand). Locked; 3rd = replace, and the old one is destroyed. 2 identical normal items (equipped or not) merge into golden. | VERIFIED |
| Deployment | Free, at t=0, order **top→bottom then left→right** (right-side boss player mirrored). Ranged units may use melee tiles. | VERIFIED |
| DP | Start **10**, **+1/s**, cap **99**. Used only for auto-redeploy (original tile, respawn timer done, DP ≥ `cost`). | DATA/VERIFIED |
-| Skill auto-cast | Default: SP ready + about to attack/heal + an enemy in the **initial** range. ~~`skillTriggerDataList` rows with `skillIndex` 0 = skill 1 only (TANK S1 → on damage: only 古米 and 灰毫 this season)~~ — Superseded by user playtest #6 (DESIGN §20): the class rows apply to **every MANUAL skill** of the class and never to an AUTO skill (PRTS 卫戍协议/帮助 names whole classes; the 阵法术师 row must cover 薄绿's default S2, a phalanx that never attacks with its skill off); a MANUAL skill with its own 技能范围 (not an attack-range change) uses SKILL_RANGE; automatic operations have a 3 s cooldown. charId rows per 03. The TANK row came with 下半 (上半 had none); 深巡 S2, 雷蛇 S2, 号角 S2 / S3 and 灰毫 S1 / S2 deliberately cast with an enemy in range instead (the owner's decision, DESIGN §21.29). | VERIFIED (class-row reading superseded; six 重装 skills deviate on purpose) |
+| Skill auto-cast | Default: SP ready + about to attack/heal + an enemy in the **initial** range. ~~`skillTriggerDataList` rows with `skillIndex` 0 = skill 1 only (TANK S1 → on damage: only 古米 and 灰毫 this season)~~ — Superseded by user playtest #6 (DESIGN §20): the class rows apply to **every MANUAL skill** of the class and never to an AUTO skill (PRTS 卫戍协议/帮助 names whole classes; the 阵法术师 row must cover 薄绿's default S2, a phalanx that never attacks with its skill off); a MANUAL skill with its own 技能范围 (not an attack-range change) uses SKILL_RANGE; automatic operations have a 3 s cooldown. charId rows per 03. The TANK row came with 下半 (上半 had none); 深巡 S2, 雷蛇 S2, 号角 S2 / S3 and 灰毫 S1 / S2 deliberately cast with an enemy in range instead (the owner's decision, DESIGN §21.29); 余 S2 too, on its x-1 (SKILL_RANGE, the owner, 2026-10-04, DESIGN §22.10). | VERIFIED (class-row reading superseded; six 重装 skills deviate on purpose) |
| Speed | 2× forced, no manual control | VERIFIED |
| Board geometry | 19×21 stage. Player board rows 9–12, cols 2–10. Gates (9,10) and (12,10); R1–3 use only the lower one. Goal (9,2). Col 9 is a non-deployable lane. Hand row 7 cols 0–9. Temp hand row 8 cols 4–8. Boss field rows 1–5. | DATA |
| Bond counting | Distinct operators on board. 远见/奇迹/投资人 also count the hand. 绝技 counts elites. Layers persist all match; **no IN_BATTLE layer gains in 联防 or boss rounds**; each bond's layers stop at **999** (research 11). | DATA/VERIFIED |
diff --git a/docs/research/03-operators.md b/docs/research/03-operators.md
index 34baa2af..712f5c55 100644
--- a/docs/research/03-operators.md
+++ b/docs/research/03-operators.md
@@ -74,7 +74,7 @@ All skills fire automatically in this mode. Normal behaviour: AUTO skills fire b
Meaning (names are from the data; semantics partly inferred — the official wording, PRTS 卫戍协议/帮助 §作战阶段 技能操作, is quoted in DESIGN §20.2):
- `DEFAULT` (no matching row; 97 of 129 pool chess): the basic strategy "技能就绪,且即将进行普通攻击/治疗" — SP full AND about to attack (heal skills: to heal) AND an enemy (an injured ally) inside the initial range; a MANUAL skill with a 技能范围 of its own (not an attack-range change) uses `SKILL_RANGE` instead (DESIGN §20.2).
-- `TAKE_DAMAGE` (profession TANK, 15 chess): SP full AND the unit takes damage — PRTS 重装 "不受技能范围影响,受到伤害时释放技能". The row has skillIndex 0 but pool tanks use S1 x2, S2 x10, S3 x4; as a class row it covers every MANUAL skill of the class (DESIGN §20.2; C1 below keeps the "skill 1 only" counter-reading). **History of the row** (activity_table `autoChessData.skillTriggerDataList`): 上半 (act1autochess, 2025-11) shipped no TANK row — 重装 skills had no strategy of their own; 下半 (act2autochess, 2026-03-14) added `TANK | | | 0 | TAKE_DAMAGE` for every skill index, with PRTS's 重装 line (下半, 2026/3/14). **Deliberate deviation** (the owner, 2026-10-03, after community feedback — GitHub issue #4, PR #12; DESIGN §21.29): 深巡 S2, 雷蛇 S2, 号角 S2 / S3 and 灰毫 S1 / S2 cast with an enemy in range (`DEFAULT`; `tools/build-data.mjs TRIGGER_DEVIATIONS`, keyed per chess — 灰毫 S1 is the generic `skcom_atk_up[3]` — with `rawRule` keeping the official TAKE_DAMAGE); every other MANUAL 重装 skill, 深巡 S1 included, keeps TAKE_DAMAGE.
+- `TAKE_DAMAGE` (profession TANK, 15 chess): SP full AND the unit takes damage — PRTS 重装 "不受技能范围影响,受到伤害时释放技能". The row has skillIndex 0 but pool tanks use S1 x2, S2 x10, S3 x4; as a class row it covers every MANUAL skill of the class (DESIGN §20.2; C1 below keeps the "skill 1 only" counter-reading). **History of the row** (activity_table `autoChessData.skillTriggerDataList`): 上半 (act1autochess, 2025-11) shipped no TANK row — 重装 skills had no strategy of their own; 下半 (act2autochess, 2026-03-14) added `TANK | | | 0 | TAKE_DAMAGE` for every skill index, with PRTS's 重装 line (下半, 2026/3/14). **Deliberate deviation** (the owner, 2026-10-03, after community feedback — GitHub issue #4, PR #12; DESIGN §21.29): 深巡 S2, 雷蛇 S2, 号角 S2 / S3 and 灰毫 S1 / S2 cast with an enemy in range (`DEFAULT`; `tools/build-data.mjs TRIGGER_DEVIATIONS`, keyed per chess — 灰毫 S1 is the generic `skcom_atk_up[3]` — with `rawRule` keeping the official TAKE_DAMAGE); every other MANUAL 重装 skill, 深巡 S1 included, keeps TAKE_DAMAGE; extended 2026-10-04 to 余 S2 (SKILL_RANGE on its x-1, DESIGN §22.10).
- `ALWAYS` (5 chess; subprof bearer 旗手 / tactician 战术家 / bard 吟游者, plus 维什戴尔 S3 not in pool): cast as soon as SP is full, no target needed. Pool: 伺夜 S3, 缪尔赛思 S3 (tactician), 魔王 S3 (T4 & hidden T5), 浊心斯卡蒂 S3 (bard).
- `SEARCH` (4 chess; subprof librator 解放者 / phalanx 阵法术师, 安洁莉娜 S2/S3): [ASSUMED] cast when SP full and any enemy is on the field (search whole map) — phalanx/librator skills change their own attack mode and should not wait for an enemy in their (small/none) normal range. Pool: 薄绿 S2, 蜜蜡 S2 (hidden), 卡涅利安 S2 (phalanx); 安洁莉娜 S3. 玛恩纳 S3 and 圣聆初雪 S3 are overridden by their charId rows (CUSTOM_RANGE).
- `CUSTOM_RANGE_SEARCH_ENEMY` (6 chess): SP full AND an enemy inside the `skillRangeDict` range (listed below). Pool: 乌尔比安 S3 (6-1), 维娜·维多利亚 S3 (x-4), 余 S3 (3-15), 远牙 S3 (6-1), 玛恩纳 S3 (3-18), 圣聆初雪 S3 (x-2). Not in pool: 塑心 demetr, 司霆惊蛰 leizi2, 林 lin, 猎蜂? headb2.