@lmzhen/dsh-evolution-skill-health 0.34.0 → 0.36.0

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/lib/client.js CHANGED
@@ -112,6 +112,55 @@ window.__ModuleLoader__.load({
112
112
  reason: "transport"
113
113
  });
114
114
  //#endregion
115
+ //#region ../evolution-client-kit/src/notice.ts
116
+ /** One inline state notice: semantic tone plus text, no surface-specific styling. */
117
+ //#endregion
118
+ //#region ../evolution-client-kit/src/presentation/decision-frame.ts
119
+ /** One decision card: title, facts, at most one primary, secondary actions and details. */
120
+ //#endregion
121
+ //#region ../evolution-client-kit/src/presentation/task-banner.ts
122
+ /** A read-only task hint; it deliberately has no primary action. */
123
+ //#endregion
124
+ //#region ../evolution-client-kit/src/presentation/chips.ts
125
+ /** Read-only status chips and toggleable filter chips. */
126
+ //#endregion
127
+ //#region ../evolution-client-kit/src/presentation/empty-state.ts
128
+ /** A compact completed/empty state with at most one primary next step. */
129
+ //#endregion
130
+ //#region ../evolution-client-kit/src/presentation/disclosure-group.ts
131
+ /** A native details group for normal/secondary facts. */
132
+ //#endregion
133
+ //#region ../evolution-client-kit/src/presentation/time-text.ts
134
+ /** The one local-time presentation used by reading surfaces. */
135
+ //#endregion
136
+ //#region ../evolution-client-kit/src/presentation/action-menu.ts
137
+ /**
138
+ * The one seam onto the platform's menu material, plus a small fallback for deployments
139
+ * without the primitive row. No page owns a second menu implementation.
140
+ */
141
+ const PLATFORM_UI_MODULE$1 = "@deepseek-ai/dsh-client-ui-primitives";
142
+ /**
143
+ * Accept only the two component functions; a namespace row without them is not a menu.
144
+ * @param row - the module row's exports.
145
+ * @returns the two components, or undefined.
146
+ */
147
+ function menuPrimitivesFrom(row) {
148
+ const surface = row.MenuSurface;
149
+ const item = row.MenuItemButton;
150
+ if (typeof surface !== "function" || typeof item !== "function") return void 0;
151
+ return {
152
+ MenuSurface: surface,
153
+ MenuItemButton: item
154
+ };
155
+ }
156
+ (() => {
157
+ try {
158
+ return menuPrimitivesFrom(require(PLATFORM_UI_MODULE$1));
159
+ } catch {
160
+ return;
161
+ }
162
+ })();
163
+ //#endregion
115
164
  //#region ../evolution-client-kit/src/action.ts
