@lmzhen/dsh-evolution-skill-health 0.32.4 → 0.32.6
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/README.md +4 -19
- package/lib/client.js +158 -97
- package/lib/types/client/index.d.ts +4 -4
- package/lib/types/client/seats.d.ts +1 -1
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -1,24 +1,9 @@
|
|
|
1
1
|
# @lmzhen/dsh-evolution-skill-health
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
让"哪条规则在哪些技能上出现、本次改动新引入了什么"一眼可见。**只读**:不写任何技能、不改任何配置。
|
|
3
|
+
Optional read-only skill-health route and a view inside the shared evolution workbench. The `all` bundle ships it disabled by default.
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
The view projects curator health findings, proposal reports, protection markers, hard-cap hits, and available dimensions such as body size, support files, churn, and stamp density. It reports structural problems and duplicates; it does not repair skills. The by-skill queue is the only skill list; history and copy actions live on each row, and proposal provenance is under a details disclosure.
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
同一个 id 既是 `sidebar.panellist` 的行,也是 keyed `main` 的 key(家族面板契约);
|
|
10
|
-
`label` 由 Kit 以 thunk 提供,跟随语言切换;`order` 取 40 一带(与技能历史相邻)。
|
|
11
|
-
- 三个侧栏面板共用同一份客户端缝和生命周期;业务只提供 Panel/Store/api 和图标。
|
|
7
|
+
Unreadable skills are not presented as healthy. An unavailable scan or proposal read is marked unavailable/truncated rather than returned as a clean empty result. The `references-sprawl` rule is named but its count is suppressed until its threshold is calibrated.
|
|
12
8
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
- **数据**:只经只读通道取引擎结论(`healthView()` 一类的**全量行**:`{ name, verdict, dims, findings }` ✓;读不到的技能以 `unreadable-skill` 呈现,**不沉默** ✓)。
|
|
16
|
-
- **呈现**:总览四态(ok/warn/error/不可读)+ **按规则聚合**的清单 + 与技能历史/技能目录的交叉跳转;
|
|
17
|
-
`line: …`/`line: UNKNOWN` 两态要写清(未知就是未知 ✓)。
|
|
18
|
-
- **不上屏**:**未标定**的阈值(如 `SUPPORT_SPRAWL_FILES`)**只报规则名、不报数字** ✓ —— 口径冻结之前不许把数字给读者 ✓。
|
|
19
|
-
- 客户端半不直接 import 其它插件的值/类型;座位形状由 `client-kit` 的 seam 唯一定义 ✓。
|
|
20
|
-
|
|
21
|
-
## 当前状态
|
|
22
|
-
|
|
23
|
-
**占名已发布**(npm `@lmzhen/dsh-evolution-skill-health`,占位版本 `0.0.0-stage` ✓);本包的 `src/` 内容随后补齐,
|
|
24
|
-
**首次真实内容必须发更高版本** ✓("已发布只能抬版本")。
|
|
9
|
+
The host package owns one GET route. The browser package registers the view into `evolution.workbench.view`; applying fixes requires the relevant curator or skill-management surface, not this view.
|
package/lib/client.js
CHANGED
|
@@ -5,28 +5,24 @@ window.__ModuleLoader__.load({
|
|
|
5
5
|
var exports = module.exports;
|
|
6
6
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
7
|
let react = require("react");
|
|
8
|
-
//#region ../evolution-client-kit/src/
|
|
9
|
-
function interpolate(text, values) {
|
|
10
|
-
if (values === void 0) return text;
|
|
11
|
-
return text.replace(/\{(\w+)\}/g, (_match, key) => String(values[key] ?? ""));
|
|
12
|
-
}
|
|
8
|
+
//#region ../evolution-client-kit/src/workbench-view.ts
|
|
13
9
|
function injectStyles(doc, css, tagId) {
|
|
14
10
|
if (doc === void 0) return () => {};
|
|
15
11
|
doc.querySelector("style[data-plugin-css=\"" + tagId + "\"]")?.remove();
|
|
16
12
|
const tag = doc.createElement("style");
|
|
17
13
|
tag.setAttribute("data-plugin-css", tagId);
|
|
18
14
|
tag.textContent = css;
|
|
19
|
-
doc.head.
|
|
15
|
+
doc.head.appendChild(tag);
|
|
20
16
|
return () => {
|
|
21
17
|
tag.remove();
|
|
22
18
|
};
|
|
23
19
|
}
|
|
24
20
|
/**
|
|
25
|
-
* Register one
|
|
26
|
-
* @param ctx -
|
|
27
|
-
* @param spec -
|
|
21
|
+
* Register one view into `evolution.workbench.view`.
|
|
22
|
+
* @param ctx - client cordis context.
|
|
23
|
+
* @param spec - view identity, copy, styles, component and face factory.
|
|
28
24
|
*/
|
|
29
|
-
function
|
|
25
|
+
function registerWorkbenchView(ctx, spec) {
|
|
30
26
|
const seam = ctx;
|
|
31
27
|
let registered = false;
|
|
32
28
|
ctx.effect(() => {
|
|
@@ -35,12 +31,12 @@ window.__ModuleLoader__.load({
|
|
|
35
31
|
registered = true;
|
|
36
32
|
return dispose;
|
|
37
33
|
} catch (error) {
|
|
38
|
-
ctx.logger.warn(spec.namespace + ":
|
|
34
|
+
ctx.logger.warn(spec.namespace + ": locale refused (" + String(error) + "); the view falls back to the bundle copy");
|
|
39
35
|
return () => {};
|
|
40
36
|
}
|
|
41
37
|
}, spec.namespace + ": locale");
|
|
42
38
|
ctx.effect(() => injectStyles(typeof document === "undefined" ? void 0 : document, spec.styles.css, spec.styles.tagId), spec.namespace + ": styles");
|
|
43
|
-
const fallback = spec.dictionaries
|
|
39
|
+
const fallback = spec.dictionaries.zh;
|
|
44
40
|
const lookup = (key) => {
|
|
45
41
|
const own = fallback[key] ?? key;
|
|
46
42
|
if (!registered) return own;
|
|
@@ -50,19 +46,18 @@ window.__ModuleLoader__.load({
|
|
|
50
46
|
return own;
|
|
51
47
|
}
|
|
52
48
|
};
|
|
53
|
-
const t = (key, values) =>
|
|
54
|
-
|
|
55
|
-
|
|
49
|
+
const t = (key, values) => {
|
|
50
|
+
const template = lookup(key);
|
|
51
|
+
if (values === void 0) return template;
|
|
52
|
+
return template.replace(/\{(\w+)\}/g, (match, slot) => values[slot] === void 0 ? match : String(values[slot]));
|
|
53
|
+
};
|
|
54
|
+
seam.slots.inject("evolution.workbench.view", function* () {
|
|
56
55
|
yield seam.slots.register({
|
|
57
|
-
name: "
|
|
56
|
+
name: "evolution.workbench.view",
|
|
58
57
|
id: spec.id,
|
|
59
58
|
order: spec.order,
|
|
60
|
-
label
|
|
61
|
-
|
|
62
|
-
yield seam.slots.register({
|
|
63
|
-
name: "main",
|
|
64
|
-
key: spec.id,
|
|
65
|
-
inject: () => spec.body(t)
|
|
59
|
+
label: () => t("entry.label"),
|
|
60
|
+
inject: () => spec.face(t)
|
|
66
61
|
}, spec.component);
|
|
67
62
|
});
|
|
68
63
|
}
|
|
@@ -79,7 +74,8 @@ window.__ModuleLoader__.load({
|
|
|
79
74
|
pending: "/api/dsh-evolution/approval/pending",
|
|
80
75
|
preview: "/api/dsh-evolution/approval/preview",
|
|
81
76
|
approve: "/api/dsh-evolution/approval/approve",
|
|
82
|
-
reject: "/api/dsh-evolution/approval/reject"
|
|
77
|
+
reject: "/api/dsh-evolution/approval/reject",
|
|
78
|
+
release: "/api/dsh-evolution/approval/release"
|
|
83
79
|
},
|
|
84
80
|
"skill-history": {
|
|
85
81
|
skills: "/api/dsh-evolution/skill-history/skills",
|
|
@@ -98,8 +94,30 @@ window.__ModuleLoader__.load({
|
|
|
98
94
|
body: "/api/dsh-evolution/merge/body",
|
|
99
95
|
history: "/api/dsh-evolution/merge/history"
|
|
100
96
|
},
|
|
101
|
-
diagnostics: { view: "/api/dsh-evolution/diagnostics" }
|
|
97
|
+
diagnostics: { view: "/api/dsh-evolution/diagnostics" },
|
|
98
|
+
settings: {
|
|
99
|
+
describe: "/api/dsh-evolution/settings/describe",
|
|
100
|
+
mutate: "/api/dsh-evolution/settings/mutate"
|
|
101
|
+
}
|
|
102
102
|
};
|
|
103
|
+
ROUTES.settings.describe;
|
|
104
|
+
ROUTES.settings.mutate;
|
|
105
|
+
Object.freeze({
|
|
106
|
+
status: "unavailable",
|
|
107
|
+
value: void 0,
|
|
108
|
+
user: void 0,
|
|
109
|
+
writable: false,
|
|
110
|
+
base: void 0,
|
|
111
|
+
revision: void 0,
|
|
112
|
+
reason: "transport"
|
|
113
|
+
});
|
|
114
|
+
//#endregion
|
|
115
|
+
//#region ../evolution-client-kit/src/action.ts
|
|
116
|
+
/**
|
|
117
|
+
* Command-only actions. Approval decisions are a separate host API and must never
|
|
118
|
+
* be represented as a copyable command here.
|
|
119
|
+
* @module @lmzhen/dsh-evolution-client-kit
|
|
120
|
+
*/
|
|
103
121
|
//#endregion
|
|
104
122
|
//#region ../evolution-client-kit/src/generated/fallbacks.generated.ts
|
|
105
123
|
/**
|
|
@@ -109,13 +127,14 @@ window.__ModuleLoader__.load({
|
|
|
109
127
|
*/
|
|
110
128
|
const FALLBACKS = {
|
|
111
129
|
approval: { command: "/evolution pending … /evolution approve <id> … /evolution reject <id> … /evolution release <id>" },
|
|
112
|
-
"skill-history": { command: "/evolution
|
|
130
|
+
"skill-history": { command: "/evolution skill undo <name> [--to v<N>](查看:/evolution skill history <name>)" },
|
|
113
131
|
"skill-health": { command: "/evolution skills refresh(健康行:/evolution doctor)" },
|
|
114
132
|
merge: { command: "/evolution merge status / pending / approve <id> / report" },
|
|
115
133
|
diagnostics: {
|
|
116
134
|
command: "/evolution doctor",
|
|
117
135
|
platformCli: "dsh --json /evolution doctor"
|
|
118
|
-
}
|
|
136
|
+
},
|
|
137
|
+
settings: { command: "/evolution policy set <id> <value>(查看:/evolution policy)" }
|
|
119
138
|
};
|
|
120
139
|
//#endregion
|
|
121
140
|
//#region ../evolution-client-kit/src/generated/states.generated.ts
|
|
@@ -316,6 +335,7 @@ window.__ModuleLoader__.load({
|
|
|
316
335
|
"proposal.kept": "保留正文",
|
|
317
336
|
"proposal.warnings": "警告",
|
|
318
337
|
"proposal.copy": "复制命令",
|
|
338
|
+
"proposal.provenance": "生成来源",
|
|
319
339
|
"counts": "{ok} 正常 · {warn} 警告 · {error} 错误 · {unreadable} 不可读",
|
|
320
340
|
"col.skill": "技能",
|
|
321
341
|
"col.findings": "证据",
|
|
@@ -340,8 +360,15 @@ window.__ModuleLoader__.load({
|
|
|
340
360
|
"failure.unmounted": "该功能没有挂载。",
|
|
341
361
|
"failure.server": "读取失败,可以重试。",
|
|
342
362
|
"fallback.hint": "可以改用命令:{command}",
|
|
363
|
+
"failureUnauthorized": "需要登录:重新打开这个页面完成登录后再试。",
|
|
364
|
+
"failureForbidden": "平台拒绝了这个请求(身份不是 owner)。",
|
|
365
|
+
"failureUnmounted": "该功能没有挂载。",
|
|
366
|
+
"failureServer": "读取失败,可以重试。",
|
|
367
|
+
"fallbackHint": "可以改用命令:{command}",
|
|
343
368
|
"action.history": "查看历史",
|
|
344
369
|
"action.copy": "复制命令",
|
|
370
|
+
"copy.copied": "已复制",
|
|
371
|
+
"copy.failed": "复制失败",
|
|
345
372
|
"action.extract": "提取",
|
|
346
373
|
"action.extract.reason": "命令/预览面未就绪,暂不可用。"
|
|
347
374
|
};
|
|
@@ -380,6 +407,7 @@ window.__ModuleLoader__.load({
|
|
|
380
407
|
"proposal.kept": "kept body",
|
|
381
408
|
"proposal.warnings": "warnings",
|
|
382
409
|
"proposal.copy": "Copy command",
|
|
410
|
+
"proposal.provenance": "Provenance",
|
|
383
411
|
"counts": "{ok} ok · {warn} warn · {error} error · {unreadable} unreadable",
|
|
384
412
|
"col.skill": "Skill",
|
|
385
413
|
"col.findings": "Evidence",
|
|
@@ -403,8 +431,15 @@ window.__ModuleLoader__.load({
|
|
|
403
431
|
"failure.unmounted": "This feature is not mounted.",
|
|
404
432
|
"failure.server": "The read failed; you can retry.",
|
|
405
433
|
"fallback.hint": "Command fallback: {command}",
|
|
434
|
+
"failureUnauthorized": "Sign-in is required: reopen this page and sign in, then retry.",
|
|
435
|
+
"failureForbidden": "The platform refused this request (not the owner principal).",
|
|
436
|
+
"failureUnmounted": "This feature is not mounted.",
|
|
437
|
+
"failureServer": "The read failed; you can retry.",
|
|
438
|
+
"fallbackHint": "Command fallback: {command}",
|
|
406
439
|
"action.history": "History",
|
|
407
440
|
"action.copy": "Copy command",
|
|
441
|
+
"copy.copied": "Copied",
|
|
442
|
+
"copy.failed": "Copy failed",
|
|
408
443
|
"action.extract": "Extract",
|
|
409
444
|
"action.extract.reason": "The command/preview surface is not ready yet."
|
|
410
445
|
};
|
|
@@ -443,7 +478,7 @@ window.__ModuleLoader__.load({
|
|
|
443
478
|
":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 }",
|
|
444
479
|
":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); }",
|
|
445
480
|
":where(.dsh-evolution-skill-health [data-role=\"hint\"]) { margin: 0; color: var(--dsw-alias-label-secondary); }",
|
|
446
|
-
":where(.dsh-evolution-skill-health [data-role=\"stats\"]) { display: grid; grid-template-columns: repeat(
|
|
481
|
+
":where(.dsh-evolution-skill-health [data-role=\"stats\"]) { display: grid; grid-template-columns: repeat(auto-fit, minmax(136px, 1fr)); gap: var(--evo-space-8); }",
|
|
447
482
|
":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); }",
|
|
448
483
|
":where(.dsh-evolution-skill-health [data-role=\"stat\"][data-tone=\"ok\"]) { box-shadow: inset 2px 0 0 var(--dsw-alias-state-success-primary); }",
|
|
449
484
|
":where(.dsh-evolution-skill-health [data-role=\"stat\"][data-tone=\"warn\"]) { box-shadow: inset 2px 0 0 var(--dsw-alias-state-warn-primary); }",
|
|
@@ -452,8 +487,20 @@ window.__ModuleLoader__.load({
|
|
|
452
487
|
":where(.dsh-evolution-skill-health [data-role=\"stat-value\"]) { font-size: var(--evo-type-lg); font-variant-numeric: tabular-nums; line-height: 1; }",
|
|
453
488
|
":where(.dsh-evolution-skill-health [data-role=\"stat-label\"]) { color: var(--dsw-alias-label-tertiary); }",
|
|
454
489
|
":where(.dsh-evolution-skill-health [data-role=\"group-title\"]) { margin: 0; font-weight: 500; }",
|
|
455
|
-
":where(.dsh-evolution-skill-health [data-role=\"rule-table\"]) { display:
|
|
456
|
-
":where(.dsh-evolution-skill-health [data-role=\"rule-row\"]) {
|
|
490
|
+
":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; }",
|
|
491
|
+
":where(.dsh-evolution-skill-health [data-role=\"rule-row\"]) { border-top: var(--evo-hairline-width) solid var(--dsw-alias-border-l1); }",
|
|
492
|
+
":where(.dsh-evolution-skill-health [data-role=\"rule-row\"] > th, .dsh-evolution-skill-health [data-role=\"rule-row\"] > td) { padding: var(--evo-space-6) var(--evo-space-10); text-align: left; vertical-align: top; }",
|
|
493
|
+
":where(.dsh-evolution-skill-health [data-role=\"rule-row\"] > th:first-child) { width: minmax(9rem, 13rem); }",
|
|
494
|
+
":where(.dsh-evolution-skill-health [data-role=\"rule-row\"] > th:last-child, .dsh-evolution-skill-health [data-role=\"rule-row\"] > td:last-child) { width: 4rem; text-align: right; }",
|
|
495
|
+
":where(.dsh-evolution-skill-health [data-role=\"rule-row\"][data-tone=\"ok\"]) { box-shadow: inset var(--evo-hairline-marker) 0 0 var(--dsw-alias-state-success-primary); }",
|
|
496
|
+
":where(.dsh-evolution-skill-health [data-role=\"skill-queue\"]) { display: flex; flex-direction: column; gap: var(--evo-space-6); }",
|
|
497
|
+
":where(.dsh-evolution-skill-health [data-role=\"skill-row\"]) { display: grid; grid-template-columns: minmax(8rem, 12rem) 6rem minmax(0, 1fr) auto; gap: var(--evo-space-8); align-items: center; padding: var(--evo-space-6) var(--evo-space-10); border: var(--evo-hairline-width) solid var(--dsw-alias-border-l1); border-radius: var(--evo-radius-control); }",
|
|
498
|
+
":where(.dsh-evolution-skill-health [data-role=\"skill-name\"]) { overflow-wrap: anywhere; font-weight: 500; }",
|
|
499
|
+
":where(.dsh-evolution-skill-health [data-role=\"skill-verdict\"], .dsh-evolution-skill-health [data-role=\"skill-dims\"], .dsh-evolution-skill-health [data-role=\"skill-findings\"]) { color: var(--dsw-alias-label-secondary); font-size: var(--evo-type-xs); }",
|
|
500
|
+
":where(.dsh-evolution-skill-health [data-role=\"skill-row-actions\"]) { display: flex; gap: var(--evo-space-4); }",
|
|
501
|
+
":where(.dsh-evolution-skill-health [data-role=\"proposals\"]) { display: flex; flex-direction: column; gap: var(--evo-space-8); }",
|
|
502
|
+
":where(.dsh-evolution-skill-health [data-role=\"proposal\"]) { 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); }",
|
|
503
|
+
":where(.dsh-evolution-skill-health [data-role=\"proposal\"] p) { margin: var(--evo-space-2) 0; }",
|
|
457
504
|
":where(.dsh-evolution-skill-health [data-role=\"rule-row\"][data-tone=\"warn\"]) { box-shadow: inset var(--evo-hairline-marker) 0 0 var(--dsw-alias-state-warn-primary); }",
|
|
458
505
|
":where(.dsh-evolution-skill-health [data-role=\"rule-row\"][data-tone=\"error\"]) { box-shadow: inset var(--evo-hairline-marker) 0 0 var(--dsw-alias-state-error-primary); }",
|
|
459
506
|
":where(.dsh-evolution-skill-health [data-role=\"rule-row\"][data-tone=\"unreadable\"]) { box-shadow: inset var(--evo-hairline-marker) 0 0 var(--evo-tone-quiet); }",
|
|
@@ -485,6 +532,14 @@ window.__ModuleLoader__.load({
|
|
|
485
532
|
"error",
|
|
486
533
|
"unreadable"
|
|
487
534
|
];
|
|
535
|
+
/** UI tone per verdict; the CSS keys are ok/warn/error/unreadable. */
|
|
536
|
+
const TONE = Object.freeze({
|
|
537
|
+
healthy: "ok",
|
|
538
|
+
warn: "warn",
|
|
539
|
+
"needs-restructure": "warn",
|
|
540
|
+
error: "error",
|
|
541
|
+
unreadable: "unreadable"
|
|
542
|
+
});
|
|
488
543
|
/** One row per rule, with the skills that carry it — the view the report is actually read in. */
|
|
489
544
|
function byRule(rows) {
|
|
490
545
|
const table = /* @__PURE__ */ new Map();
|
|
@@ -516,6 +571,28 @@ window.__ModuleLoader__.load({
|
|
|
516
571
|
}
|
|
517
572
|
return worst;
|
|
518
573
|
}
|
|
574
|
+
/** A copy button that reports the clipboard verdict instead of swallowing it. */
|
|
575
|
+
function CopyButton(props) {
|
|
576
|
+
const [state, setState] = (0, react.useState)("idle");
|
|
577
|
+
const copy = async () => {
|
|
578
|
+
try {
|
|
579
|
+
if (typeof navigator === "undefined" || navigator.clipboard === void 0) throw new Error("clipboard unavailable");
|
|
580
|
+
await navigator.clipboard.writeText(props.command);
|
|
581
|
+
setState("ok");
|
|
582
|
+
} catch {
|
|
583
|
+
setState("fail");
|
|
584
|
+
}
|
|
585
|
+
};
|
|
586
|
+
const text = state === "ok" ? props.t("copy.copied") : state === "fail" ? props.t("copy.failed") : props.label;
|
|
587
|
+
return (0, react.createElement)("button", {
|
|
588
|
+
type: "button",
|
|
589
|
+
"data-role": props.role,
|
|
590
|
+
"data-copy-state": state,
|
|
591
|
+
onClick: () => {
|
|
592
|
+
copy();
|
|
593
|
+
}
|
|
594
|
+
}, text);
|
|
595
|
+
}
|
|
519
596
|
/** H4: the evidence queue by skill, before the by-rule summary. */
|
|
520
597
|
function skillQueue(face, t) {
|
|
521
598
|
const order = [
|
|
@@ -530,52 +607,45 @@ window.__ModuleLoader__.load({
|
|
|
530
607
|
key: row.name,
|
|
531
608
|
"data-role": "skill-row",
|
|
532
609
|
"data-tone": row.verdict
|
|
533
|
-
}, (0, react.createElement)("span", { "data-role": "skill-name" }, row.name), (0, react.createElement)("span", { "data-role": "skill-verdict" }, t("verdict." + row.verdict)), (0, react.createElement)("span", { "data-role": "skill-findings" }, row.findings.length === 0 ? t("findings.none") : row.findings.map((finding) => finding.rule).join(" / ")), (0, react.createElement)("span", { "data-role": "skill-dims" }, t("dims.body") + ": " + String(row.dims?.bodyChars ?? t("dims.unknown")) + " · " + t("dims.support") + ": " + String(row.dims?.supportFiles ?? t("dims.unknown")))))
|
|
610
|
+
}, (0, react.createElement)("span", { "data-role": "skill-name" }, row.name), (0, react.createElement)("span", { "data-role": "skill-verdict" }, t("verdict." + row.verdict)), (0, react.createElement)("span", { "data-role": "skill-findings" }, row.findings.length === 0 ? t("findings.none") : row.findings.map((finding) => finding.rule).join(" / ")), (0, react.createElement)("span", { "data-role": "skill-dims" }, t("dims.body") + ": " + String(row.dims?.bodyChars ?? t("dims.unknown")) + " · " + t("dims.support") + ": " + String(row.dims?.supportFiles ?? t("dims.unknown"))), (0, react.createElement)("span", { "data-role": "skill-row-actions" }, (0, react.createElement)("button", {
|
|
611
|
+
type: "button",
|
|
612
|
+
"data-role": "action-history",
|
|
613
|
+
disabled: face.openHistory === void 0,
|
|
614
|
+
onClick: () => {
|
|
615
|
+
face.openHistory?.(row.name);
|
|
616
|
+
}
|
|
617
|
+
}, t("action.history")), (0, react.createElement)(CopyButton, {
|
|
618
|
+
command: "/evolution skill history " + row.name,
|
|
619
|
+
t,
|
|
620
|
+
role: "action-copy",
|
|
621
|
+
label: t("action.copy")
|
|
622
|
+
})))));
|
|
534
623
|
}
|
|
535
624
|
/** The rule table: a grid so counts line up, with a tone bar per row and skill pills. */
|
|
536
625
|
function ruleTable(face, t) {
|
|
537
626
|
const rows = byRule(face.rows);
|
|
538
|
-
const cell = (role, children, key) => (0, react.createElement)("
|
|
627
|
+
const cell = (role, children, key) => (0, react.createElement)("td", key === void 0 ? { "data-role": role } : {
|
|
539
628
|
"data-role": role,
|
|
540
629
|
key
|
|
541
630
|
}, children);
|
|
542
|
-
return (0, react.createElement)("
|
|
543
|
-
|
|
544
|
-
"data-role
|
|
545
|
-
},
|
|
631
|
+
return (0, react.createElement)("table", { "data-role": "rule-table" }, (0, react.createElement)("thead", null, (0, react.createElement)("tr", { "data-role": "rule-head" }, (0, react.createElement)("th", {
|
|
632
|
+
scope: "col",
|
|
633
|
+
"data-role": "rule-name"
|
|
634
|
+
}, t("col.rule")), (0, react.createElement)("th", {
|
|
635
|
+
scope: "col",
|
|
636
|
+
"data-role": "skills"
|
|
637
|
+
}, t("col.skills")), (0, react.createElement)("th", {
|
|
638
|
+
scope: "col",
|
|
639
|
+
"data-role": "rule-count"
|
|
640
|
+
}, t("col.count")))), (0, react.createElement)("tbody", null, rows.map((entry) => (0, react.createElement)("tr", {
|
|
546
641
|
key: entry.rule,
|
|
547
642
|
"data-role": "rule-row",
|
|
548
|
-
"data-tone": worstVerdict(face, entry.skills)
|
|
643
|
+
"data-tone": TONE[worstVerdict(face, entry.skills)]
|
|
549
644
|
}, cell("rule-name", entry.rule), cell("skills", entry.skills.map((name, i) => (0, react.createElement)("span", {
|
|
550
645
|
"data-role": "skill-pill",
|
|
551
646
|
key: name + ":" + String(i),
|
|
552
647
|
title: name
|
|
553
|
-
}, name))), cell("rule-count", entry.count === 0 ? t("count.notCalibrated") : String(entry.count)))));
|
|
554
|
-
}
|
|
555
|
-
/** Per-skill actions: open history, copy the CLI command, and the disabled extract entry. */
|
|
556
|
-
function skillActions(face, t) {
|
|
557
|
-
const names = [...new Set(face.rows.map((row) => row.name))];
|
|
558
|
-
const copy = (name) => {
|
|
559
|
-
const text = "/evolution skill history " + name;
|
|
560
|
-
if (typeof navigator !== "undefined" && navigator.clipboard !== void 0) navigator.clipboard.writeText(text).catch(() => {});
|
|
561
|
-
};
|
|
562
|
-
return (0, react.createElement)("div", { "data-role": "skill-actions" }, ...names.map((name) => (0, react.createElement)("div", {
|
|
563
|
-
key: name,
|
|
564
|
-
"data-role": "skill-action-row"
|
|
565
|
-
}, (0, react.createElement)("span", { "data-role": "skill-action-name" }, name), (0, react.createElement)("button", {
|
|
566
|
-
type: "button",
|
|
567
|
-
"data-role": "action-history",
|
|
568
|
-
disabled: face.openHistory === void 0,
|
|
569
|
-
onClick: () => {
|
|
570
|
-
face.openHistory?.(name);
|
|
571
|
-
}
|
|
572
|
-
}, t("action.history")), (0, react.createElement)("button", {
|
|
573
|
-
type: "button",
|
|
574
|
-
"data-role": "action-copy",
|
|
575
|
-
onClick: () => {
|
|
576
|
-
copy(name);
|
|
577
|
-
}
|
|
578
|
-
}, t("action.copy")))));
|
|
648
|
+
}, name))), cell("rule-count", entry.count === 0 ? t("count.notCalibrated") : String(entry.count))))));
|
|
579
649
|
}
|
|
580
650
|
/**
|
|
581
651
|
* Render the panel.
|
|
@@ -628,6 +698,7 @@ window.__ModuleLoader__.load({
|
|
|
628
698
|
});
|
|
629
699
|
setLastReadAt(payload.readAt);
|
|
630
700
|
setScan(payload.scan);
|
|
701
|
+
setFailed(void 0);
|
|
631
702
|
} else setFailed(outcome.failure);
|
|
632
703
|
}).catch(() => {
|
|
633
704
|
if (live) setFailed({
|
|
@@ -646,7 +717,7 @@ window.__ModuleLoader__.load({
|
|
|
646
717
|
const stats = (0, react.createElement)("div", { "data-role": "stats" }, KINDS.map((kind) => (0, react.createElement)("div", {
|
|
647
718
|
key: kind,
|
|
648
719
|
"data-role": "stat",
|
|
649
|
-
"data-tone": kind
|
|
720
|
+
"data-tone": TONE[kind]
|
|
650
721
|
}, (0, react.createElement)("div", { "data-role": "stat-value" }, String(counts.get(kind) ?? 0)), (0, react.createElement)("div", { "data-role": "stat-label" }, t("verdict." + kind)))));
|
|
651
722
|
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", {
|
|
652
723
|
type: "button",
|
|
@@ -655,22 +726,20 @@ window.__ModuleLoader__.load({
|
|
|
655
726
|
onClick: () => {
|
|
656
727
|
load();
|
|
657
728
|
}
|
|
658
|
-
}, t("refresh"))), (0, react.createElement)("p", { "data-role": "hint" }, t("hint")), stats, loading ? (0, react.createElement)("p", { "data-role": "note" }, t("loading")) : null, view.truncated ? (0, react.createElement)("p", { "data-role": "note" }, t("scan.truncated")) : null, failed === void 0 ? null : (0, react.createElement)("div", { "data-role": "note" }, failureBlock(t, failed)), view.loaded === true && view.rows.length === 0 ? (0, react.createElement)("p", { "data-role": "note" }, t("empty.noneReported")) : null, view.proposalStatus === "unavailable" && (view.proposals ?? []).length === 0 ? (0, react.createElement)("p", { "data-role": "note" }, t("proposal.unavailable")) : null, (view.proposals ?? []).length > 0 ? (0, react.createElement)("div", { "data-role": "proposals" }, (0, react.createElement)("h3", { "data-role": "group-title" }, t("group.proposals")), ...(view.proposals ?? []).map((proposal) => {
|
|
729
|
+
}, t("refresh"))), (0, react.createElement)("p", { "data-role": "hint" }, t("hint")), loading || failed !== void 0 || scan?.status === "unavailable" ? null : stats, loading ? (0, react.createElement)("p", { "data-role": "note" }, t("loading")) : null, view.truncated ? (0, react.createElement)("p", { "data-role": "note" }, t("scan.truncated")) : null, failed === void 0 ? null : (0, react.createElement)("div", { "data-role": "note" }, failureBlock(t, failed)), view.loaded === true && view.rows.length === 0 ? (0, react.createElement)("p", { "data-role": "note" }, t("empty.noneReported")) : null, view.proposalStatus === "unavailable" && (view.proposals ?? []).length === 0 ? (0, react.createElement)("p", { "data-role": "note" }, t("proposal.unavailable")) : null, (view.proposals ?? []).length > 0 ? (0, react.createElement)("div", { "data-role": "proposals" }, (0, react.createElement)("h3", { "data-role": "group-title" }, t("group.proposals")), ...(view.proposals ?? []).map((proposal) => {
|
|
659
730
|
const heading = proposal.parts?.[0]?.heading;
|
|
660
731
|
const target = proposal.owner.mode === "covered" ? proposal.owner.name : proposal.owner.neededOwner;
|
|
661
732
|
const command = heading === void 0 || target === void 0 ? void 0 : "/evolution extract " + proposal.source + " " + target + " \"" + heading + "\" --plan";
|
|
662
|
-
const copyCommand = () => {
|
|
663
|
-
if (command !== void 0 && typeof navigator !== "undefined" && navigator.clipboard !== void 0) navigator.clipboard.writeText(command).catch(() => {});
|
|
664
|
-
};
|
|
665
733
|
return (0, react.createElement)("div", {
|
|
666
734
|
key: proposal.id,
|
|
667
735
|
"data-role": "proposal"
|
|
668
|
-
}, (0, react.createElement)("p", { "data-role": "proposal-summary" }, proposal.source + " — " + t("proposal.outcome." + proposal.outcome) + " · " + (proposal.owner.mode === "covered" ? t("proposal.owner.covered") + (proposal.owner.name === void 0 ? "" : ": " + proposal.owner.name) : t("proposal.owner.owner-gap") + (proposal.owner.neededOwner === void 0 ? "" : ": " + proposal.owner.neededOwner))), (0, react.createElement)("p", { "data-role": "proposal-status" }, t("proposal.status." + proposal.status)), proposal.provenance === void 0 ? null : (0, react.createElement)("
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
736
|
+
}, (0, react.createElement)("p", { "data-role": "proposal-summary" }, proposal.source + " — " + t("proposal.outcome." + proposal.outcome) + " · " + (proposal.owner.mode === "covered" ? t("proposal.owner.covered") + (proposal.owner.name === void 0 ? "" : ": " + proposal.owner.name) : t("proposal.owner.owner-gap") + (proposal.owner.neededOwner === void 0 ? "" : ": " + proposal.owner.neededOwner))), (0, react.createElement)("p", { "data-role": "proposal-status" }, t("proposal.status." + proposal.status)), proposal.provenance === void 0 ? null : (0, react.createElement)("details", { "data-role": "proposal-provenance" }, (0, react.createElement)("summary", null, t("proposal.provenance")), (0, react.createElement)("p", null, proposal.provenance.promptVersion + (proposal.provenance.model === void 0 ? "" : " · " + proposal.provenance.model) + " · " + proposal.provenance.runId + " · " + new Date(proposal.provenance.at).toLocaleString() + (proposal.provenance.promptHash === void 0 ? "" : " · #" + proposal.provenance.promptHash.slice(0, 8)))), proposal.residual === void 0 || proposal.residual.trim() === "" ? null : (0, react.createElement)("p", { "data-role": "proposal-kept" }, t("proposal.kept") + ": " + proposal.residual.trim().slice(0, 160)), (proposal.parts ?? []).length === 0 ? null : (0, react.createElement)("p", { "data-role": "proposal-reusable" }, t("proposal.reusable") + ": " + (proposal.parts ?? []).map((part) => part.heading).join("、")), (proposal.warnings ?? []).length === 0 ? null : (0, react.createElement)("p", { "data-role": "proposal-warnings" }, t("proposal.warnings") + ": " + (proposal.warnings ?? []).join(";")), command === void 0 ? null : (0, react.createElement)("p", { "data-role": "proposal-command" }, (0, react.createElement)("code", {}, command), (0, react.createElement)(CopyButton, {
|
|
737
|
+
command,
|
|
738
|
+
t,
|
|
739
|
+
role: "proposal-copy",
|
|
740
|
+
label: t("proposal.copy")
|
|
741
|
+
})));
|
|
742
|
+
})) : null, skillQueue(view, t), (0, react.createElement)("h3", { "data-role": "group-title" }, t("group.byRule")), ruleTable(view, t), view.rows.filter((row) => row.verdict === "unreadable").map((row) => (0, react.createElement)("p", {
|
|
674
743
|
key: row.name + ":unreadable",
|
|
675
744
|
"data-role": "note"
|
|
676
745
|
}, row.name + " — " + t("unreadable.note"))), view.rows.filter((row) => row.protection !== void 0 && row.protection !== null).map((row) => (0, react.createElement)("p", {
|
|
@@ -685,38 +754,31 @@ window.__ModuleLoader__.load({
|
|
|
685
754
|
if (ctx.slots === void 0) throw new Error("skill-health: the client slots seat is not mounted");
|
|
686
755
|
}
|
|
687
756
|
/** The one place the panel crosses into the platform layout seat. */
|
|
688
|
-
function openSkillHistory(ctx) {
|
|
689
|
-
ctx.layout.
|
|
757
|
+
function openSkillHistory(ctx, name) {
|
|
758
|
+
ctx.layout.openPage("evolution.workbench", name === void 0 ? { view: "history" } : {
|
|
759
|
+
view: "history",
|
|
760
|
+
skillName: name
|
|
761
|
+
});
|
|
690
762
|
}
|
|
691
763
|
//#endregion
|
|
692
764
|
//#region src/client/index.ts
|
|
693
|
-
/** Required client services: the slot registry and
|
|
765
|
+
/** Required client services: the slot registry, locale seat and page navigation. */
|
|
694
766
|
const inject = [
|
|
695
767
|
"slots",
|
|
696
768
|
"locale",
|
|
697
769
|
"layout"
|
|
698
770
|
];
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
return
|
|
702
|
-
"aria-hidden": "true",
|
|
703
|
-
width: String(size),
|
|
704
|
-
height: String(size),
|
|
705
|
-
viewBox: "0 0 16 16",
|
|
706
|
-
fill: "none",
|
|
707
|
-
stroke: "currentColor",
|
|
708
|
-
strokeWidth: "1.5",
|
|
709
|
-
strokeLinecap: "round",
|
|
710
|
-
strokeLinejoin: "round"
|
|
711
|
-
}, (0, react.createElement)("path", { d: "M2 8h3l1.5-3.5L9 11.5 10.5 8H14" }));
|
|
771
|
+
/** The view component receives the workbench's activeView marker alongside its face. */
|
|
772
|
+
function HealthView(props) {
|
|
773
|
+
return props.activeView === "health" ? SkillHealthPanel(props) : null;
|
|
712
774
|
}
|
|
713
775
|
/**
|
|
714
|
-
* Register the
|
|
715
|
-
* @param ctx - the client context; it must carry the
|
|
776
|
+
* Register the health view on the workbench page.
|
|
777
|
+
* @param ctx - the client context; it must carry the seats above.
|
|
716
778
|
*/
|
|
717
779
|
function apply(ctx) {
|
|
718
780
|
requireHealthSeats(ctx);
|
|
719
|
-
|
|
781
|
+
registerWorkbenchView(ctx, {
|
|
720
782
|
id: PANEL_ID,
|
|
721
783
|
order: 40,
|
|
722
784
|
namespace: NS,
|
|
@@ -728,17 +790,16 @@ window.__ModuleLoader__.load({
|
|
|
728
790
|
css: CSS,
|
|
729
791
|
tagId: CSS_TAG_ID
|
|
730
792
|
},
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
body: (t) => ({
|
|
793
|
+
component: HealthView,
|
|
794
|
+
face: (t) => ({
|
|
734
795
|
rows: [],
|
|
735
796
|
proposals: [],
|
|
736
797
|
truncated: false,
|
|
737
798
|
loaded: false,
|
|
738
799
|
proposalStatus: "unavailable",
|
|
739
800
|
loadRows: rows,
|
|
740
|
-
openHistory: () => {
|
|
741
|
-
openSkillHistory(ctx);
|
|
801
|
+
openHistory: (name) => {
|
|
802
|
+
openSkillHistory(ctx, name);
|
|
742
803
|
},
|
|
743
804
|
t
|
|
744
805
|
})
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Browser half:
|
|
2
|
+
* Browser half: the health view inside the shared evolution workbench.
|
|
3
3
|
* @module @lmzhen/dsh-evolution-skill-health/client
|
|
4
4
|
*/
|
|
5
5
|
import type { Context as ClientContext } from '@deepseek-ai/cordis';
|
|
6
6
|
import { PANEL_ID, PANEL_ORDER } from './ids.ts';
|
|
7
7
|
import { type HealthFace } from './Panel.ts';
|
|
8
|
-
/** Required client services: the slot registry and
|
|
8
|
+
/** Required client services: the slot registry, locale seat and page navigation. */
|
|
9
9
|
export declare const inject: string[];
|
|
10
10
|
/** The host half hands the panel a way to read its rows (a read-only route on the host side). */
|
|
11
11
|
export type HealthFaceLoader = () => Promise<HealthFace>;
|
|
12
12
|
export { PANEL_ID, PANEL_ORDER };
|
|
13
13
|
/**
|
|
14
|
-
* Register the
|
|
15
|
-
* @param ctx - the client context; it must carry the
|
|
14
|
+
* Register the health view on the workbench page.
|
|
15
|
+
* @param ctx - the client context; it must carry the seats above.
|
|
16
16
|
*/
|
|
17
17
|
export declare function apply(ctx: ClientContext): void;
|
|
18
18
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -2,5 +2,5 @@ import type { Context as ClientContext } from '@deepseek-ai/cordis';
|
|
|
2
2
|
/** Fail loud when the injected client seats are absent, instead of leaving a PENDING row. */
|
|
3
3
|
export declare function requireHealthSeats(ctx: ClientContext): void;
|
|
4
4
|
/** The one place the panel crosses into the platform layout seat. */
|
|
5
|
-
export declare function openSkillHistory(ctx: ClientContext): void;
|
|
5
|
+
export declare function openSkillHistory(ctx: ClientContext, name?: string): void;
|
|
6
6
|
//# sourceMappingURL=seats.d.ts.map
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
]
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
|
-
"version": "0.32.
|
|
14
|
+
"version": "0.32.6",
|
|
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.32.
|
|
46
|
-
"@lmzhen/dsh-evolution-curator": "^0.32.
|
|
45
|
+
"@lmzhen/dsh-evolution-core": "^0.32.6",
|
|
46
|
+
"@lmzhen/dsh-evolution-curator": "^0.32.6"
|
|
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.32.
|
|
53
|
-
"@lmzhen/dsh-evolution-curator": "^0.32.
|
|
52
|
+
"@lmzhen/dsh-evolution-core": "^0.32.6",
|
|
53
|
+
"@lmzhen/dsh-evolution-curator": "^0.32.6"
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
|
-
"@lmzhen/dsh-evolution-client-kit": "^0.32.
|
|
56
|
+
"@lmzhen/dsh-evolution-client-kit": "^0.32.6"
|
|
57
57
|
},
|
|
58
58
|
"engines": {
|
|
59
59
|
"dsh": ">=0.2.1-rc.2 <0.2.2-0"
|