dsh-novel-write-engine 0.2.11 → 0.2.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,20 @@
1
+ ## 0.2.12
2
+
3
+ 0.2.12 是工作台滚动与角色标签修复版本,不新增或改变阶段、工具、操作、门控、语义项、导出、schema 或配置键。
4
+
5
+ ### Fixed
6
+
7
+ - **页面滚动**:撤销 0.2.11 的固定顶栏与 `nwe-workbench` 内滚动,恢复宿主固定高度裁切盒内的整页滚动;顶栏、下一步卡和栏目导航随内容移动,页面根滚动条隐藏,滚轮、触控和键盘仍可滚到底。
8
+ - **局部滚动**:人物、时间线、线索、设定、全书资料、章节表与卷列表改为有界局部滚动;列表滚到边界后,滚轮继续滚动页面,不再形成滚轮陷阱。
9
+ - **展开卡片**:设定与线索分组中任意卡片展开时,整个分组跨两栏、卡片通栏显示;不再被锁在左半栏或右半栏。
10
+ - **全书资料标题**:删除 `summary::before` 的 `+`/`−` 伪元素,避免展开时多出第四个子项把标题和副标题挤进 14px 箭头列、贴到最右侧;标题行在打开和关闭状态都保持三列。
11
+ - **角色标签**:补齐 `antagonist` 的中文映射「反派」,人物卡不再裸出英文规范值;未知角色仍按原值兜底。
12
+
13
+ ### Tests
14
+
15
+ - 95 个测试文件 / 1011 项测试全绿;覆盖率 94.00 / 89.20 / 96.86 / 94.00,逐文件门禁通过;client 函数覆盖 85.34%,client bundle 239.97 KB(react-dom 外置)。
16
+ - 新增根滚动、宿主裁切盒、局部列表滚动、展开卡片跨整行、全书资料标题三列与 `antagonist` 中文标签回归;`typecheck`、`lint`、`build`、`check:pack`(27 files)、`check:artifacts`、`check:install` 通过。
17
+
1
18
  ## 0.2.11
2
19
 
3
20
  0.2.11 是工作台内容层与命令教程版本,不新增或改变阶段、工具、操作、门控、语义项、导出、schema 或配置键。