116
165
  /**
117
166
  * Command-only actions. Approval decisions are a separate host API and must never
@@ -314,6 +363,8 @@ window.__ModuleLoader__.load({
314
363
  "loading": "读取中…",
315
364
  "group.byRule": "按规则",
316
365
  "group.bySkill": "按技能",
366
+ "health.complete": "没有需要处理的问题",
367
+ "health.normal": "{n} 项正常,展开查看",
317
368
  "verdict.healthy": "正常",
318
369
  "verdict.warn": "警告",
319
370
  "verdict.needs-restructure": "需重构",
@@ -396,6 +447,8 @@ window.__ModuleLoader__.load({
396
447
  "loading": "Loading…",
397
448
  "group.byRule": "By rule",
398
449
  "group.bySkill": "By skill",
450
+ "health.complete": "Nothing needs attention",
451
+ "health.normal": "{n} normal items — expand to view",
399
452
  "verdict.healthy": "OK",
400
453
  "verdict.warn": "Warn",
401
454
  "verdict.needs-restructure": "Needs restructure",
@@ -498,13 +551,19 @@ window.__ModuleLoader__.load({
498
551
  ":where(.dsh-evolution-skill-health) { --evo-type-lg:calc(1em + 2px);--evo-type-body:1em;--evo-type-sm:calc(1em - 1px);--evo-type-xs:calc(1em - 2px);--evo-space-2:2px;--evo-space-4:4px;--evo-space-6:6px;--evo-space-8:8px;--evo-space-10:10px;--evo-space-12:12px;--evo-space-14:14px;--evo-space-16:16px;--evo-space-20:20px;--evo-radius-chip:4px;--evo-radius-control:8px;--evo-radius-surface:12px;--evo-radius-pill:999px;--evo-hairline-width:.5px;--evo-hairline-marker:2px;--evo-measure-read:80ch;--evo-leading-base:1.5;--evo-tone-quiet:var(--dsw-alias-label-secondary);--evo-tone-primary:var(--dsw-alias-brand-primary);--evo-tone-danger:var(--dsw-alias-state-error-primary);--evo-tone-success:var(--dsw-alias-state-success-primary);--evo-focus-ring:2px solid var(--dsw-alias-label-primary);--evo-focus-offset:-2px;--evo-cap-aside:280px;--evo-cap-block:260px }",
499
552
  ":where(.dsh-evolution-skill-health) { display: flex; flex-direction: column; gap: var(--evo-space-12); padding: var(--evo-space-16); color: var(--dsw-alias-label-primary); font-size: var(--evo-type-sm); line-height: var(--evo-leading-base); }",
500
553
  ":where(.dsh-evolution-skill-health [data-role=\"hint\"]) { margin: 0; color: var(--dsw-alias-label-secondary); }",
501
- ":where(.dsh-evolution-skill-health [data-role=\"stats\"]) { display: grid; grid-template-columns: repeat(auto-fit, minmax(136px, 1fr)); gap: var(--evo-space-8); }",
502
- ":where(.dsh-evolution-skill-health [data-role=\"stat\"]) { display: flex; flex-direction: column; gap: var(--evo-space-2); padding: var(--evo-space-8) var(--evo-space-10); border: var(--evo-hairline-width) solid var(--dsw-alias-border-l1); border-radius: var(--evo-radius-control); }",
554
+ ":where(.dsh-evolution-skill-health [data-role=\"stats\"]) { display: flex; flex-wrap: wrap; gap: var(--evo-space-6); }",
555
+ ":where(.dsh-evolution-skill-health [data-role=\"stat\"]) { display: inline-flex; align-items: baseline; gap: var(--evo-space-4); padding: var(--evo-space-4) var(--evo-space-10); border: var(--evo-hairline-width) solid var(--dsw-alias-border-l1); border-radius: var(--evo-radius-pill); background: transparent; color: inherit; font: inherit; text-align: left; cursor: pointer; }",
556
+ ":where(.dsh-evolution-skill-health [data-role=\"stat-value\"]) { font-size: var(--evo-type-sm); }",
557
+ ":where(.dsh-evolution-skill-health [data-role=\"health-complete\"]) { padding: var(--evo-space-12) var(--evo-space-14); border: var(--evo-hairline-width) solid var(--dsw-alias-state-success-primary); border-radius: var(--evo-radius-control); background: var(--dsw-alias-bg-layer-1); color: var(--dsw-alias-state-success-primary); }",
558
+ ":where(.dsh-evolution-skill-health [data-role=\"health-normal\"]) { display: flex; flex-direction: column; gap: var(--evo-space-4); padding-top: var(--evo-space-4); }",
559
+ ":where(.dsh-evolution-skill-health [data-role=\"health-normal\"] > summary) { cursor: pointer; color: var(--dsw-alias-label-tertiary); font-size: var(--evo-type-xs); }",
560
+ ":where(.dsh-evolution-skill-health [data-role=\"stat\"][aria-pressed=\"true\"]) { border-color: var(--dsw-alias-brand-primary); background: var(--dsw-alias-interactive-bg-hover); }",
561
+ ":where(.dsh-evolution-skill-health [data-role=\"stat\"]:disabled) { opacity: 0.55; cursor: default; }",
503
562
  ":where(.dsh-evolution-skill-health [data-role=\"stat\"][data-tone=\"ok\"]) { box-shadow: inset 2px 0 0 var(--dsw-alias-state-success-primary); }",
504
563
  ":where(.dsh-evolution-skill-health [data-role=\"stat\"][data-tone=\"warn\"]) { box-shadow: inset 2px 0 0 var(--dsw-alias-state-warn-primary); }",
505
564
  ":where(.dsh-evolution-skill-health [data-role=\"stat\"][data-tone=\"error\"]) { box-shadow: inset 2px 0 0 var(--dsw-alias-state-error-primary); }",
506
565
  ":where(.dsh-evolution-skill-health [data-role=\"stat\"][data-tone=\"unreadable\"]) { box-shadow: inset 2px 0 0 var(--evo-tone-quiet); }",
507
- ":where(.dsh-evolution-skill-health [data-role=\"stat-value\"]) { font-size: var(--evo-type-lg); font-variant-numeric: tabular-nums; line-height: 1; }",
566
+ ":where(.dsh-evolution-skill-health [data-role=\"stat-value\"]) { font-variant-numeric: tabular-nums; }",
508
567
  ":where(.dsh-evolution-skill-health [data-role=\"stat-label\"]) { color: var(--dsw-alias-label-tertiary); }",
509
568
  ":where(.dsh-evolution-skill-health [data-role=\"group-title\"]) { margin: 0; font-weight: 500; }",
510
569
  ":where(.dsh-evolution-skill-health [data-role=\"rule-table\"]) { display: table; width: 100%; border-collapse: collapse; border: var(--evo-hairline-width) solid var(--dsw-alias-border-l1); border-radius: var(--evo-radius-control); overflow: hidden; }",
@@ -549,6 +608,29 @@ window.__ModuleLoader__.load({
549
608
  return cached ?? void 0;
550
609
  }
551
610
  //#endregion
611
+ //#region src/client/health-presentation.ts
612
+ /**
613
+ * Split rows without dropping or inventing a verdict. Unreadable is an issue, never normal.
614
+ * @param rows - all rows in the current projection.
615
+ * @returns issues in severity order and the normal remainder.
616
+ */
617
+ function healthViewModel(rows) {
618
+ const order = [
619
+ "error",
620
+ "needs-restructure",
621
+ "warn",
622
+ "unreadable",
623
+ "healthy"
624
+ ];
625
+ const sorted = [...rows].sort((a, b) => order.indexOf(a.verdict) - order.indexOf(b.verdict) || a.name.localeCompare(b.name));
626
+ const issues = sorted.filter((row) => row.verdict !== "healthy");
627
+ return {
628
+ issues,
629
+ normal: sorted.filter((row) => row.verdict === "healthy"),
630
+ hasIssues: issues.length > 0
631
+ };
632
+ }
633
+ //#endregion
552
634
  //#region src/client/Panel.ts
