@cardenelabs/cdl 0.80.0 → 0.81.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/CHANGELOG.md +35 -1
- package/dist/index.cjs +33 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +33 -8
- package/dist/index.js.map +1 -1
- package/dist/react.cjs.map +1 -1
- package/dist/react.js.map +1 -1
- package/package.json +1 -1
- package/src/visual-validate.ts +78 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cardenelabs/cdl",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.81.0",
|
|
4
4
|
"description": "CDL (Chainome Diagram Language). Mermaid-like declarative DSL that compiles to animated SVG diagrams. Built for blockchain / Solidity flows, generic enough for sequence / flow / state / ER / topology diagrams.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "cardene777",
|
package/src/visual-validate.ts
CHANGED
|
@@ -4415,18 +4415,27 @@ export interface SweepReport {
|
|
|
4415
4415
|
profile: ValidationProfile;
|
|
4416
4416
|
/** 用途によって見なかった軸。 `totalCounts` はこれらも 0 を返す。 */
|
|
4417
4417
|
skippedAxes: VisualAxis[];
|
|
4418
|
+
/**
|
|
4419
|
+
* 速さを何で測ったか (`#897`)。
|
|
4420
|
+
*
|
|
4421
|
+
* 超過した時だけ文面に出すと、超過していない周では測り方が分からない。 呼ぶ側が
|
|
4422
|
+
* 「CPU 時間で測れているか」 を常に確かめられるように、超過の有無と切り離して返す。
|
|
4423
|
+
*/
|
|
4424
|
+
perfClock: PerfClockKind;
|
|
4418
4425
|
}
|
|
4419
4426
|
|
|
4420
4427
|
export function visualValidateAll(diagrams: CdlDiagram[], opts?: ValidateOptions): SweepReport {
|
|
4421
4428
|
// **図を 1 枚も持たない呼び出しでも器を確かめる**。 各図の `visualValidate` に任せると、
|
|
4422
4429
|
// 図が 0 枚の掃き出しでは壊れた器が黙って通る (`#797`)。
|
|
4423
4430
|
器を確かめる(opts?.container);
|
|
4424
|
-
// Axis 52 用 = 各 diagram
|
|
4431
|
+
// Axis 52 用 = 各 diagram の検査に掛かった時間 (ms) を計測。 performance budget 超過検知。
|
|
4432
|
+
// 測るのは CPU 時間で、待たされた分は足さない (`perfClock` の doc comment が理由の SSOT)。
|
|
4433
|
+
const 時計 = perfClock();
|
|
4425
4434
|
const durations: number[] = [];
|
|
4426
4435
|
const reports = diagrams.map((d) => {
|
|
4427
|
-
const
|
|
4436
|
+
const 止める = 時計.測る();
|
|
4428
4437
|
const r = visualValidate(d, opts);
|
|
4429
|
-
durations.push(
|
|
4438
|
+
durations.push(止める());
|
|
4430
4439
|
return r;
|
|
4431
4440
|
});
|
|
4432
4441
|
const fail = reports.filter((r) => !r.ok).length;
|
|
@@ -4438,7 +4447,7 @@ export function visualValidateAll(diagrams: CdlDiagram[], opts?: ValidateOptions
|
|
|
4438
4447
|
}
|
|
4439
4448
|
|
|
4440
4449
|
// Axis 47/48/49/50/52 = engine meta 判定
|
|
4441
|
-
const metaViolations = validateMetaAxes(totalCounts, diagrams, durations, reports);
|
|
4450
|
+
const metaViolations = validateMetaAxes(totalCounts, diagrams, durations, reports, 時計.kind);
|
|
4442
4451
|
|
|
4443
4452
|
return {
|
|
4444
4453
|
total: reports.length,
|
|
@@ -4449,6 +4458,7 @@ export function visualValidateAll(diagrams: CdlDiagram[], opts?: ValidateOptions
|
|
|
4449
4458
|
profile: opts?.profile ?? "production",
|
|
4450
4459
|
skippedAxes: [...SKIPPED_AXES[opts?.profile ?? "production"]],
|
|
4451
4460
|
metaViolations,
|
|
4461
|
+
perfClock: 時計.kind,
|
|
4452
4462
|
};
|
|
4453
4463
|
}
|
|
4454
4464
|
|
|
@@ -4468,6 +4478,63 @@ export function visualValidateAll(diagrams: CdlDiagram[], opts?: ValidateOptions
|
|
|
4468
4478
|
/** 全 diagram の検査に掛けてよい合計の時間 (ms)。 */
|
|
4469
4479
|
export const PERF_BUDGET_TOTAL_MS = 5000;
|
|
4470
4480
|
|
|
4481
|
+
/** 時間を何で測ったか。 超過の文面に出して、黙って別の物を測らないようにする。 */
|
|
4482
|
+
export type PerfClockKind = "cpu" | "wall";
|
|
4483
|
+
|
|
4484
|
+
/**
|
|
4485
|
+
* 検査 1 回に掛かった時間を測る道具を作る (`#897`)。
|
|
4486
|
+
*
|
|
4487
|
+
* ## 壁時計は図の性質を測っていない
|
|
4488
|
+
*
|
|
4489
|
+
* 壁時計は **待たされた分も足す**。 使う側の図 599 枚を 3 周する形で測った実測。
|
|
4490
|
+
*
|
|
4491
|
+
* ```
|
|
4492
|
+
* その検査だけを回す (5 回 × 3 周) 335..1739ms
|
|
4493
|
+
* 検査を一式回す (5 回 × 3 周) 806..2468ms
|
|
4494
|
+
* ```
|
|
4495
|
+
*
|
|
4496
|
+
* 同じ入力で 7.4 倍ぶれる。 境の 5000ms に対して最悪 49% なので今は超えないが、図の枚数は
|
|
4497
|
+
* 軸を作った時の 444 枚から 599 枚に増えており、余裕は枚数の増加だけで減る。
|
|
4498
|
+
* 超えると使う側の「3 周とも同じ件数か」 を見る検査が周ごとに落ち、落ちた人が自分の変更を
|
|
4499
|
+
* 疑うことになる (`cardene777/dragon#2526` 実測 = 無関係だと確かめるのに一式を 3 回)。
|
|
4500
|
+
*
|
|
4501
|
+
* ## CPU 時間なら待っている間は増えない
|
|
4502
|
+
*
|
|
4503
|
+
* `process.cpuUsage()` はこの process が使った CPU 時間をマイクロ秒で返す。 同時に他の検査が
|
|
4504
|
+
* 走っていても、待っている間は増えない。 `Date.now()` の 1ms 刻みでは 1 枚あたりがほとんど
|
|
4505
|
+
* 0ms に丸まるため、超過した時に出す「重い順」 の内訳も読めるようになる。
|
|
4506
|
+
*
|
|
4507
|
+
* ## 読めない環境では壁時計に落ちる
|
|
4508
|
+
*
|
|
4509
|
+
* `visualValidateAll` を呼ぶのは検査だけで Node で動くが、browser に持ち込まれた時は
|
|
4510
|
+
* `process` が無い。 **落ちたことを文面に出す** = 測り方が変わったのに同じ顔で報告すると、
|
|
4511
|
+
* 読み手は 2 つの値を同じものとして並べる (`rules/quality.md § 判定できなかったことを値に
|
|
4512
|
+
* 潰さない` と同じ理由)。
|
|
4513
|
+
*/
|
|
4514
|
+
export function perfClock(): { kind: PerfClockKind; 測る: () => () => number } {
|
|
4515
|
+
const cpu = (globalThis as { process?: { cpuUsage?: (v?: unknown) => { user: number; system: number } } })
|
|
4516
|
+
.process?.cpuUsage;
|
|
4517
|
+
if (typeof cpu === "function") {
|
|
4518
|
+
return {
|
|
4519
|
+
kind: "cpu",
|
|
4520
|
+
測る: () => {
|
|
4521
|
+
const 始め = cpu();
|
|
4522
|
+
return () => {
|
|
4523
|
+
const 差 = cpu(始め);
|
|
4524
|
+
return (差.user + 差.system) / 1000;
|
|
4525
|
+
};
|
|
4526
|
+
},
|
|
4527
|
+
};
|
|
4528
|
+
}
|
|
4529
|
+
return {
|
|
4530
|
+
kind: "wall",
|
|
4531
|
+
測る: () => {
|
|
4532
|
+
const 始め = Date.now();
|
|
4533
|
+
return () => Date.now() - 始め;
|
|
4534
|
+
},
|
|
4535
|
+
};
|
|
4536
|
+
}
|
|
4537
|
+
|
|
4471
4538
|
/** 合計が境を超えた時に、内訳として名前を出す図の数。 */
|
|
4472
4539
|
export const PERF_SLOWEST_SAMPLE = 5;
|
|
4473
4540
|
|
|
@@ -4506,10 +4573,12 @@ export const PERF_SLOWEST_SAMPLE = 5;
|
|
|
4506
4573
|
*
|
|
4507
4574
|
* @param durations 図ごとの実行時間 (ms)。 `diagrams` と同じ並び
|
|
4508
4575
|
* @param diagrams 図。 名前を内訳に出すためだけに使う
|
|
4576
|
+
* @param clock 何で測ったか。 渡さない時は文面に出さない (合成した値を測り方つきで語らない)
|
|
4509
4577
|
*/
|
|
4510
4578
|
export function perfBudgetViolations(
|
|
4511
4579
|
durations: readonly number[],
|
|
4512
4580
|
diagrams: readonly { id: string }[] = [],
|
|
4581
|
+
clock?: PerfClockKind,
|
|
4513
4582
|
): Violation[] {
|
|
4514
4583
|
const total = durations.reduce((s, d) => s + d, 0);
|
|
4515
4584
|
if (total <= PERF_BUDGET_TOTAL_MS) return [];
|
|
@@ -4529,7 +4598,9 @@ export function perfBudgetViolations(
|
|
|
4529
4598
|
diagramId: "__meta__",
|
|
4530
4599
|
detail:
|
|
4531
4600
|
`visualValidateAll 全 ${durations.length} 図の累計 ${total}ms > ` +
|
|
4532
|
-
`${PERF_BUDGET_TOTAL_MS}ms budget (重い順 ${内訳})
|
|
4601
|
+
`${PERF_BUDGET_TOTAL_MS}ms budget (重い順 ${内訳})` +
|
|
4602
|
+
// 測り方が変わったのに同じ顔で報告すると、読み手が 2 つの値を同じものとして並べる
|
|
4603
|
+
(clock === undefined ? "" : `、 測り方 ${clock === "cpu" ? "CPU 時間" : "壁時計 (CPU 時間が読めない)"}`),
|
|
4533
4604
|
severity: "warn",
|
|
4534
4605
|
},
|
|
4535
4606
|
];
|
|
@@ -4540,6 +4611,7 @@ function validateMetaAxes(
|
|
|
4540
4611
|
diagrams: CdlDiagram[] = [],
|
|
4541
4612
|
durations: number[] = [],
|
|
4542
4613
|
reports: VisualValidationReport[] = [],
|
|
4614
|
+
clock?: PerfClockKind,
|
|
4543
4615
|
): Violation[] {
|
|
4544
4616
|
const out: Violation[] = [];
|
|
4545
4617
|
|
|
@@ -4566,7 +4638,7 @@ function validateMetaAxes(
|
|
|
4566
4638
|
// 本 axis は 空 (engine 単体で判定材料なし)、 発火経路として先取り。
|
|
4567
4639
|
|
|
4568
4640
|
// ─── Axis 52: validate-performance-budget (validate 実行時間) ───
|
|
4569
|
-
out.push(...perfBudgetViolations(durations, diagrams));
|
|
4641
|
+
out.push(...perfBudgetViolations(durations, diagrams, clock));
|
|
4570
4642
|
|
|
4571
4643
|
// Axis 47: dead axis 検知
|
|
4572
4644
|
// security / migration 系は自然発火なしを許容 (実データに XSS / migration 混入は稀)
|