@stofone/dsh-agent-roster 0.9.0 → 0.9.2

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
@@ -4,6 +4,38 @@
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.9.2] - 2026-11-03
8
+
9
+ ### The member list is a table
10
+
11
+ - **Four columns now line up across rows.** Each member row used to compute its own grid, so the
12
+ name / description / tool policy / model columns drifted from row to row and the list read as
13
+ separate blocks. `.rstr-members` owns the column widths and every row uses `subgrid`.
14
+ - **One line per member at narrow widths**: name and role on the left, the policy pinned right,
15
+ description and model beneath — four lines instead of five, and nothing overlaps.
16
+ - Member notes (aliases, declared skills, inherited fields) span the full row instead of pushing
17
+ the columns around.
18
+
19
+ ## [0.9.1] - 2026-11-03
20
+
21
+ ### Expansion stops clipping itself
22
+
23
+ - **No more scroll boxes inside expansions.** 0.8.3 capped the expanded collection list at
24
+ `max-height: 340px` with its own scrollbar; with 21 rosters that reads as "the list is cut off".
25
+ The cap and the nested scroller are gone — the panel root is the only thing that scrolls, and
26
+ an expanded section simply grows.
27
+ - **The sources tab gets its page padding back** (`16px 28px 28px`); its collections had been
28
+ rendering flush against the window edge, hard against `overflow-x: hidden`.
29
+ - **Source collections use the ledger row**, like rosters and teams. They were still emitting
30
+ `.rstr-card*` class names whose rules disappeared in the 0.9.0 ledger rewrite, so the tab
31
+ rendered unstyled elements. A regression assertion now forbids those class names returning.
32
+ - **Member rows keep name and role on one line**: `toolPolicy` moved from the head to the meta
33
+ strip, where the model, effort and prompt size already sit.
34
+ - **Wider id column with a title tooltip**, so `agent-roster-collective` is readable instead of
35
+ truncated to `agent-roster-collec…`.
36
+ - The CSS guard now asserts the opposite of what it did in 0.8.3: expansions must carry neither
37
+ `max-height` nor `overflow`, because nested scrolling is what made the content look incomplete.
38
+
7
39
  ## [0.9.0] - 2026-11-03
8
40
 
9
41
  ### The roster list is a ledger
@@ -356,7 +388,9 @@
356
388
  - 工具返回值含 `undefined` 键,运行时按 `value is not lossless JSON` 整次拒绝;缺失值统一写 `null`,
357
389
  且所有返回值先过 `lib/json.js#lossless`。
358
390
 
359
- [Unreleased]: https://github.com/dsh-agent-roster/dsh-agent-roster/compare/v0.9.0...main
391
+ [Unreleased]: https://github.com/dsh-agent-roster/dsh-agent-roster/compare/v0.9.2...main
392
+ [0.9.2]: https://github.com/dsh-agent-roster/dsh-agent-roster/releases/tag/v0.9.2
393
+ [0.9.1]: https://github.com/dsh-agent-roster/dsh-agent-roster/releases/tag/v0.9.1
360
394
  [0.9.0]: https://github.com/dsh-agent-roster/dsh-agent-roster/releases/tag/v0.9.0
361
395
  [0.8.3]: https://github.com/dsh-agent-roster/dsh-agent-roster/releases/tag/v0.8.3
362
396
  [0.8.2]: https://github.com/dsh-agent-roster/dsh-agent-roster/releases/tag/v0.8.2
package/README.md CHANGED
@@ -268,7 +268,7 @@ member and finally `roster_verify`. Creating the team stays with the runtime.
268
268
 
269
269
  ## Sidebar panel
270
270
 
271
- The roster list is a **ledger, not a wall of cards**: one row per roster — a 3px state edge (lit only when something is wrong, quiet when it is fine), a monospace id column, the title with a one-line description, right-aligned counts (members / errors / warnings / deployment), and a quiet pair of actions (edit, expand). Duplicate, copy-create and delete moved into the expanded area, which turns 105 buttons across 21 rosters into 42. Below 860px the tag pool becomes a top row and the metadata wraps.
271
+ The roster list is a **ledger, not a wall of cards**: one row per roster — a 3px state edge (lit only when something is wrong, quiet when it is fine), a monospace id column, the title with a one-line description, right-aligned counts (members / errors / warnings / deployment), and a quiet pair of actions (edit, expand). Duplicate, copy-create and delete moved into the expanded area, which turns 105 buttons across 21 rosters into 42. Below 860px the tag pool becomes a top row and the metadata wraps. Expansions never build their own scroll box: the panel root is the only scroller, so an expanded section grows as tall as its content instead of showing "just a few rows".
272
272
 