553
635
  /**
554
636
  * The panel body: a four-state summary plus the list aggregated BY RULE.
@@ -645,17 +727,8 @@ window.__ModuleLoader__.load({
645
727
  }
646
728
  }, text);
647
729
  }
648
- /** H4: the evidence queue by skill, before the by-rule summary. */
649
- function skillQueue(face, t) {
650
- const order = [
651
- "error",
652
- "needs-restructure",
653
- "warn",
654
- "unreadable",
655
- "healthy"
656
- ];
657
- const rows = [...face.rows].sort((a, b) => order.indexOf(a.verdict) - order.indexOf(b.verdict) || a.name.localeCompare(b.name));
658
- return (0, react.createElement)("div", { "data-role": "skill-queue" }, (0, react.createElement)("h3", { "data-role": "group-title" }, t("group.bySkill")), ...rows.map((row) => (0, react.createElement)("div", {
730
+ function skillRowNode(face, t, row) {
731
+ return (0, react.createElement)("div", {
659
732
  key: row.name,
660
733
  "data-role": "skill-row",
661
734
  "data-tone": row.verdict
@@ -671,7 +744,14 @@ window.__ModuleLoader__.load({
671
744
  t,
672
745
  role: "action-copy",
673
746
  label: t("action.copy")
674
- })))));
747
+ })));
748
+ }
749
+ /** H4: issues first, normal items folded behind one native details summary. */
750
+ function skillQueue(face, t, model) {
751
+ return (0, react.createElement)("div", { "data-role": "skill-queue" }, (0, react.createElement)("h3", { "data-role": "group-title" }, t("group.bySkill")), model.hasIssues ? null : (0, react.createElement)("div", { "data-role": "health-complete" }, t("health.complete")), ...model.issues.map((row) => skillRowNode(face, t, row)), model.normal.length === 0 ? null : (0, react.createElement)("details", {
752
+ "data-role": "health-normal",
753
+ className: "evo-health-normal"
754
+ }, (0, react.createElement)("summary", null, t("health.normal").replace("{n}", String(model.normal.length))), ...model.normal.map((row) => skillRowNode(face, t, row))));
675
755
  }
676
756
  /** The rule table: a grid so counts line up, with a tone bar per row and skill pills. */
