@reicek/neataptic-ts 0.1.24 → 0.1.26
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/.github/copilot-instructions.md +11 -0
- package/.github/skills/trace-analyzer-extension/SKILL.md +3 -3
- package/.github/skills/trace-analyzer-extension/assets/extension-checklist.md +1 -1
- package/.github/skills/trace-analyzer-extension/references/analyzer-extension-workflow.md +1 -1
- package/.github/skills/trace-audit-reporting/SKILL.md +3 -3
- package/.github/skills/trace-audit-reporting/references/trace-analysis-workflow.md +1 -1
- package/.github/workflows/ci.yml +3 -3
- package/.github/workflows/deploy-pages.yml +6 -6
- package/.github/workflows/manual_release_pipeline.yml +3 -3
- package/.github/workflows/publish.yml +18 -19
- package/.github/workflows/release_dispatch.yml +3 -3
- package/package.json +26 -20
- package/plans/Flappy_Bird_Folder_Documentation_Pass.md +4 -4
- package/plans/README.md +24 -0
- package/plans/Roadmap.md +62 -40
- package/plans/analyze-trace-solid-split.plans.md +66 -0
- package/plans/architecture-solid-split.plans.md +9 -15
- package/plans/asciiMaze-typescript-repair.plans.md +1 -1
- package/plans/generate-docs-solid-split.plans.md +87 -0
- package/plans/methods-docs.plans.md +25 -1
- package/plans/methods-solid-split.plans.md +14 -14
- package/plans/neat-docs.plans.md +9 -1
- package/plans/neat-test-surface-repair.plans.md +1 -1
- package/plans/render-docs-html-solid-split.plans.md +68 -0
- package/plans/src-no-explicit-any-cleanup.plans.md +1 -1
- package/plans/utils-docs.plans.md +6 -1
- package/scripts/analyze-trace/analyze-trace.analysis.ts +479 -0
- package/scripts/analyze-trace/analyze-trace.constants.ts +35 -0
- package/scripts/analyze-trace/analyze-trace.io.ts +69 -0
- package/scripts/analyze-trace/analyze-trace.report.ts +100 -0
- package/scripts/analyze-trace/analyze-trace.shared.ts +116 -0
- package/scripts/analyze-trace/analyze-trace.ts +45 -0
- package/scripts/analyze-trace/analyze-trace.types.ts +72 -0
- package/scripts/assets/theme.css +80 -23
- package/scripts/copy-examples.ts +239 -0
- package/scripts/export-onnx.ts +223 -0
- package/scripts/generate-bench-tables.ts +378 -37
- package/scripts/generate-docs/generate-docs.constants.ts +107 -0
- package/scripts/generate-docs/generate-docs.order.ts +355 -0
- package/scripts/generate-docs/generate-docs.state.ts +31 -0
- package/scripts/generate-docs/generate-docs.targets.ts +165 -0
- package/scripts/generate-docs/generate-docs.ts +63 -0
- package/scripts/generate-docs/generate-docs.types.ts +112 -0
- package/scripts/generate-docs/output/generate-docs.output.folder-index.utils.ts +167 -0
- package/scripts/generate-docs/output/generate-docs.output.ordering.utils.ts +353 -0
- package/scripts/generate-docs/output/generate-docs.output.readme.utils.ts +420 -0
- package/scripts/generate-docs/output/generate-docs.output.ts +123 -0
- package/scripts/generate-docs/output/generate-docs.output.warnings.utils.ts +219 -0
- package/scripts/generate-docs/symbols/generate-docs.symbols.collection.utils.ts +365 -0
- package/scripts/generate-docs/symbols/generate-docs.symbols.jsdoc.utils.ts +373 -0
- package/scripts/generate-docs/symbols/generate-docs.symbols.normalize.utils.ts +155 -0
- package/scripts/generate-docs/symbols/generate-docs.symbols.render.utils.ts +149 -0
- package/scripts/generate-docs/symbols/generate-docs.symbols.signature.utils.ts +289 -0
- package/scripts/generate-docs/symbols/generate-docs.symbols.ts +11 -0
- package/scripts/mermaid-cli.mjs +102 -22
- package/scripts/mermaid-cli.ts +736 -0
- package/scripts/render-docs-html/render-docs-html.assets.ts +54 -0
- package/scripts/render-docs-html/render-docs-html.mermaid.ts +245 -0
- package/scripts/{render-docs-html.sidebar.ts → render-docs-html/render-docs-html.navigation.ts} +141 -144
- package/scripts/render-docs-html/render-docs-html.pages.ts +333 -0
- package/scripts/render-docs-html/render-docs-html.shared.ts +333 -0
- package/scripts/render-docs-html/render-docs-html.types.ts +42 -0
- package/scripts/render-docs-html.ts +23 -587
- package/scripts/run-docs.ts +238 -0
- package/scripts/write-dist-docs-pkg.ts +40 -0
- package/src/README.md +75 -75
- package/src/architecture/connection/README.md +5 -5
- package/src/architecture/layer/README.md +508 -508
- package/src/architecture/network/README.md +1458 -1458
- package/src/architecture/network/activate/README.md +694 -694
- package/src/architecture/network/bootstrap/README.md +77 -77
- package/src/architecture/network/connect/README.md +74 -74
- package/src/architecture/network/deterministic/README.md +135 -135
- package/src/architecture/network/evolve/README.md +364 -364
- package/src/architecture/network/gating/README.md +130 -130
- package/src/architecture/network/genetic/README.md +399 -399
- package/src/architecture/network/mutate/README.md +897 -897
- package/src/architecture/network/onnx/README.md +720 -720
- package/src/architecture/network/onnx/export/README.md +728 -728
- package/src/architecture/network/onnx/export/layers/README.md +450 -450
- package/src/architecture/network/onnx/import/README.md +618 -618
- package/src/architecture/network/onnx/schema/README.md +32 -32
- package/src/architecture/network/prune/README.md +245 -245
- package/src/architecture/network/remove/README.md +135 -135
- package/src/architecture/network/runtime/README.md +106 -106
- package/src/architecture/network/serialize/README.md +542 -542
- package/src/architecture/network/slab/README.md +608 -608
- package/src/architecture/network/standalone/README.md +212 -212
- package/src/architecture/network/stats/README.md +84 -84
- package/src/architecture/network/topology/README.md +465 -465
- package/src/architecture/network/training/README.md +200 -200
- package/src/architecture/node/README.md +5 -5
- package/src/architecture/nodePool/README.md +14 -14
- package/src/methods/README.md +99 -99
- package/src/methods/activation/README.md +189 -189
- package/src/methods/cost/README.md +131 -131
- package/src/methods/rate/README.md +86 -86
- package/src/multithreading/README.md +77 -77
- package/src/multithreading/workers/browser/README.md +8 -8
- package/src/multithreading/workers/node/README.md +8 -8
- package/src/neat/README.md +148 -148
- package/src/neat/adaptive/README.md +120 -120
- package/src/neat/adaptive/acceptance/README.md +40 -40
- package/src/neat/adaptive/complexity/README.md +137 -137
- package/src/neat/adaptive/core/README.md +197 -197
- package/src/neat/adaptive/lineage/README.md +90 -90
- package/src/neat/adaptive/mutation/README.md +284 -284
- package/src/neat/compat/README.md +43 -43
- package/src/neat/compat/core/README.md +90 -90
- package/src/neat/diversity/README.md +35 -35
- package/src/neat/diversity/core/README.md +88 -88
- package/src/neat/evaluate/README.md +85 -85
- package/src/neat/evaluate/auto-distance/README.md +75 -75
- package/src/neat/evaluate/entropy-compat/README.md +37 -37
- package/src/neat/evaluate/entropy-sharing/README.md +43 -43
- package/src/neat/evaluate/fitness/README.md +23 -23
- package/src/neat/evaluate/novelty/README.md +120 -120
- package/src/neat/evaluate/objectives/README.md +17 -17
- package/src/neat/evaluate/shared/README.md +94 -94
- package/src/neat/evolve/README.md +96 -96
- package/src/neat/evolve/adaptive/README.md +60 -60
- package/src/neat/evolve/objectives/README.md +63 -63
- package/src/neat/evolve/offspring/README.md +56 -56
- package/src/neat/evolve/population/README.md +171 -171
- package/src/neat/evolve/runtime/README.md +79 -79
- package/src/neat/evolve/speciation/README.md +74 -74
- package/src/neat/evolve/warnings/README.md +10 -10
- package/src/neat/export/README.md +114 -114
- package/src/neat/helpers/README.md +50 -50
- package/src/neat/init/README.md +9 -9
- package/src/neat/lineage/core/README.md +101 -101
- package/src/neat/multiobjective/category/README.md +74 -74
- package/src/neat/multiobjective/crowding/README.md +272 -272
- package/src/neat/multiobjective/dominance/README.md +171 -171
- package/src/neat/multiobjective/fronts/README.md +68 -68
- package/src/neat/multiobjective/metrics/README.md +43 -43
- package/src/neat/multiobjective/objectives/README.md +31 -31
- package/src/neat/multiobjective/shared/README.md +27 -27
- package/src/neat/mutation/README.md +97 -97
- package/src/neat/mutation/add-conn/README.md +115 -115
- package/src/neat/mutation/add-node/README.md +126 -126
- package/src/neat/mutation/flow/README.md +149 -149
- package/src/neat/mutation/repair/README.md +185 -185
- package/src/neat/mutation/select/README.md +117 -117
- package/src/neat/mutation/shared/README.md +32 -32
- package/src/neat/objectives/README.md +25 -25
- package/src/neat/objectives/core/README.md +67 -67
- package/src/neat/pruning/README.md +40 -40
- package/src/neat/pruning/core/README.md +171 -171
- package/src/neat/pruning/facade/README.md +32 -32
- package/src/neat/rng/README.md +104 -104
- package/src/neat/rng/core/README.md +137 -137
- package/src/neat/rng/facade/README.md +50 -50
- package/src/neat/selection/README.md +111 -111
- package/src/neat/selection/core/README.md +227 -227
- package/src/neat/selection/facade/README.md +61 -61
- package/src/neat/shared/README.md +163 -163
- package/src/neat/speciation/README.md +31 -31
- package/src/neat/speciation/threshold/README.md +35 -35
- package/src/neat/species/README.md +25 -25
- package/src/neat/species/core/README.md +20 -20
- package/src/neat/species/core/shared/README.md +18 -18
- package/src/neat/species/history/context/README.md +22 -22
- package/src/neat/telemetry/accessors/README.md +58 -58
- package/src/neat/telemetry/exports/README.md +233 -233
- package/src/neat/telemetry/facade/README.md +252 -252
- package/src/neat/telemetry/facade/archive/README.md +57 -57
- package/src/neat/telemetry/facade/buffer/README.md +43 -43
- package/src/neat/telemetry/facade/lineage/README.md +12 -12
- package/src/neat/telemetry/facade/objectives/README.md +44 -44
- package/src/neat/telemetry/facade/runtime/README.md +26 -26
- package/src/neat/telemetry/facade/species/README.md +27 -27
- package/src/neat/telemetry/metrics/README.md +696 -696
- package/src/neat/telemetry/recorder/README.md +57 -57
- package/src/neat/telemetry/types/README.md +32 -32
- package/src/neat/topology-intent/README.md +75 -75
- package/src/utils/README.md +193 -193
- package/test/examples/asciiMaze/browser-entry/README.md +92 -92
- package/test/examples/asciiMaze/dashboardManager/README.md +109 -109
- package/test/examples/asciiMaze/dashboardManager/telemetry/README.md +28 -28
- package/test/examples/asciiMaze/evolutionEngine/README.md +1527 -1527
- package/test/examples/asciiMaze/mazeMovement/README.md +105 -105
- package/test/examples/asciiMaze/mazeMovement/finalization/README.md +16 -16
- package/test/examples/asciiMaze/mazeMovement/policy/README.md +57 -57
- package/test/examples/asciiMaze/mazeMovement/runtime/README.md +52 -52
- package/test/examples/asciiMaze/mazeMovement/shaping/README.md +46 -46
- package/test/examples/flappy_bird/browser-entry/README.md +508 -508
- package/test/examples/flappy_bird/browser-entry/host/README.md +101 -101
- package/test/examples/flappy_bird/browser-entry/host/resize/README.md +144 -144
- package/test/examples/flappy_bird/browser-entry/network-view/README.md +194 -194
- package/test/examples/flappy_bird/browser-entry/playback/README.md +278 -278
- package/test/examples/flappy_bird/browser-entry/playback/background/README.md +129 -129
- package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/README.md +502 -502
- package/test/examples/flappy_bird/browser-entry/playback/frame-render/README.md +139 -139
- package/test/examples/flappy_bird/browser-entry/playback/snapshot/README.md +10 -10
- package/test/examples/flappy_bird/browser-entry/playback/trail/README.md +43 -43
- package/test/examples/flappy_bird/browser-entry/playback/worker-channel/README.md +30 -30
- package/test/examples/flappy_bird/browser-entry/runtime/README.md +59 -59
- package/test/examples/flappy_bird/browser-entry/visualization/README.md +276 -276
- package/test/examples/flappy_bird/browser-entry/worker-channel/README.md +16 -16
- package/test/examples/flappy_bird/constants/README.md +1070 -1070
- package/test/examples/flappy_bird/environment/README.md +22 -22
- package/test/examples/flappy_bird/evaluation/README.md +32 -32
- package/test/examples/flappy_bird/evaluation/rollout/README.md +141 -141
- package/test/examples/flappy_bird/flappy-evolution-worker/README.md +425 -425
- package/test/examples/flappy_bird/simulation-shared/README.md +170 -170
- package/test/examples/flappy_bird/simulation-shared/observation/README.md +109 -109
- package/test/examples/flappy_bird/trainer/README.md +325 -325
- package/test/examples/flappy_bird/trainer/evaluation/README.md +74 -74
- package/scripts/analyze-trace.ts +0 -590
- package/scripts/copy-examples.mjs +0 -114
- package/scripts/export-onnx.mjs +0 -86
- package/scripts/generate-bench-tables.mjs +0 -182
- package/scripts/generate-docs.ts +0 -2900
- package/scripts/write-dist-docs-pkg.mjs +0 -16
|
@@ -14,46 +14,336 @@
|
|
|
14
14
|
* - Gracefully degrades when fields missing (older artifact schema).
|
|
15
15
|
* - Extend later for variance/regression annotation summaries.
|
|
16
16
|
*/
|
|
17
|
-
import fs from 'fs';
|
|
18
|
-
import path from 'path';
|
|
17
|
+
import fs from 'node:fs';
|
|
18
|
+
import path from 'node:path';
|
|
19
19
|
|
|
20
|
+
/** Canonical benchmark artifact consumed by the table generator. */
|
|
21
|
+
const BENCHMARK_ARTIFACT_PATH = path.resolve(
|
|
22
|
+
'test/benchmarks/benchmark.results.json',
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
/** Metrics shown in the variant delta table. */
|
|
26
|
+
const DELTA_METRICS = ['buildMs', 'fwdAvgMs', 'bytesPerConn'] as const;
|
|
27
|
+
|
|
28
|
+
/** Metrics shown in the heap and resident-set table. */
|
|
29
|
+
const HEAP_METRICS = ['heapUsed', 'rss'] as const;
|
|
30
|
+
|
|
31
|
+
/** Full metric set recognized across both current and legacy artifact schemas. */
|
|
32
|
+
const AGGREGATED_METRICS = [...DELTA_METRICS, ...HEAP_METRICS] as const;
|
|
33
|
+
|
|
34
|
+
/** Benchmark variant identifiers emitted by the build-variant suite. */
|
|
35
|
+
type BenchmarkMode = 'src' | 'dist';
|
|
36
|
+
|
|
37
|
+
/** Metric names that participate in src-vs-dist regression comparison. */
|
|
38
|
+
type DeltaMetricName = (typeof DELTA_METRICS)[number];
|
|
39
|
+
|
|
40
|
+
/** Metric names that participate in the heap summary table. */
|
|
41
|
+
type HeapMetricName = (typeof HEAP_METRICS)[number];
|
|
42
|
+
|
|
43
|
+
/** All metric names recognized by the script. */
|
|
44
|
+
type BenchmarkMetricName = (typeof AGGREGATED_METRICS)[number];
|
|
45
|
+
|
|
46
|
+
/** Legacy flat-artifact key names such as `buildMsMean`. */
|
|
47
|
+
type LegacyMeanMetricKey = `${BenchmarkMetricName}Mean`;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Aggregate statistics for one benchmark metric.
|
|
51
|
+
*
|
|
52
|
+
* The current table generator only consumes `mean`, but the wider schema can
|
|
53
|
+
* also carry percentile and spread values that may be used by later reports.
|
|
54
|
+
*/
|
|
20
55
|
interface AggregatedMetric {
|
|
21
|
-
mean
|
|
22
|
-
p50
|
|
23
|
-
p95
|
|
24
|
-
std
|
|
56
|
+
mean?: number;
|
|
57
|
+
p50?: number;
|
|
58
|
+
p95?: number;
|
|
59
|
+
std?: number;
|
|
25
60
|
}
|
|
26
61
|
|
|
27
|
-
/**
|
|
28
|
-
|
|
62
|
+
/**
|
|
63
|
+
* Scenario-level metrics under one size bucket.
|
|
64
|
+
*
|
|
65
|
+
* The script currently reads the `all` scenario, but the normalized shape keeps
|
|
66
|
+
* the scenario layer so future reporting can distinguish specialized runs.
|
|
67
|
+
*/
|
|
68
|
+
type AggregatedScenarioBucket = Partial<
|
|
69
|
+
Record<BenchmarkMetricName, AggregatedMetric>
|
|
70
|
+
>;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Size bucket keyed by scenario name.
|
|
74
|
+
*
|
|
75
|
+
* Example: `1024 -> all -> buildMs -> { mean: ... }`.
|
|
76
|
+
*/
|
|
77
|
+
type AggregatedSizeBucket = Record<
|
|
78
|
+
string,
|
|
79
|
+
AggregatedScenarioBucket | undefined
|
|
80
|
+
> & {
|
|
81
|
+
all?: AggregatedScenarioBucket;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/** Aggregated metrics keyed by benchmark size. */
|
|
85
|
+
type AggregatedModeBucket = Record<string, AggregatedSizeBucket>;
|
|
86
|
+
|
|
87
|
+
/** Fully normalized aggregated results keyed by build variant. */
|
|
88
|
+
interface NormalizedAggregatedResults {
|
|
89
|
+
src: AggregatedModeBucket;
|
|
90
|
+
dist: AggregatedModeBucket;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** Minimal artifact contract needed by this script. */
|
|
94
|
+
interface BenchmarkArtifact {
|
|
95
|
+
aggregated?: unknown;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Legacy array-based aggregated entry shape.
|
|
100
|
+
*
|
|
101
|
+
* Older benchmark artifacts stored one flat record per `(mode, size)` pair
|
|
102
|
+
* using `fooMean` properties instead of the nested scenario bucket structure.
|
|
103
|
+
*/
|
|
104
|
+
interface LegacyAggregatedEntry extends Partial<
|
|
105
|
+
Record<LegacyMeanMetricKey, number>
|
|
106
|
+
> {
|
|
107
|
+
mode: BenchmarkMode;
|
|
108
|
+
size: number | string;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Pads or truncates a value to fixed width for the fenced monospace tables.
|
|
113
|
+
*
|
|
114
|
+
* @param v - Cell value to render.
|
|
115
|
+
* @param w - Target cell width.
|
|
116
|
+
* @returns Fixed-width cell content.
|
|
117
|
+
*/
|
|
118
|
+
function cell(v: string | number | undefined | null, w: number): string {
|
|
29
119
|
const s = String(v ?? '');
|
|
30
120
|
return s.length >= w ? s.slice(0, w) : s + ' '.repeat(w - s.length);
|
|
31
121
|
}
|
|
32
122
|
|
|
33
|
-
/**
|
|
34
|
-
|
|
35
|
-
|
|
123
|
+
/**
|
|
124
|
+
* Formats a numeric value with trimmed trailing zeros.
|
|
125
|
+
*
|
|
126
|
+
* This keeps markdown tables compact without losing the ability to request
|
|
127
|
+
* higher precision for smaller benchmark values.
|
|
128
|
+
*
|
|
129
|
+
* @param n - Candidate numeric value.
|
|
130
|
+
* @param digits - Maximum fixed decimal precision.
|
|
131
|
+
* @returns Formatted number or an empty string when the input is not finite.
|
|
132
|
+
*/
|
|
133
|
+
function fmtNum(n: number | undefined, digits = 4): string {
|
|
134
|
+
if (typeof n !== 'number' || !Number.isFinite(n)) return '';
|
|
36
135
|
return n.toFixed(digits).replace(/0+$/, '').replace(/\.$/, '');
|
|
37
136
|
}
|
|
38
137
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
138
|
+
/**
|
|
139
|
+
* Loads the benchmark artifact from disk.
|
|
140
|
+
*
|
|
141
|
+
* @returns Parsed artifact when present and readable, otherwise `null`.
|
|
142
|
+
*/
|
|
143
|
+
function loadArtifact(): BenchmarkArtifact | null {
|
|
144
|
+
if (!fs.existsSync(BENCHMARK_ARTIFACT_PATH)) {
|
|
145
|
+
console.error(
|
|
146
|
+
'[bench:tables] Artifact not found:',
|
|
147
|
+
BENCHMARK_ARTIFACT_PATH,
|
|
148
|
+
);
|
|
43
149
|
return null;
|
|
44
150
|
}
|
|
151
|
+
|
|
45
152
|
try {
|
|
46
|
-
return JSON.parse(
|
|
47
|
-
|
|
48
|
-
|
|
153
|
+
return JSON.parse(
|
|
154
|
+
fs.readFileSync(BENCHMARK_ARTIFACT_PATH, 'utf8'),
|
|
155
|
+
) as BenchmarkArtifact;
|
|
156
|
+
} catch (error) {
|
|
157
|
+
console.error('[bench:tables] Parse error', error);
|
|
49
158
|
return null;
|
|
50
159
|
}
|
|
51
160
|
}
|
|
52
161
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
162
|
+
/**
|
|
163
|
+
* Normalizes the artifact's aggregated payload into one stable nested shape.
|
|
164
|
+
*
|
|
165
|
+
* The benchmark pipeline has emitted both nested and legacy flat array schemas.
|
|
166
|
+
* Folding both into the same mode/size/scenario/metric structure keeps the
|
|
167
|
+
* table builders simple and resilient.
|
|
168
|
+
*
|
|
169
|
+
* @param artifact - Parsed benchmark artifact.
|
|
170
|
+
* @returns Normalized aggregated result buckets.
|
|
171
|
+
*/
|
|
172
|
+
function normalizeAggregated(
|
|
173
|
+
artifact: BenchmarkArtifact,
|
|
174
|
+
): NormalizedAggregatedResults {
|
|
175
|
+
if (Array.isArray(artifact.aggregated)) {
|
|
176
|
+
return normalizeLegacyAggregated(artifact.aggregated);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (!isRecord(artifact.aggregated)) {
|
|
180
|
+
return createEmptyAggregatedResults();
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return {
|
|
184
|
+
src: normalizeModeBucket(artifact.aggregated.src),
|
|
185
|
+
dist: normalizeModeBucket(artifact.aggregated.dist),
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Converts the older flat array schema into the normalized nested shape.
|
|
191
|
+
*
|
|
192
|
+
* @param rawEntries - Legacy aggregated entries.
|
|
193
|
+
* @returns Normalized aggregated result buckets.
|
|
194
|
+
*/
|
|
195
|
+
function normalizeLegacyAggregated(
|
|
196
|
+
rawEntries: readonly unknown[],
|
|
197
|
+
): NormalizedAggregatedResults {
|
|
198
|
+
const aggregatedResults = createEmptyAggregatedResults();
|
|
199
|
+
|
|
200
|
+
for (const rawEntry of rawEntries) {
|
|
201
|
+
if (!isLegacyAggregatedEntry(rawEntry)) {
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const sizeKey = String(rawEntry.size);
|
|
206
|
+
const scenarioBucket = ensureAllScenarioBucket(
|
|
207
|
+
aggregatedResults[rawEntry.mode],
|
|
208
|
+
sizeKey,
|
|
209
|
+
);
|
|
210
|
+
|
|
211
|
+
for (const metricName of AGGREGATED_METRICS) {
|
|
212
|
+
const meanKey = `${metricName}Mean` as const;
|
|
213
|
+
const meanValue = rawEntry[meanKey];
|
|
214
|
+
if (typeof meanValue === 'number' && Number.isFinite(meanValue)) {
|
|
215
|
+
scenarioBucket[metricName] = { mean: meanValue };
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return aggregatedResults;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Normalizes one top-level mode bucket such as `src` or `dist`.
|
|
225
|
+
*
|
|
226
|
+
* @param rawModeBucket - Unknown raw mode payload.
|
|
227
|
+
* @returns Normalized size buckets.
|
|
228
|
+
*/
|
|
229
|
+
function normalizeModeBucket(rawModeBucket: unknown): AggregatedModeBucket {
|
|
230
|
+
if (!isRecord(rawModeBucket)) {
|
|
231
|
+
return {};
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return Object.fromEntries(
|
|
235
|
+
Object.entries(rawModeBucket).map(([sizeKey, rawSizeBucket]) => [
|
|
236
|
+
sizeKey,
|
|
237
|
+
normalizeSizeBucket(rawSizeBucket),
|
|
238
|
+
]),
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Normalizes one size bucket keyed by scenario names.
|
|
244
|
+
*
|
|
245
|
+
* @param rawSizeBucket - Unknown raw size payload.
|
|
246
|
+
* @returns Normalized scenario buckets.
|
|
247
|
+
*/
|
|
248
|
+
function normalizeSizeBucket(rawSizeBucket: unknown): AggregatedSizeBucket {
|
|
249
|
+
if (!isRecord(rawSizeBucket)) {
|
|
250
|
+
return {};
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return Object.fromEntries(
|
|
254
|
+
Object.entries(rawSizeBucket).map(([scenarioName, rawScenarioBucket]) => [
|
|
255
|
+
scenarioName,
|
|
256
|
+
normalizeScenarioBucket(rawScenarioBucket),
|
|
257
|
+
]),
|
|
258
|
+
) as AggregatedSizeBucket;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Normalizes one scenario bucket keyed by metric name.
|
|
263
|
+
*
|
|
264
|
+
* Invalid or incomplete metric objects are dropped rather than guessed.
|
|
265
|
+
*
|
|
266
|
+
* @param rawScenarioBucket - Unknown raw scenario payload.
|
|
267
|
+
* @returns Normalized metric bucket.
|
|
268
|
+
*/
|
|
269
|
+
function normalizeScenarioBucket(
|
|
270
|
+
rawScenarioBucket: unknown,
|
|
271
|
+
): AggregatedScenarioBucket {
|
|
272
|
+
if (!isRecord(rawScenarioBucket)) {
|
|
273
|
+
return {};
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const normalizedEntries = AGGREGATED_METRICS.flatMap((metricName) => {
|
|
277
|
+
const rawMetric = rawScenarioBucket[metricName];
|
|
278
|
+
if (!isRecord(rawMetric)) {
|
|
279
|
+
return [];
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const meanValue = rawMetric.mean;
|
|
283
|
+
if (typeof meanValue !== 'number' || !Number.isFinite(meanValue)) {
|
|
284
|
+
return [];
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
return [[metricName, { mean: meanValue }] as const];
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
return Object.fromEntries(normalizedEntries) as AggregatedScenarioBucket;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Ensures the `all` scenario exists for one `(mode, size)` pair.
|
|
295
|
+
*
|
|
296
|
+
* @param modeBucket - Normalized mode bucket.
|
|
297
|
+
* @param sizeKey - Size identifier.
|
|
298
|
+
* @returns Mutable `all` scenario bucket.
|
|
299
|
+
*/
|
|
300
|
+
function ensureAllScenarioBucket(
|
|
301
|
+
modeBucket: AggregatedModeBucket,
|
|
302
|
+
sizeKey: string,
|
|
303
|
+
): AggregatedScenarioBucket {
|
|
304
|
+
modeBucket[sizeKey] ??= {};
|
|
305
|
+
modeBucket[sizeKey].all ??= {};
|
|
306
|
+
return modeBucket[sizeKey].all!;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Creates an empty normalized results shell.
|
|
311
|
+
*
|
|
312
|
+
* @returns Empty `src` and `dist` mode buckets.
|
|
313
|
+
*/
|
|
314
|
+
function createEmptyAggregatedResults(): NormalizedAggregatedResults {
|
|
315
|
+
return {
|
|
316
|
+
src: {},
|
|
317
|
+
dist: {},
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Resolves size keys in ascending numeric order.
|
|
323
|
+
*
|
|
324
|
+
* @param aggregatedResults - Normalized aggregated result buckets.
|
|
325
|
+
* @returns Ordered size keys.
|
|
326
|
+
*/
|
|
327
|
+
function resolveOrderedSizes(
|
|
328
|
+
aggregatedResults: NormalizedAggregatedResults,
|
|
329
|
+
): string[] {
|
|
330
|
+
return [...new Set(Object.keys(aggregatedResults.src))].toSorted(
|
|
331
|
+
compareNumericSizeKeys,
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Builds the variant delta table comparing `src` and `dist` means.
|
|
337
|
+
*
|
|
338
|
+
* The result is tuned for markdown fenced blocks rather than GFM pipe tables,
|
|
339
|
+
* which keeps wide benchmark rows easier to scan in docs and pull requests.
|
|
340
|
+
*
|
|
341
|
+
* @param artifact - Parsed benchmark artifact.
|
|
342
|
+
* @returns Monospace markdown table body.
|
|
343
|
+
*/
|
|
344
|
+
function buildVariantDeltaTable(artifact: BenchmarkArtifact): string {
|
|
345
|
+
const aggregatedResults = normalizeAggregated(artifact);
|
|
346
|
+
const orderedSizes = resolveOrderedSizes(aggregatedResults);
|
|
57
347
|
const rows: string[] = [];
|
|
58
348
|
rows.push(
|
|
59
349
|
'Size Metric Src Mean Dist Mean Δ Abs Δ % Flag Result',
|
|
@@ -61,13 +351,10 @@ function buildVariantDeltaTable(artifact: any): string {
|
|
|
61
351
|
rows.push(
|
|
62
352
|
'------ ----------------- ------------- ------------- ------------- ---------- ------------- ------------------------------------------------------------',
|
|
63
353
|
);
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const
|
|
68
|
-
agg.src?.[size]?.all?.[metric];
|
|
69
|
-
const distAgg: AggregatedMetric | undefined =
|
|
70
|
-
agg.dist?.[size]?.all?.[metric];
|
|
354
|
+
for (const size of orderedSizes) {
|
|
355
|
+
for (const metric of DELTA_METRICS) {
|
|
356
|
+
const srcAgg = aggregatedResults.src[size]?.all?.[metric];
|
|
357
|
+
const distAgg = aggregatedResults.dist[size]?.all?.[metric];
|
|
71
358
|
const sMean = srcAgg?.mean;
|
|
72
359
|
const dMean = distAgg?.mean;
|
|
73
360
|
let dAbs: number | undefined;
|
|
@@ -123,10 +410,15 @@ function buildVariantDeltaTable(artifact: any): string {
|
|
|
123
410
|
return rows.join('\n');
|
|
124
411
|
}
|
|
125
412
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
413
|
+
/**
|
|
414
|
+
* Builds the heap and RSS comparison table.
|
|
415
|
+
*
|
|
416
|
+
* @param artifact - Parsed benchmark artifact.
|
|
417
|
+
* @returns Monospace markdown table body.
|
|
418
|
+
*/
|
|
419
|
+
function buildHeapTable(artifact: BenchmarkArtifact): string {
|
|
420
|
+
const aggregatedResults = normalizeAggregated(artifact);
|
|
421
|
+
const orderedSizes = resolveOrderedSizes(aggregatedResults);
|
|
130
422
|
const rows: string[] = [];
|
|
131
423
|
rows.push(
|
|
132
424
|
'Size Metric Src Bytes Dist Bytes Src MB Dist MB Δ Bytes Δ % Note',
|
|
@@ -134,10 +426,10 @@ function buildHeapTable(artifact: any): string {
|
|
|
134
426
|
rows.push(
|
|
135
427
|
'------ -------------- ------------ ------------ --------- --------- ----------- ------- -------------------------------------------------',
|
|
136
428
|
);
|
|
137
|
-
for (const size of
|
|
138
|
-
for (const metric of
|
|
139
|
-
const s =
|
|
140
|
-
const d =
|
|
429
|
+
for (const size of orderedSizes) {
|
|
430
|
+
for (const metric of HEAP_METRICS) {
|
|
431
|
+
const s = aggregatedResults.src[size]?.all?.[metric]?.mean;
|
|
432
|
+
const d = aggregatedResults.dist[size]?.all?.[metric]?.mean;
|
|
141
433
|
if (typeof s !== 'number' || typeof d !== 'number') continue;
|
|
142
434
|
const dBytes = d - s;
|
|
143
435
|
const dPct = s === 0 ? 0 : (dBytes / s) * 100;
|
|
@@ -165,6 +457,55 @@ function buildHeapTable(artifact: any): string {
|
|
|
165
457
|
return rows.join('\n');
|
|
166
458
|
}
|
|
167
459
|
|
|
460
|
+
/**
|
|
461
|
+
* Compares size keys numerically, falling back to lexical comparison.
|
|
462
|
+
*
|
|
463
|
+
* @param left - Left size key.
|
|
464
|
+
* @param right - Right size key.
|
|
465
|
+
* @returns Standard comparator delta.
|
|
466
|
+
*/
|
|
467
|
+
function compareNumericSizeKeys(left: string, right: string): number {
|
|
468
|
+
const leftValue = Number.parseInt(left, 10);
|
|
469
|
+
const rightValue = Number.parseInt(right, 10);
|
|
470
|
+
|
|
471
|
+
if (Number.isNaN(leftValue) || Number.isNaN(rightValue)) {
|
|
472
|
+
return left.localeCompare(right);
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
return leftValue - rightValue || left.localeCompare(right);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* Narrows an unknown value to the legacy flat aggregated entry shape.
|
|
480
|
+
*
|
|
481
|
+
* @param value - Candidate legacy entry.
|
|
482
|
+
* @returns `true` when the value matches the legacy schema.
|
|
483
|
+
*/
|
|
484
|
+
function isLegacyAggregatedEntry(
|
|
485
|
+
value: unknown,
|
|
486
|
+
): value is LegacyAggregatedEntry {
|
|
487
|
+
return (
|
|
488
|
+
isRecord(value) &&
|
|
489
|
+
(value.mode === 'src' || value.mode === 'dist') &&
|
|
490
|
+
(typeof value.size === 'number' || typeof value.size === 'string')
|
|
491
|
+
);
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* Narrows an unknown value to a plain object record.
|
|
496
|
+
*
|
|
497
|
+
* @param value - Candidate value.
|
|
498
|
+
* @returns `true` when the value is a non-array object.
|
|
499
|
+
*/
|
|
500
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
501
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* Runs the artifact load and emits both markdown tables to standard output.
|
|
506
|
+
*
|
|
507
|
+
* @returns Nothing.
|
|
508
|
+
*/
|
|
168
509
|
function main() {
|
|
169
510
|
const artifact = loadArtifact();
|
|
170
511
|
if (!artifact) process.exit(1);
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Centralizes stable docs-generator constants and target definitions.
|
|
3
|
+
*
|
|
4
|
+
* Keeping these values in one file makes it easier to audit what the generator
|
|
5
|
+
* considers a target, a published output root, or an ordering-control file
|
|
6
|
+
* without mixing that policy into traversal or rendering code.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import * as path from 'path';
|
|
10
|
+
|
|
11
|
+
import type { DocsTargetConfig } from './generate-docs.types.js';
|
|
12
|
+
|
|
13
|
+
/** Root docs output directory mirrored into the published docs site. */
|
|
14
|
+
export const DOCS_DIR = path.resolve('docs');
|
|
15
|
+
|
|
16
|
+
/** Default docs target when no CLI or environment override is supplied. */
|
|
17
|
+
export const DEFAULT_DOCS_TARGET = 'src';
|
|
18
|
+
|
|
19
|
+
/** Synthetic symbol name used to store file-level summary content. */
|
|
20
|
+
export const FILE_SUMMARY_SYMBOL_NAME = '__file_summary__';
|
|
21
|
+
|
|
22
|
+
/** Source-file glob used to discover docs-generator inputs. */
|
|
23
|
+
export const SOURCE_FILE_GLOBS = ['**/*.ts'];
|
|
24
|
+
|
|
25
|
+
/** Ignore rules for files that should never become generated docs sources. */
|
|
26
|
+
export const SOURCE_FILE_IGNORE_GLOBS = ['**/*.d.ts'];
|
|
27
|
+
|
|
28
|
+
/** Generated docs landing page file name for the folder index. */
|
|
29
|
+
export const FOLDER_INDEX_FILE_NAME = 'FOLDERS.md';
|
|
30
|
+
|
|
31
|
+
/** Per-directory ordering config file name. */
|
|
32
|
+
export const DOCS_ORDER_CONFIG_FILE_NAME = 'docs.order.json';
|
|
33
|
+
|
|
34
|
+
/** Supported keys accepted inside `docs.order.json`. */
|
|
35
|
+
export const DOCS_ORDER_SUPPORTED_KEYS = [
|
|
36
|
+
'introFile',
|
|
37
|
+
'fileOrder',
|
|
38
|
+
'symbolOrder',
|
|
39
|
+
'folderOrder',
|
|
40
|
+
'hiddenFiles',
|
|
41
|
+
'hiddenSymbols',
|
|
42
|
+
] as const;
|
|
43
|
+
|
|
44
|
+
/** Workspace root used to rewrite absolute ts-morph type paths into repo paths. */
|
|
45
|
+
export const WORKSPACE_ROOT_DIR = path.resolve('.');
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Docs targets supported by the folder README generator.
|
|
49
|
+
*
|
|
50
|
+
* Each target maps one source tree into one published docs tree while keeping
|
|
51
|
+
* any target-specific root README mirroring rules local to the target.
|
|
52
|
+
*/
|
|
53
|
+
export const DOCS_TARGETS: Record<string, DocsTargetConfig> = {
|
|
54
|
+
src: {
|
|
55
|
+
name: 'src',
|
|
56
|
+
sourceDir: path.resolve('src'),
|
|
57
|
+
docsDir: DOCS_DIR,
|
|
58
|
+
rootDocsDir: path.join(DOCS_DIR, 'src'),
|
|
59
|
+
rootReadmeSource: path.resolve('README.md'),
|
|
60
|
+
rootReadmeDestination: path.join(DOCS_DIR, 'README.md'),
|
|
61
|
+
includeFolderIndex: true,
|
|
62
|
+
},
|
|
63
|
+
asciiMaze: {
|
|
64
|
+
name: 'asciiMaze',
|
|
65
|
+
sourceDir: path.resolve('test', 'examples', 'asciiMaze'),
|
|
66
|
+
docsDir: path.join(DOCS_DIR, 'examples', 'asciiMaze', 'docs'),
|
|
67
|
+
rootDocsDir: path.join(DOCS_DIR, 'examples', 'asciiMaze', 'docs'),
|
|
68
|
+
rootReadmeSource: path.resolve(
|
|
69
|
+
'test',
|
|
70
|
+
'examples',
|
|
71
|
+
'asciiMaze',
|
|
72
|
+
'README.md',
|
|
73
|
+
),
|
|
74
|
+
rootReadmeDestination: path.join(
|
|
75
|
+
DOCS_DIR,
|
|
76
|
+
'examples',
|
|
77
|
+
'asciiMaze',
|
|
78
|
+
'docs',
|
|
79
|
+
'README.md',
|
|
80
|
+
),
|
|
81
|
+
excludeRootSourceFiles: true,
|
|
82
|
+
publishedRootDir: path.join(DOCS_DIR, 'examples', 'asciiMaze'),
|
|
83
|
+
preservePublishedEntries: ['index.html'],
|
|
84
|
+
},
|
|
85
|
+
'flappy-bird': {
|
|
86
|
+
name: 'flappy-bird',
|
|
87
|
+
sourceDir: path.resolve('test', 'examples', 'flappy_bird'),
|
|
88
|
+
docsDir: path.join(DOCS_DIR, 'examples', 'flappy_bird', 'docs'),
|
|
89
|
+
rootDocsDir: path.join(DOCS_DIR, 'examples', 'flappy_bird', 'docs'),
|
|
90
|
+
rootReadmeSource: path.resolve(
|
|
91
|
+
'test',
|
|
92
|
+
'examples',
|
|
93
|
+
'flappy_bird',
|
|
94
|
+
'README.md',
|
|
95
|
+
),
|
|
96
|
+
rootReadmeDestination: path.join(
|
|
97
|
+
DOCS_DIR,
|
|
98
|
+
'examples',
|
|
99
|
+
'flappy_bird',
|
|
100
|
+
'docs',
|
|
101
|
+
'README.md',
|
|
102
|
+
),
|
|
103
|
+
excludeRootSourceFiles: true,
|
|
104
|
+
publishedRootDir: path.join(DOCS_DIR, 'examples', 'flappy_bird'),
|
|
105
|
+
preservePublishedEntries: ['index.html'],
|
|
106
|
+
},
|
|
107
|
+
};
|