273
273
  The panel takes the full page width; nothing constrains it to a reading column. The archive list has
274
274
  a **tag pool** on the left: every tag present in the library, with how many archives carry it. Clicking
package/README.zh.md CHANGED
@@ -262,7 +262,7 @@ node bin/cli.mjs validate --dir orgs/agent-roster-collective
262
262
 
263
263
  面板铺满整个页面宽度,外层容器不设阅读列宽度。
264
264
 
265
- 档案列表是**账本,不是卡片墙**:一行一份档案——左沿 3 像素状态色(只有出错或有提醒时才亮,正常的档案不标记)、等宽字体的 id 列、标题与一句话描述、右侧计数(成员数 / 错误 / 提醒 / 部署态),最后是一对安静的操作(编辑、展开成员)。复制、复制建队、删除收在展开区里,21 份档案的 105 个按钮因此变成 42 个。窄于 860 像素时标签池从左侧栏变成顶上一行、元数据自动折行。
265
+ 档案列表是**账本,不是卡片墙**:一行一份档案——左沿 3 像素状态色(只有出错或有提醒时才亮,正常的档案不标记)、等宽字体的 id 列、标题与一句话描述、右侧计数(成员数 / 错误 / 提醒 / 部署态),最后是一对安静的操作(编辑、展开成员)。复制、复制建队、删除收在展开区里,21 份档案的 105 个按钮因此变成 42 个。窄于 860 像素时标签池从左侧栏变成顶上一行、元数据自动折行。展开区不另建小滚动盒:整页只有面板根滚动,展开多少内容就撑多高,不会出现「展开了却只看得到几条」。
266
266
 
267
267
  档案列表左侧是**标签池**:列出全库出现过的标签
268
268
  以及各标签的档案数,点标签即筛选——多选是「且」,一个按钮清除选择。标签池只影响视图,不会把