package/README.md CHANGED
@@ -10,7 +10,7 @@
10
10
  [![npm downloads](https://img.shields.io/npm/dm/dsh-novel-write-engine?style=flat-square&logo=npm&label=downloads)](https://www.npmjs.com/package/dsh-novel-write-engine)
11
11
  [![CI](https://img.shields.io/github/actions/workflow/status/ThzxxArt/dsh-novel-write-engine/ci.yml?branch=main&style=flat-square&logo=github&label=CI)](https://github.com/ThzxxArt/dsh-novel-write-engine/actions/workflows/ci.yml)
12
12
  [![release](https://img.shields.io/github/v/release/ThzxxArt/dsh-novel-write-engine?style=flat-square&logo=github&label=release)](https://github.com/ThzxxArt/dsh-novel-write-engine/releases)
13
- [![version](https://img.shields.io/badge/version-0.2.11-2f81f7?style=flat-square)](https://github.com/ThzxxArt/dsh-novel-write-engine/releases/tag/v0.2.11)
13
+ [![version](https://img.shields.io/badge/version-0.2.12-2f81f7?style=flat-square)](https://github.com/ThzxxArt/dsh-novel-write-engine/releases/tag/v0.2.12)
14
14
  [![Node](https://img.shields.io/badge/Node-%3E%3D24.9.0-339933?style=flat-square&logo=node.js&logoColor=white)](#1-兼容性)
15
15
  [![DSH](https://img.shields.io/badge/DSH-0.2.1--rc.2%20~%200.3-6f42c1?style=flat-square)](#1-兼容性)
16
16
  [![License](https://img.shields.io/github/license/ThzxxArt/dsh-novel-write-engine?style=flat-square)](LICENSE)
@@ -20,9 +20,9 @@
20
20
  </div>
21
21
 
22
22
  > [!IMPORTANT]
23
- > 当前版本 **0.2.11**。宿主范围:DSH `>=0.2.1-rc.2 <0.3.0-0`;Node `>=24.9.0`。
23
+ > 当前版本 **0.2.12**。宿主范围:DSH `>=0.2.1-rc.2 <0.3.0-0`;Node `>=24.9.0`。
24
24
  >
25
- > 0.2.11 是工作台内容层与命令教程版本:七栏内容区固定在面板高度内独立滚动,所有折叠详情、资料卡、章节/质量详情与章节表改为有界滚动;教程新增「全部命令」,覆盖 5 个入口、`/novel` 的 25 种带名写法、6 种导出、25 个 admin 操作与常用组合。没有新增或改变阶段、工具、操作、门控、语义项、导出、schema 或配置键。
25
+ > 0.2.12 是工作台滚动与角色标签修复版本:页面在宿主固定高度裁切盒内恢复整页滚动,顶栏与下一步卡随内容移动;人物、时间线、线索、设定、全书资料等长列表改为有界局部滚动,展开的设定/线索卡片跨整行;修复全书资料标题行被额外伪元素挤到最右,以及角色 `antagonist` 显示英文。没有新增或改变阶段、工具、操作、门控、语义项、导出、schema 或配置键。
26
26
 
27
27
  ---
28
28
 
@@ -204,7 +204,7 @@ pnpm --version # CLI 安装插件时需要
204
204
  corepack enable
205
205
  corepack prepare pnpm@11.28.9 --activate
206
206
 
207
- dsh plugin --profile web add dsh-novel-write-engine@0.2.11
207
+ dsh plugin --profile web add dsh-novel-write-engine@0.2.12
208
208
  ```
209
209
 
210
210
  安装后重启 DSH,或刷新 Web 页面。
@@ -252,10 +252,10 @@ corepack pnpm build
252
252
  corepack pnpm pack
253
253
  ```
254
254
 
255
- 得到 `dsh-novel-write-engine-0.2.11.tgz`,复制到目标机器后:
255
+ 得到 `dsh-novel-write-engine-0.2.12.tgz`,复制到目标机器后:
256
256
 
257
257
  ```bash
258
- dsh plugin --profile web add /absolute/path/to/dsh-novel-write-engine-0.2.11.tgz
258
+ dsh plugin --profile web add /absolute/path/to/dsh-novel-write-engine-0.2.12.tgz
259
259
  ```
260
260
 
261
261
  tarball 已包含 `lib/`、`rulepacks/`、`briefs/`、`skills/`、`presets/` 和两层 patch,不需要在目标机器重新构建。
@@ -267,7 +267,7 @@ tarball 已包含 `lib/`、`rulepacks/`、`briefs/`、`skills/`、`presets/` 和
267
267
 
268
268
  1. 左侧栏进入 **插件**;
269
269
  2. 点 **添加插件**;
270
- 3. 填 npm 包名 `dsh-novel-write-engine`(或精确版本 `dsh-novel-write-engine@0.2.11`);
270
+ 3. 填 npm 包名 `dsh-novel-write-engine`(或精确版本 `dsh-novel-write-engine@0.2.12`);
271
271
  4. 安装后启用,刷新页面,新开会话。
272
272
 
273
273
  插件页安装的是当前 profile 的依赖;Desktop 的插件页管理的是 `desktop` profile。
@@ -627,16 +627,16 @@ corepack pnpm test
627
627
 
628
628
  ## 升级与卸载
629
629
 
630
- ### 升级到 0.2.11
630
+ ### 升级到 0.2.12
631
631
 
632
- 0.2.11 是工作台内容层与命令教程更新,没有破坏性 schema 迁移、阶段/门控/导出或配置键变更;面板协议 `payload_version` 保持 7,`PANEL_VERSION` 从 0.2.10 升到 0.2.11。
632
+ 0.2.12 是工作台滚动与角色标签修复更新,没有破坏性 schema 迁移、阶段/门控/导出或配置键变更;面板协议 `payload_version` 保持 7,`PANEL_VERSION` 从 0.2.11 升到 0.2.12。
633
633
 
634
634
  ```bash
635
635
  dsh plugin --profile web remove dsh-novel-write-engine
636
- dsh plugin --profile web add dsh-novel-write-engine@0.2.11
636
+ dsh plugin --profile web add dsh-novel-write-engine@0.2.12
637
637
  ```
638
638
 
639
- 升级后刷新页面、新开会话。面板教程版本从 0.2.10 升到 0.2.11;旧标签页显示“需要刷新”时刷新即可。
639
+ 升级后刷新页面、新开会话。面板教程版本从 0.2.11 升到 0.2.12;旧标签页显示“需要刷新”时刷新即可。
640
640
 
641
641
  历史版本的升级说明见 [CHANGELOG.md](CHANGELOG.md);更早版本使用对应发布 tag 或 Release 快照查看。
642
642
 
@@ -793,15 +793,15 @@ presets/ # 内置 Agent 预设 patch
793
793
  tests/ # 单测、集成、falsify、e2e
794
794
  ```
795
795
 
796
- ### 当前工作树验证(0.2.11 基线)
796
+ ### 当前工作树验证(0.2.12 基线)
797
797
 
798
798
  以当前工作树实际跑出的结果为准:
799
799
 
800
- - `corepack pnpm test`:**95 个测试文件 / 1009 项全部通过**;
801
- - 覆盖率:**语句 93.99% / 分支 89.21% / 函数 96.86% / 行 93.99%**;逐文件门禁通过;client 函数覆盖 85.34%;client bundle 238.90 KB(react-dom 外置);
800
+ - `corepack pnpm test`:**95 个测试文件 / 1011 项全部通过**;
801
+ - 覆盖率:**语句 94.00% / 分支 89.20% / 函数 96.86% / 行 94.00%**;逐文件门禁通过;client 函数覆盖 85.34%;client bundle 239.97 KB(react-dom 外置);
802
802
  - `typecheck`、`lint`、`build`:通过;
803
- - 视觉:主工作台沿用上一轮 Chromium 1440×900 与 390×844 检查;新增命令教程由 client 测试打开弹框并逐项断言,**未做真实浏览器截图**;有项目态真实宿主、触屏真机与屏幕阅读器未验收;
804
- - 0.2.11 未改引擎写路径;本轮没有重新跑真实模型。
803
+ - 视觉:client 与 responsive 测试锁住“页面在宿主裁切盒内可滚、顶栏随内容移动、列表局部滚动、展开卡片跨整行”;未做触屏真机与屏幕阅读器验收;
804
+ - 0.2.12 未改引擎写路径;本轮没有重新跑真实模型。
805
805
 
806
806
  具体数字会随代码变化;发布前请以重新跑出的结果为准,不要把历史数字当保证。
807
807
 
package/lib/client.js CHANGED
@@ -10,7 +10,7 @@ window.__ModuleLoader__.load({
10
10
  const PANEL_ID = "novel-workshop";
11
11
  const PANEL_ROUTE = "/api/novel-write-engine/panel";
12
12
  /** User-visible panel/tutorial version; keep in sync with package.json. */
13
- const PANEL_VERSION = "0.2.11";
13
+ const PANEL_VERSION = "0.2.12";
14
14
  // src/command-reference.ts
15
15
  /** The five registered command entry points, including the umbrella command. */
16
16
  const COMMAND_ENTRY = [
@@ -826,11 +826,12 @@ window.__ModuleLoader__.load({
826
826
  width: 100%;
827
827
  max-width: 1120px;
828
828
  height: 100%;
829
+ max-height: 100%;
829
830
  min-height: 0;
830
831
  overflow-x: hidden;
831
832
  overflow-y: auto;
832
833
  overscroll-behavior: contain;
833
- scrollbar-gutter: stable;
834
+ scrollbar-width: none;
834
835
  margin: 0 auto;
835
836
  padding: clamp(18px, 3.2vw, 38px);
836
837
  color: var(--nwe-ink);
@@ -838,6 +839,7 @@ window.__ModuleLoader__.load({
838
839
  line-height: 1.55;
839
840
  }
840
841
  .nwe-root * { box-sizing: border-box; }
842
+ .nwe-root::-webkit-scrollbar { width: 0; height: 0; display: none; }
841
843
  .nwe-root::before {
842
844
  content: "";
843
845
  position: absolute;
@@ -946,6 +948,7 @@ window.__ModuleLoader__.load({
946
948
  }
947
949
  .nwe-help:hover { border-color: color-mix(in srgb, var(--nwe-gold) 60%, var(--nwe-border)); color: var(--nwe-ink); transform: translateY(-1px); }
948
950
  .nwe-help svg { flex: 0 0 auto; }
951
+ .nwe-root:focus-visible { outline: 2px solid var(--nwe-gold); outline-offset: -3px; }
949
952
  .nwe-root :focus-visible { outline: 2px solid var(--nwe-gold); outline-offset: 3px; }
950
953
  .nwe-modal-backdrop {
951
954
  position: fixed;
@@ -1892,8 +1895,6 @@ window.__ModuleLoader__.load({
1892
1895
  font-weight: 650;
1893
1896
  }
1894
1897
  .nwe-dossier > summary::-webkit-details-marker { display: none; }
1895
- .nwe-dossier > summary::before { content: "+"; color: var(--nwe-accent); font-size: 16px; line-height: 1; }
1896
- .nwe-dossier[open] > summary::before { content: "−"; }
1897
1898
  .nwe-dossier-note { margin-left: auto; color: var(--nwe-muted); font-size: 11px; font-weight: 400; }
1898
1899
  .nwe-dossier .nwe-section { margin-top: 12px; }
1899
1900
  .nwe-dossier .nwe-section-head { display: none; }
@@ -2030,7 +2031,17 @@ window.__ModuleLoader__.load({
2030
2031
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
2031
2032
  gap: 10px;
2032
2033
  align-items: start;
2034
+ max-height: min(56vh, 580px);
2035
+ overflow-x: hidden;
2036
+ overflow-y: auto;
2037
+ overscroll-behavior: contain;
2038
+ scrollbar-gutter: stable;
2033
2039
  margin-top: 9px;
2040
+ padding-right: 4px;
2041
+ }
2042
+ .nwe-card-grid:focus-visible {
2043
+ outline: 2px solid var(--nwe-accent);
2044
+ outline-offset: -2px;
2034
2045
  }
2035
2046
  .nwe-data-card {
2036
2047
  overflow: hidden;
@@ -2113,9 +2124,17 @@ window.__ModuleLoader__.load({
2113
2124
  .nwe-worldbook-layout > .nwe-subsection:first-child,
2114
2125
  .nwe-leads-layout > .nwe-subsection:first-child { grid-column: 1 / -1; }
2115
2126
  .nwe-worldbook-layout > .nwe-subsection .nwe-card-grid,
2116
- .nwe-leads-layout > .nwe-subsection .nwe-card-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
2127
+ .nwe-leads-layout > .nwe-subsection .nwe-card-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); max-height: min(40vh, 400px); }
2117
2128
  .nwe-worldbook-layout > .nwe-subsection:first-child .nwe-card-grid,
2118
2129
  .nwe-leads-layout > .nwe-subsection:first-child .nwe-card-grid { grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); }
2130
+ .nwe-worldbook-layout > .nwe-subsection:has(.nwe-data-card[open]),
2131
+ .nwe-leads-layout > .nwe-subsection:has(.nwe-data-card[open]) { grid-column: 1 / -1; }
2132
+ .nwe-worldbook-layout > .nwe-subsection:has(.nwe-data-card[open]) .nwe-card-grid,
2133
+ .nwe-leads-layout > .nwe-subsection:has(.nwe-data-card[open]) .nwe-card-grid {
2134
+ grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
2135
+ max-height: min(52vh, 540px);
2136
+ }
2137
+ #nwe-panel-characters .nwe-card-grid { max-height: min(60vh, 620px); }
2119
2138
  .nwe-quality-layout { display: block; }
2120
2139
  .nwe-quality-kpis {
2121
2140
  display: grid;
@@ -2243,44 +2262,26 @@ window.__ModuleLoader__.load({
2243
2262
  .nwe-chapter-cards-mobile { display: grid; gap: 8px; margin-top: 10px; }
2244
2263
  }
2245
2264
 
2246
- /* v10 data surfaces: bounded canvas, one disclosure language, local scroll. */
2265
+ /* v10 data surfaces: the host clips its fixed centre column, so the page owns
2266
+ exactly one scroller and the chrome stays in flow. The root scrollbar is
2267
+ hidden; card lists and detail bodies below keep their visible local bars. */
2247
2268
  .nwe-root {
2248
- display: flex;
2249
- flex-direction: column;
2250
- min-height: 0;
2251
- max-height: 100%;
2252
- overflow: hidden;
2253
- }
2254
- .nwe-hero,
2255
- .nwe-damaged,
2256
- .nwe-next,
2257
- .nwe-tabs { flex: 0 0 auto; }
2258
- .nwe-workbench {
2269
+ display: block;
2259
2270
  flex: 1 1 auto;
2271
+ height: 100%;
2272
+ max-height: 100%;
2260
2273
  min-height: 0;
2261
- margin-top: 2px;
2262
- padding: 0 6px 2px 0;
2263
2274
  overflow-x: hidden;
2264
2275
  overflow-y: auto;
2265
2276
  overscroll-behavior: contain;
2266
- scrollbar-gutter: stable;
2267
- }
2268
- .nwe-workbench:focus-visible { outline: 2px solid var(--nwe-accent); outline-offset: -3px; }
2269
- .nwe-workbench::-webkit-scrollbar { width: 10px; height: 10px; }
2270
- .nwe-workbench::-webkit-scrollbar-track {
2271
- border-radius: 999px;
2272
- background: color-mix(in srgb, var(--nwe-ink) 5%, transparent);
2273
- }
2274
- .nwe-workbench::-webkit-scrollbar-button { display: none; }
2275
- .nwe-workbench::-webkit-scrollbar-thumb {
2276
- border: 2px solid transparent;
2277
- border-radius: 999px;
2278
- background: color-mix(in srgb, var(--nwe-ink) 28%, transparent);
2279
- background-clip: padding-box;
2277
+ scrollbar-width: none;
2280
2278
  }
2281
- .nwe-workbench::-webkit-scrollbar-thumb:hover {
2282
- background: color-mix(in srgb, var(--nwe-ink) 42%, transparent);
2283
- background-clip: padding-box;
2279
+ .nwe-root::-webkit-scrollbar { width: 0; height: 0; display: none; }
2280
+ .nwe-workbench {
2281
+ min-width: 0;
2282
+ margin-top: 2px;
2283
+ padding: 0 6px 2px 0;
2284
+ overflow: visible;
2284
2285
  }
2285
2286
  .nwe-root details > summary { cursor: pointer; list-style: none; }
2286
2287
  .nwe-root details > summary::-webkit-details-marker { display: none; }
@@ -2304,6 +2305,7 @@ window.__ModuleLoader__.load({
2304
2305
  .nwe-info-card-body:focus-visible,
2305
2306
  .nwe-dossier-body:focus-visible,
2306
2307
  .nwe-fold-body:focus-visible,
2308
+ .nwe-card-grid:focus-visible,
2307
2309
  .nwe-table-wrap:focus-visible {
2308
2310
  outline: 2px solid var(--nwe-accent);
2309
2311
  outline-offset: -2px;
@@ -2312,11 +2314,13 @@ window.__ModuleLoader__.load({
2312
2314
  .nwe-info-card-body::-webkit-scrollbar,
2313
2315
  .nwe-dossier-body::-webkit-scrollbar,
2314
2316
  .nwe-fold-body::-webkit-scrollbar,
2317
+ .nwe-card-grid::-webkit-scrollbar,
2315
2318
  .nwe-table-wrap::-webkit-scrollbar { width: 10px; height: 10px; }
2316
2319
  .nwe-data-card-body::-webkit-scrollbar-track,
2317
2320
  .nwe-info-card-body::-webkit-scrollbar-track,
2318
2321
  .nwe-dossier-body::-webkit-scrollbar-track,
2319
2322
  .nwe-fold-body::-webkit-scrollbar-track,
2323
+ .nwe-card-grid::-webkit-scrollbar-track,
2320
2324
  .nwe-table-wrap::-webkit-scrollbar-track {
2321
2325
  border-radius: 999px;
2322
2326
  background: color-mix(in srgb, var(--nwe-ink) 5%, transparent);
@@ -2325,11 +2329,13 @@ window.__ModuleLoader__.load({
2325
2329
  .nwe-info-card-body::-webkit-scrollbar-button,
2326
2330
  .nwe-dossier-body::-webkit-scrollbar-button,
2327
2331
  .nwe-fold-body::-webkit-scrollbar-button,
2332
+ .nwe-card-grid::-webkit-scrollbar-button,
2328
2333
  .nwe-table-wrap::-webkit-scrollbar-button { display: none; }
2329
2334
  .nwe-data-card-body::-webkit-scrollbar-thumb,
2330
2335
  .nwe-info-card-body::-webkit-scrollbar-thumb,
2331
2336
  .nwe-dossier-body::-webkit-scrollbar-thumb,
2332
2337
  .nwe-fold-body::-webkit-scrollbar-thumb,
2338
+ .nwe-card-grid::-webkit-scrollbar-thumb,
2333
2339
  .nwe-table-wrap::-webkit-scrollbar-thumb {
2334
2340
  border: 2px solid transparent;
2335
2341
  border-radius: 999px;
@@ -2340,6 +2346,7 @@ window.__ModuleLoader__.load({
2340
2346
  .nwe-info-card-body::-webkit-scrollbar-thumb:hover,
2341
2347
  .nwe-dossier-body::-webkit-scrollbar-thumb:hover,
2342
2348
  .nwe-fold-body::-webkit-scrollbar-thumb:hover,
2349
+ .nwe-card-grid::-webkit-scrollbar-thumb:hover,
2343
2350
  .nwe-table-wrap::-webkit-scrollbar-thumb:hover {
2344
2351
  background: color-mix(in srgb, var(--nwe-ink) 42%, transparent);
2345
2352
  background-clip: padding-box;
@@ -2445,7 +2452,7 @@ window.__ModuleLoader__.load({
2445
2452
  }
2446
2453
  .nwe-dossier[open] .nwe-dossier-caret { transform: rotate(45deg); color: var(--nwe-accent); }
2447
2454
  .nwe-dossier-body {
2448
- max-height: min(60vh, 620px);
2455
+ max-height: min(50vh, 500px);
2449
2456
  overflow: auto;
2450
2457
  overscroll-behavior: contain;
2451
2458
  scrollbar-gutter: stable;
@@ -2557,6 +2564,20 @@ window.__ModuleLoader__.load({
2557
2564
  .nwe-table-wrap { max-height: 62vh; }
2558
2565
  .nwe-chapters { max-height: 58vh; }
2559
2566
  }
2567
+
2568
+ /* A card body is a reading window, not a wheel trap: at its edge the page
2569
+ continues to scroll. The modal keeps contain so the page never moves behind it. */
2570
+ .nwe-card-grid,
2571
+ .nwe-data-card-body,
2572
+ .nwe-info-card-body,
2573
+ .nwe-dossier-body,
2574
+ .nwe-fold-body,
2575
+ .nwe-chapter-detail,
2576
+ .nwe-table-wrap,
2577
+ .nwe-chapters,
2578
+ .nwe-activity,
2579
+ .nwe-volumes,
2580
+ .nwe-desk-main .nwe-chapters { overscroll-behavior: auto; }
2560
2581
  `;
2561
2582
  const icon = (size, path) => (0, react.createElement)("svg", {
2562
2583
  width: size,
@@ -3521,7 +3542,13 @@ brief P6 → check → brief P8 → archive 的顺序推进。
3521
3542
  }, item.label)));
3522
3543
  const asRow = (value) => typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
3523
3544
  const textOf = (value, fallback = "—") => typeof value === "string" && value !== "" ? value : typeof value === "number" && Number.isFinite(value) ? String(value) : fallback;
3524
- const roleLabel = (value) => value === "protagonist" ? "主角" : value === "supporting" ? "配角" : value === "extra" ? "龙套" : textOf(value);
3545
+ const ROLE_LABELS = {
3546
+ protagonist: "主角",
3547
+ supporting: "配角",
3548
+ antagonist: "反派",
3549
+ extra: "龙套"
3550
+ };
3551
+ const roleLabel = (value) => typeof value === "string" ? ROLE_LABELS[value] ?? textOf(value) : textOf(value);
3525
3552
  const STATUS_LABELS = {
3526
3553
  planted: "已埋",
3527
3554
  advanced: "已推进",
@@ -3676,7 +3703,12 @@ brief P6 → check → brief P8 → archive 的顺序推进。
3676
3703
  };
3677
3704
  const sectionList = (title, items, kind = "spark") => {
3678
3705
  if (!Array.isArray(items) || items.length === 0) return (0, react.createElement)("div", { className: "nwe-empty" }, `${title}:暂无数据`);
3679
- return (0, react.createElement)("div", { className: "nwe-card-grid" }, ...items.map((item, index) => {
3706
+ return (0, react.createElement)("div", {
3707
+ className: "nwe-card-grid",
3708
+ role: "region",
3709
+ "aria-label": `${title}列表,可滚动`,
3710
+ tabIndex: 0
3711
+ }, ...items.map((item, index) => {
3680
3712
  const row = asRow(item);
3681
3713
  const explicitLabel = row === null ? void 0 : row.a !== void 0 && row.b !== void 0 ? `${textOf(row.a)} ↔ ${textOf(row.b)}` : row.title ?? row.name ?? row.id ?? row.alias ?? row.term ?? row.event ?? row.a;
3682
3714
  const label = row === null ? String(item) : textOf(row.chapter === void 0 ? explicitLabel : `第 ${textOf(row.chapter)} 章${row.time === void 0 ? "" : ` · ${textOf(row.time)}`}`, explicitLabel === void 0 ? title : textOf(explicitLabel));
@@ -4087,7 +4119,9 @@ brief P6 → check → brief P8 → archive 的顺序推进。
4087
4119
  "data-plugin": "dsh-novel-write-engine",
4088
4120
  className: "nwe-root",
4089
4121
  "aria-busy": loading,
4090
- "data-state": view.state
4122
+ "aria-label": "网文工坊页面",
4123
+ "data-state": view.state,
4124
+ tabIndex: 0
4091
4125
  }, (0, react.createElement)("style", { key: "nwe-style" }, CSS), (0, react.createElement)("header", { className: "nwe-hero" }, (0, react.createElement)("div", { className: "nwe-brand" }, (0, react.createElement)("span", {
4092
4126
  className: "nwe-brand-mark",
4093
4127
  "aria-hidden": "true"
@@ -4106,8 +4140,7 @@ brief P6 → check → brief P8 → archive 的顺序推进。
4106
4140
  }, "项目定义不可读;先用 novel_state 查看,再用 novel_amend 按 next 修复。面板不会把它伪装成正常项目。") : null, ready && view.nextTitle !== "" ? nextCard(view) : null, ready ? tabBar(tab, onTab) : null, (0, react.createElement)("div", {
4107
4141
  className: "nwe-workbench",
4108
4142
  role: "region",
4109
- "aria-label": "网文工坊内容",
4110
- tabIndex: 0
4143
+ "aria-label": "网文工坊内容"
4111
4144
  }, ready && tab === "overview" ? (0, react.createElement)("div", {
4112
4145
  className: "nwe-stats",
4113
4146
  role: "group",
package/lib/index.d.ts CHANGED
@@ -2813,7 +2813,7 @@ declare const PANEL_ROUTE = "/api/novel-write-engine/panel";
2813
2813
  declare const SKILL_NAME = "novel-write-engine";
2814
2814
  declare const REMOTE_VERSION = 6;
2815
2815
  /** User-visible panel/tutorial version; keep in sync with package.json. */
2816
- declare const PANEL_VERSION = "0.2.11";
2816
+ declare const PANEL_VERSION = "0.2.12";
2817
2817
  /** The panel is a recent-history view; the wire payload and UI use one cap. */
2818
2818
  declare const PANEL_CHAPTER_LIMIT = 30;
2819
2819
  /** Project-relative locations. Every write goes through these constants. */
package/lib/index.js CHANGED
@@ -16,7 +16,7 @@ const PANEL_ROUTE = "/api/novel-write-engine/panel";
16
16
  const SKILL_NAME = "novel-write-engine";
17
17
  const REMOTE_VERSION = 6;
18
18
  /** User-visible panel/tutorial version; keep in sync with package.json. */
19
- const PANEL_VERSION = "0.2.11";
19
+ const PANEL_VERSION = "0.2.12";
20
20
  /** The panel is a recent-history view; the wire payload and UI use one cap. */
21
21
  const PANEL_CHAPTER_LIMIT = 30;
22
22
  /** Project-relative locations. Every write goes through these constants. */
@@ -6,7 +6,7 @@ export declare const PANEL_ROUTE = "/api/novel-write-engine/panel";
6
6
  export declare const SKILL_NAME = "novel-write-engine";
7
7
  export declare const REMOTE_VERSION = 6;
8
8
  /** User-visible panel/tutorial version; keep in sync with package.json. */
9
- export declare const PANEL_VERSION = "0.2.11";
9
+ export declare const PANEL_VERSION = "0.2.12";
10
10
  /** The panel is a recent-history view; the wire payload and UI use one cap. */
11
11
  export declare const PANEL_CHAPTER_LIMIT = 30;
12
12
  /** Project-relative locations. Every write goes through these constants. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-novel-write-engine",
3
- "version": "0.2.11",
3
+ "version": "0.2.12",
4
4
  "description": "Novel writing engine for DeepSeek Harness: state machine, gates, rulepacks and ledgers moved from prompts into code.",
5
5
  "keywords": [
6
6
  "dsh-plugin",