677
757
  function ruleTable(face, t) {
@@ -731,6 +811,7 @@ window.__ModuleLoader__.load({
731
811
  const [lastReadAt, setLastReadAt] = (0, react.useState)(face.readAt);
732
812
  const [scan, setScan] = (0, react.useState)(face.scan);
733
813
  const [viewMode, setViewMode] = (0, react.useState)("skills");
814
+ const [verdictFilter, setVerdictFilter] = (0, react.useState)(void 0);
734
815
  const firstLoad = (0, react.useRef)(false);
735
816
  const readTicket = (0, react.useRef)(0);
736
817
  /** One read trigger for first paint and the refresh button; the latest answer wins. */
@@ -771,11 +852,22 @@ window.__ModuleLoader__.load({
771
852
  load();
772
853
  }, [face]);
773
854
  const counts = new Map(KINDS.map((kind) => [kind, view.rows.filter((row) => row.verdict === kind).length]));
774
- const stats = (0, react.createElement)("div", { "data-role": "stats" }, KINDS.map((kind) => (0, react.createElement)("div", {
855
+ const shown = verdictFilter === void 0 ? view : {
856
+ ...view,
857
+ rows: view.rows.filter((row) => row.verdict === verdictFilter)
858
+ };
859
+ const stats = (0, react.createElement)("div", { "data-role": "stats" }, KINDS.map((kind) => (0, react.createElement)("button", {
775
860
  key: kind,
861
+ type: "button",
776
862
  "data-role": "stat",
777
- "data-tone": TONE[kind]
778
- }, (0, react.createElement)("div", { "data-role": "stat-value" }, String(counts.get(kind) ?? 0)), (0, react.createElement)("div", { "data-role": "stat-label" }, t("verdict." + kind)))));
863
+ "data-tone": TONE[kind],
864
+ "aria-pressed": verdictFilter === kind ? "true" : "false",
865
+ "aria-label": t("verdict." + kind),
866
+ disabled: (counts.get(kind) ?? 0) === 0,
867
+ onClick: () => {
868
+ setVerdictFilter((previous) => previous === kind ? void 0 : kind);
869
+ }
870
+ }, (0, react.createElement)("span", { "data-role": "stat-value" }, String(counts.get(kind) ?? 0)), (0, react.createElement)("span", { "data-role": "stat-label" }, t("verdict." + kind)))));
779
871
  return (0, react.createElement)("section", { className: CSS_TAG_ID }, (0, react.createElement)("div", { "data-role": "header" }, (0, react.createElement)("span", { "data-role": "read-at" }, lastReadAt === void 0 ? t("readAt.unknown") : new Date(lastReadAt).toLocaleString()), (0, react.createElement)("span", { "data-role": "scan-status" }, t("scan." + (scan?.status ?? "unavailable"))), (0, react.createElement)("button", {
780
872
  type: "button",
781
873
  "data-role": "refresh",
@@ -834,10 +926,10 @@ window.__ModuleLoader__.load({
834
926
  })(), viewMode === "skills" ? (0, react.createElement)("div", {
835
927
  id: "evo-health-skills",
836
928
  role: "tabpanel"
837
- }, skillQueue(view, t)) : (0, react.createElement)("div", {
929
+ }, skillQueue(shown, t, healthViewModel(shown.rows))) : (0, react.createElement)("div", {
838
930
  id: "evo-health-rules",
839
931
  role: "tabpanel"
840
- }, (0, react.createElement)("h3", { "data-role": "group-title" }, t("group.byRule")), ruleTable(view, t)));
932
+ }, (0, react.createElement)("h3", { "data-role": "group-title" }, t("group.byRule")), ruleTable(shown, t)));
841
933
  }
842
934
  //#endregion
843
935
  //#region src/client/seats.ts
@@ -0,0 +1,15 @@
1
+ /** Pure health reading shape: issues first, normal items folded behind a summary. */
2
+ import type { HealthRow } from './Panel.ts';
3
+ /** The split the health page renders from; counts remain the caller's whole-row facts. */
4
+ export interface HealthViewModel {
5
+ readonly issues: readonly HealthRow[];
6
+ readonly normal: readonly HealthRow[];
7
+ readonly hasIssues: boolean;
8
+ }
9
+ /**
10
+ * Split rows without dropping or inventing a verdict. Unreadable is an issue, never normal.
11
+ * @param rows - all rows in the current projection.
12
+ * @returns issues in severity order and the normal remainder.
13
+ */
14
+ export declare function healthViewModel(rows: readonly HealthRow[]): HealthViewModel;
15
+ //# sourceMappingURL=health-presentation.d.ts.map
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  ]
12
12
  }
13
13
  },
14
- "version": "0.34.0",
14
+ "version": "0.36.0",
15
15
  "publishConfig": {
16
16
  "access": "public"
17
17
  },
@@ -42,18 +42,18 @@
42
42
  "peerDependencies": {
43
43
  "@deepseek-ai/cordis": "^4.0.5",
44
44
  "react": "^18.2.0",
45
- "@lmzhen/dsh-evolution-core": "^0.34.0",
46
- "@lmzhen/dsh-evolution-curator": "^0.34.0"
45
+ "@lmzhen/dsh-evolution-core": "^0.36.0",
46
+ "@lmzhen/dsh-evolution-curator": "^0.36.0"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@deepseek-ai/cordis": "^4.0.5",
50
50
  "@types/react": "~18.3.1",
51
51
  "react": "^18.2.0",
52
- "@lmzhen/dsh-evolution-core": "^0.34.0",
53
- "@lmzhen/dsh-evolution-curator": "^0.34.0"
52
+ "@lmzhen/dsh-evolution-core": "^0.36.0",
53
+ "@lmzhen/dsh-evolution-curator": "^0.36.0"
54
54
  },
55
55
  "dependencies": {
56
- "@lmzhen/dsh-evolution-client-kit": "^0.34.0"
56
+ "@lmzhen/dsh-evolution-client-kit": "^0.36.0"
57
57
  },
58
58
  "engines": {
59
59
  "dsh": ">=0.2.1-rc.2 <0.2.2-0"