package/client.js CHANGED
@@ -468,42 +468,47 @@ window.__ModuleLoader__.load({
468
468
  /* ------------------------------------------------------------------ */
469
469
 
470
470
  function MemberBlock({ member }) {
471
+ // 四列由 .rstr-members 的 subgrid 统一给宽度:姓名 / 说明 / 策略 / 模型。
472
+ // 说明与策略即使为空也占位,否则后面的列会整体左移,表格就对不齐了。
473
+ const notes = [];
474
+ if (Array.isArray(member.aliases) && member.aliases.length > 0) {
475
+ notes.push(`${t("member.aliases")}: ${member.aliases.join(", ")}`);
476
+ }
477
+ if (Array.isArray(member.skills) && member.skills.length > 0) {
478
+ notes.push(`${t("member.skills")}: ${member.skills.join(", ")}(${t("member.skillsHint")})`);
479
+ }
480
+ if (Array.isArray(member.inherited) && member.inherited.length > 0) {
481
+ notes.push(`inherited: ${member.inherited.join(", ")}`);
482
+ }
483
+ if (member.notes) notes.push(member.notes);
484
+
471
485
  return h(
472
486
  "div",
473
487
  { className: "rstr-member" },
474
488
  h(
475
489
  "div",
476
490
  { className: "rstr-member-head" },
477
- h("strong", null, member.name),
491
+ h("strong", { className: "rstr-member-name" }, member.name),
478
492
  member.role ? h(Chip, null, member.role) : null,
479
- member.toolPolicy ? h(Chip, { tone: "policy" }, `${t("member.policy")}: ${member.toolPolicy}`) : null,
480
493
  ),
481
- member.description ? h("p", { className: "rstr-member-desc" }, member.description) : null,
482
- Array.isArray(member.aliases) && member.aliases.length > 0
483
- ? h("p", { className: "rstr-muted rstr-small" }, `${t("member.aliases")}: ${member.aliases.join(", ")}`)
484
- : null,
494
+ h("p", { className: "rstr-member-desc" }, member.description ?? ""),
495
+ h(
496
+ "span",
497
+ { className: "rstr-member-policy" },
498
+ member.toolPolicy ? h(Chip, { tone: "policy" }, member.toolPolicy) : null,
499
+ ),
485
500
  h(
486
501
  "div",
487
502
  { className: "rstr-member-meta" },
488
- member.model ? h("span", null, `${t("member.model")}: ${member.model}`) : null,
489
- member.reasoningEffort ? h("span", null, `${t("member.effort")}: ${member.reasoningEffort}`) : null,
503
+ member.model ? h("span", null, member.model) : null,
504
+ member.reasoningEffort ? h("span", null, member.reasoningEffort) : null,
490
505
  member.fallback ? h("span", null, `${t("member.fallback")}: ${member.fallback}`) : null,
491
506
  member.toolScope?.allow?.length
492
507
  ? h("span", null, `${t("member.tools")}: ${member.toolScope.allow.join(", ")}`)
493
508
  : null,
494
509
  h("span", { className: "rstr-muted" }, t("team.promptChars", { count: member.systemPromptChars })),
495
510
  ),
496
- Array.isArray(member.skills) && member.skills.length > 0
497
- ? h(
498
- "p",
499
- { className: "rstr-muted rstr-small" },
500
- `${t("member.skills")}: ${member.skills.join(", ")}(${t("member.skillsHint")})`,
501
- )
502
- : null,
503
- Array.isArray(member.inherited) && member.inherited.length > 0
504
- ? h("p", { className: "rstr-muted rstr-small" }, `inherited: ${member.inherited.join(", ")}`)
505
- : null,
506
- member.notes ? h("p", { className: "rstr-muted rstr-small" }, member.notes) : null,
511
+ notes.map((text, index) => h("p", { key: `note-${index}`, className: "rstr-member-note" }, text)),
507
512
  );
508
513
  }
509
514
 
@@ -1755,22 +1760,34 @@ window.__ModuleLoader__.load({
1755
1760
  collections.map((collection) =>
1756
1761
  h(
1757
1762
  "article",
1758
- { key: `${collection.origin?.source ?? ""}::${collection.id}`, className: "rstr-card" },
1759
- h(
1760
- "header",
1761
- { className: "rstr-card-head" },
1762
- h("h3", { className: "rstr-card-title" }, collection.title || collection.id),
1763
- h(Badge, { tone: "neutral" }, t("source.registered", { count: collection.rosters?.length ?? 0 })),
1764
- ),
1765
- collection.description ? h("p", { className: "rstr-card-desc" }, collection.description) : null,
1766
- h(
1767
- "p",
1768
- { className: "rstr-muted rstr-small" },
1769
- `${t("source.repo")} ${collection.repo ?? ""}@${collection.ref ?? "main"}${collection.path ? `/${collection.path}` : ""}`,
1770
- ),
1763
+ {
1764
+ key: `${collection.origin?.source ?? ""}::${collection.id}`,
1765
+ className: openId === collection.id ? "rstr-row rstr-row-open" : "rstr-row",
1766
+ },
1771
1767
  h(
1772
1768
  "div",
1773
- { className: "rstr-card-actions" },
1769
+ { className: "rstr-row-body" },
1770
+ h("code", { className: "rstr-row-id", title: collection.id }, collection.id),
1771
+ h(
1772
+ "div",
1773
+ { className: "rstr-row-text" },
1774
+ h(
1775
+ "h3",
1776
+ { className: "rstr-row-title" },
1777
+ collection.title || collection.id,
1778
+ h(Badge, { tone: "neutral" }, t("source.registered", { count: collection.rosters?.length ?? 0 })),
1779
+ ),
1780
+ collection.description ? h("p", { className: "rstr-row-desc" }, collection.description) : null,
1781
+ h(
1782
+ "p",
1783
+ { className: "rstr-source-meta" },
1784
+ `${collection.repo ?? ""}@${collection.ref ?? "main"}${collection.path ? `/${collection.path}` : ""}`,
1785
+ ),
1786
+ ),
1787
+ h("div", { className: "rstr-row-stats" }, h("span", null, `${collection.rosters?.length ?? 0}`)),
1788
+ h(
1789
+ "div",
1790
+ { className: "rstr-row-actions" },
1774
1791
  h(
1775
1792
  "button",
1776
1793
  {
@@ -1785,6 +1802,7 @@ window.__ModuleLoader__.load({
1785
1802
  "button",
1786
1803
  { type: "button", className: "rstr-btn", onClick: () => toggle(collection) },
1787
1804
  openId === collection.id ? t("source.hide") : t("source.open"),
1805
+ ),
1788
1806
  ),
1789
1807
  ),
1790
1808
  openId === collection.id
@@ -2301,7 +2319,7 @@ window.__ModuleLoader__.load({
2301
2319
 
2302
2320
  .rstr-row-body {
2303
2321
  display: grid;
2304
- grid-template-columns: minmax(88px, 140px) minmax(0, 1fr) auto auto;
2322
+ grid-template-columns: minmax(110px, 176px) minmax(0, 1fr) auto auto;
2305
2323
  align-items: baseline;
2306
2324
  gap: 8px 16px;
2307
2325
  padding: 13px 8px 13px 0;
@@ -2336,31 +2354,52 @@ window.__ModuleLoader__.load({
2336
2354
  .rstr-row-detail {
2337
2355
  display: flex;
2338
2356
  flex-direction: column;
2339
- gap: 12px;
2340
- padding: 10px 14px 18px 14px;
2357
+ gap: 14px;
2358
+ padding: 12px 16px 20px 16px;
2341
2359
  margin: 0 0 12px -1px;
2342
2360
  min-width: 0;
2343
2361
  background: var(--dsw-alias-bg-layer-2);
2362
+ border-left: 2px solid var(--dsw-alias-border-l2);
2344
2363
  }
2345
2364
  .rstr-row-detail-actions { display: flex; gap: 6px; flex-wrap: wrap; padding-top: 4px; }
2346
2365
 
2347
2366
  /* ---- 成员块 ----------------------------------------------------------- */
2348
2367
 
2349
- .rstr-members { display: flex; flex-direction: column; gap: 0; border-top: 1px dashed var(--dsw-alias-border-l1); }
2368
+ /* 成员是一张表:四列由容器统一给宽度(subgrid),否则每一行各算各的网格,
2369
+ 姓名 / 说明 / 策略 / 模型四列对不齐,读起来就是散的。 */
2370
+ .rstr-members {
2371
+ display: grid;
2372
+ grid-template-columns: minmax(120px, 172px) minmax(0, 1fr) 104px 244px;
2373
+ column-gap: 14px;
2374
+ border-top: 1px dashed var(--dsw-alias-border-l1);
2375
+ }
2350
2376
  .rstr-member {
2351
2377
  display: grid;
2352
- grid-template-columns: minmax(120px, 170px) minmax(0, 1fr) auto;
2353
- gap: 6px 16px;
2378
+ grid-column: 1 / -1;
2379
+ grid-template-columns: subgrid;
2380
+ column-gap: 14px;
2381
+ row-gap: 2px;
2354
2382
  align-items: baseline;
2355
- padding: 9px 4px;
2383
+ padding: 10px 4px;
2356
2384
  border-bottom: 1px solid var(--dsw-alias-border-l1);
2357
2385
  min-width: 0;
2358
2386
  }
2359
2387
  .rstr-member:last-child { border-bottom: none; }
2360
2388
  .rstr-member-head { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; min-width: 0; }
2361
- .rstr-member-name { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 12px; font-weight: 600; color: var(--dsw-alias-label-primary); }
2389
+ .rstr-member-name { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 12px; font-weight: 600; color: var(--dsw-alias-label-primary); overflow: hidden; text-overflow: ellipsis; }
2362
2390
  .rstr-member-desc { margin: 0; font-size: 12px; color: var(--dsw-alias-label-secondary); min-width: 0; }
2363
- .rstr-member-meta { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; font-size: 11px; color: var(--dsw-alias-label-secondary); justify-self: end; font-variant-numeric: tabular-nums; }
2391
+ .rstr-member-policy { justify-self: start; min-width: 0; }
2392
+ .rstr-member-meta { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; font-size: 11px; color: var(--dsw-alias-label-secondary); justify-self: end; font-variant-numeric: tabular-nums; }
2393
+ .rstr-member-note { grid-column: 1 / -1; margin: 0; font-size: 11px; color: var(--dsw-alias-label-secondary); }
2394
+ @media (max-width: 900px) {
2395
+ /* 窄面板:姓名一行、策略贴右;说明与模型各占一整行。 */
2396
+ .rstr-members { grid-template-columns: minmax(0, 1fr) auto; }
2397
+ .rstr-member-head { grid-column: 1; grid-row: 1; }
2398
+ .rstr-member-policy { grid-column: 2; grid-row: 1; justify-self: end; }
2399
+ .rstr-member-desc { grid-column: 1 / -1; grid-row: 2; margin-top: 2px; }
2400
+ .rstr-member-meta { grid-column: 1 / -1; grid-row: 3; justify-self: start; }
2401
+ .rstr-member-note { grid-row: auto; }
2402
+ }
2364
2403
 
2365
2404
  /* ---- 队长块 ----------------------------------------------------------- */
2366
2405
 
@@ -2394,21 +2433,33 @@ window.__ModuleLoader__.load({
2394
2433
 
2395
2434
  /* ---- 档案源 ----------------------------------------------------------- */
2396
2435
 
2397
- .rstr-sources { display: flex; flex-direction: column; gap: 0; border-top: 1px solid var(--dsw-alias-border-l2); }
2436
+ .rstr-sources { display: flex; flex-direction: column; gap: 0; min-width: 0; padding: 16px 28px 28px; border-top: 1px solid var(--dsw-alias-border-l2); }
2398
2437
  .rstr-sources-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 12px; }
2438
+ /* 展开区自己滚会把内容关进小盒子(曾经 max-height:320px 就是"显示不全"的来源)。
2439
+ 整页只有 .rstr-page 一个滚动容器,展开区只负责把高度撑开。 */
2399
2440
  .rstr-source-detail {
2400
2441
  display: flex;
2401
2442
  flex-direction: column;
2402
- gap: 2px;
2443
+ gap: 4px;
2403
2444
  min-width: 0;
2404
- max-height: 320px;
2405
- overflow-y: auto;
2406
- overflow-x: hidden;
2407
- padding: 6px 0 10px 15px;
2445
+ padding: 8px 0 12px 15px;
2446
+ border-bottom: 1px solid var(--dsw-alias-border-l1);
2447
+ border-left: 2px solid var(--dsw-alias-border-l2);
2448
+ margin-left: 2px;
2449
+ }
2450
+ .rstr-source-roster {
2451
+ display: grid;
2452
+ grid-template-columns: minmax(120px, 180px) minmax(0, 1fr) auto;
2453
+ align-items: baseline;
2454
+ gap: 4px 14px;
2455
+ min-width: 0;
2456
+ font-size: 12px;
2457
+ padding: 4px 6px 4px 0;
2408
2458
  border-bottom: 1px solid var(--dsw-alias-border-l1);
2409
2459
  }
2410
- .rstr-source-roster { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; min-width: 0; font-size: 12px; padding: 3px 0; }
2411
- .rstr-source-roster > .rstr-muted { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
2460
+ .rstr-source-roster:last-of-type { border-bottom: none; }
2461
+ .rstr-source-roster > .rstr-muted { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
2462
+ .rstr-source-meta { margin: 2px 0 0 0; min-width: 0; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 11px; color: var(--dsw-alias-label-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
2412
2463
 
2413
2464
  /* ---- 通用件 ----------------------------------------------------------- */
2414
2465
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stofone/dsh-agent-roster",
3
- "version": "0.9.0",
3
+ "version": "0.9.2",
4
4
  "description": "多 Agent 团队的静态成员档案定义与校验层:档案库在面板里看得见、改得动,团队成员的人设、模型与工具边界固化成可校验、可版本化的文件,并在 dsh-agent-teams 创建成员时把档案桥接给运行时。",
5
5
  "type": "module",
6
6
  "main": "index.js",