@reicek/neataptic-ts 0.1.25 → 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.
Files changed (210) hide show
  1. package/.github/copilot-instructions.md +11 -0
  2. package/.github/skills/trace-analyzer-extension/SKILL.md +3 -3
  3. package/.github/skills/trace-analyzer-extension/assets/extension-checklist.md +1 -1
  4. package/.github/skills/trace-analyzer-extension/references/analyzer-extension-workflow.md +1 -1
  5. package/.github/skills/trace-audit-reporting/SKILL.md +3 -3
  6. package/.github/skills/trace-audit-reporting/references/trace-analysis-workflow.md +1 -1
  7. package/package.json +19 -13
  8. package/plans/Flappy_Bird_Folder_Documentation_Pass.md +4 -4
  9. package/plans/README.md +24 -0
  10. package/plans/Roadmap.md +62 -40
  11. package/plans/analyze-trace-solid-split.plans.md +66 -0
  12. package/plans/architecture-solid-split.plans.md +9 -15
  13. package/plans/asciiMaze-typescript-repair.plans.md +1 -1
  14. package/plans/generate-docs-solid-split.plans.md +87 -0
  15. package/plans/methods-docs.plans.md +25 -1
  16. package/plans/methods-solid-split.plans.md +14 -14
  17. package/plans/neat-docs.plans.md +9 -1
  18. package/plans/neat-test-surface-repair.plans.md +1 -1
  19. package/plans/render-docs-html-solid-split.plans.md +68 -0
  20. package/plans/src-no-explicit-any-cleanup.plans.md +1 -1
  21. package/plans/utils-docs.plans.md +6 -1
  22. package/scripts/analyze-trace/analyze-trace.analysis.ts +479 -0
  23. package/scripts/analyze-trace/analyze-trace.constants.ts +35 -0
  24. package/scripts/analyze-trace/analyze-trace.io.ts +69 -0
  25. package/scripts/analyze-trace/analyze-trace.report.ts +100 -0
  26. package/scripts/analyze-trace/analyze-trace.shared.ts +116 -0
  27. package/scripts/analyze-trace/analyze-trace.ts +45 -0
  28. package/scripts/analyze-trace/analyze-trace.types.ts +72 -0
  29. package/scripts/assets/theme.css +80 -23
  30. package/scripts/copy-examples.ts +239 -0
  31. package/scripts/export-onnx.ts +223 -0
  32. package/scripts/generate-bench-tables.ts +378 -37
  33. package/scripts/generate-docs/generate-docs.constants.ts +107 -0
  34. package/scripts/generate-docs/generate-docs.order.ts +355 -0
  35. package/scripts/generate-docs/generate-docs.state.ts +31 -0
  36. package/scripts/generate-docs/generate-docs.targets.ts +165 -0
  37. package/scripts/generate-docs/generate-docs.ts +63 -0
  38. package/scripts/generate-docs/generate-docs.types.ts +112 -0
  39. package/scripts/generate-docs/output/generate-docs.output.folder-index.utils.ts +167 -0
  40. package/scripts/generate-docs/output/generate-docs.output.ordering.utils.ts +353 -0
  41. package/scripts/generate-docs/output/generate-docs.output.readme.utils.ts +420 -0
  42. package/scripts/generate-docs/output/generate-docs.output.ts +123 -0
  43. package/scripts/generate-docs/output/generate-docs.output.warnings.utils.ts +219 -0
  44. package/scripts/generate-docs/symbols/generate-docs.symbols.collection.utils.ts +365 -0
  45. package/scripts/generate-docs/symbols/generate-docs.symbols.jsdoc.utils.ts +373 -0
  46. package/scripts/generate-docs/symbols/generate-docs.symbols.normalize.utils.ts +155 -0
  47. package/scripts/generate-docs/symbols/generate-docs.symbols.render.utils.ts +149 -0
  48. package/scripts/generate-docs/symbols/generate-docs.symbols.signature.utils.ts +289 -0
  49. package/scripts/generate-docs/symbols/generate-docs.symbols.ts +11 -0
  50. package/scripts/mermaid-cli.mjs +102 -22
  51. package/scripts/mermaid-cli.ts +736 -0
  52. package/scripts/render-docs-html/render-docs-html.assets.ts +54 -0
  53. package/scripts/render-docs-html/render-docs-html.mermaid.ts +245 -0
  54. package/scripts/{render-docs-html.sidebar.ts → render-docs-html/render-docs-html.navigation.ts} +141 -144
  55. package/scripts/render-docs-html/render-docs-html.pages.ts +333 -0
  56. package/scripts/render-docs-html/render-docs-html.shared.ts +333 -0
  57. package/scripts/render-docs-html/render-docs-html.types.ts +42 -0
  58. package/scripts/render-docs-html.ts +23 -587
  59. package/scripts/run-docs.ts +238 -0
  60. package/scripts/write-dist-docs-pkg.ts +40 -0
  61. package/src/README.md +75 -75
  62. package/src/architecture/connection/README.md +5 -5
  63. package/src/architecture/layer/README.md +508 -508
  64. package/src/architecture/network/README.md +1458 -1458
  65. package/src/architecture/network/activate/README.md +694 -694
  66. package/src/architecture/network/bootstrap/README.md +77 -77
  67. package/src/architecture/network/connect/README.md +74 -74
  68. package/src/architecture/network/deterministic/README.md +135 -135
  69. package/src/architecture/network/evolve/README.md +364 -364
  70. package/src/architecture/network/gating/README.md +130 -130
  71. package/src/architecture/network/genetic/README.md +399 -399
  72. package/src/architecture/network/mutate/README.md +897 -897
  73. package/src/architecture/network/onnx/README.md +720 -720
  74. package/src/architecture/network/onnx/export/README.md +728 -728
  75. package/src/architecture/network/onnx/export/layers/README.md +450 -450
  76. package/src/architecture/network/onnx/import/README.md +618 -618
  77. package/src/architecture/network/onnx/schema/README.md +32 -32
  78. package/src/architecture/network/prune/README.md +245 -245
  79. package/src/architecture/network/remove/README.md +135 -135
  80. package/src/architecture/network/runtime/README.md +106 -106
  81. package/src/architecture/network/serialize/README.md +542 -542
  82. package/src/architecture/network/slab/README.md +608 -608
  83. package/src/architecture/network/standalone/README.md +212 -212
  84. package/src/architecture/network/stats/README.md +84 -84
  85. package/src/architecture/network/topology/README.md +465 -465
  86. package/src/architecture/network/training/README.md +200 -200
  87. package/src/architecture/node/README.md +5 -5
  88. package/src/architecture/nodePool/README.md +14 -14
  89. package/src/methods/README.md +99 -99
  90. package/src/methods/activation/README.md +189 -189
  91. package/src/methods/cost/README.md +131 -131
  92. package/src/methods/rate/README.md +86 -86
  93. package/src/multithreading/README.md +77 -77
  94. package/src/multithreading/workers/browser/README.md +8 -8
  95. package/src/multithreading/workers/node/README.md +8 -8
  96. package/src/neat/README.md +148 -148
  97. package/src/neat/adaptive/README.md +120 -120
  98. package/src/neat/adaptive/acceptance/README.md +40 -40
  99. package/src/neat/adaptive/complexity/README.md +137 -137
  100. package/src/neat/adaptive/core/README.md +197 -197
  101. package/src/neat/adaptive/lineage/README.md +90 -90
  102. package/src/neat/adaptive/mutation/README.md +284 -284
  103. package/src/neat/compat/README.md +43 -43
  104. package/src/neat/compat/core/README.md +90 -90
  105. package/src/neat/diversity/README.md +35 -35
  106. package/src/neat/diversity/core/README.md +88 -88
  107. package/src/neat/evaluate/README.md +85 -85
  108. package/src/neat/evaluate/auto-distance/README.md +75 -75
  109. package/src/neat/evaluate/entropy-compat/README.md +37 -37
  110. package/src/neat/evaluate/entropy-sharing/README.md +43 -43
  111. package/src/neat/evaluate/fitness/README.md +23 -23
  112. package/src/neat/evaluate/novelty/README.md +120 -120
  113. package/src/neat/evaluate/objectives/README.md +17 -17
  114. package/src/neat/evaluate/shared/README.md +94 -94
  115. package/src/neat/evolve/README.md +96 -96
  116. package/src/neat/evolve/adaptive/README.md +60 -60
  117. package/src/neat/evolve/objectives/README.md +63 -63
  118. package/src/neat/evolve/offspring/README.md +56 -56
  119. package/src/neat/evolve/population/README.md +171 -171
  120. package/src/neat/evolve/runtime/README.md +79 -79
  121. package/src/neat/evolve/speciation/README.md +74 -74
  122. package/src/neat/evolve/warnings/README.md +10 -10
  123. package/src/neat/export/README.md +114 -114
  124. package/src/neat/helpers/README.md +50 -50
  125. package/src/neat/init/README.md +9 -9
  126. package/src/neat/lineage/core/README.md +101 -101
  127. package/src/neat/multiobjective/category/README.md +74 -74
  128. package/src/neat/multiobjective/crowding/README.md +272 -272
  129. package/src/neat/multiobjective/dominance/README.md +171 -171
  130. package/src/neat/multiobjective/fronts/README.md +68 -68
  131. package/src/neat/multiobjective/metrics/README.md +43 -43
  132. package/src/neat/multiobjective/objectives/README.md +31 -31
  133. package/src/neat/multiobjective/shared/README.md +27 -27
  134. package/src/neat/mutation/README.md +97 -97
  135. package/src/neat/mutation/add-conn/README.md +115 -115
  136. package/src/neat/mutation/add-node/README.md +126 -126
  137. package/src/neat/mutation/flow/README.md +149 -149
  138. package/src/neat/mutation/repair/README.md +185 -185
  139. package/src/neat/mutation/select/README.md +117 -117
  140. package/src/neat/mutation/shared/README.md +32 -32
  141. package/src/neat/objectives/README.md +25 -25
  142. package/src/neat/objectives/core/README.md +67 -67
  143. package/src/neat/pruning/README.md +40 -40
  144. package/src/neat/pruning/core/README.md +171 -171
  145. package/src/neat/pruning/facade/README.md +32 -32
  146. package/src/neat/rng/README.md +104 -104
  147. package/src/neat/rng/core/README.md +137 -137
  148. package/src/neat/rng/facade/README.md +50 -50
  149. package/src/neat/selection/README.md +111 -111
  150. package/src/neat/selection/core/README.md +227 -227
  151. package/src/neat/selection/facade/README.md +61 -61
  152. package/src/neat/shared/README.md +163 -163
  153. package/src/neat/speciation/README.md +31 -31
  154. package/src/neat/speciation/threshold/README.md +35 -35
  155. package/src/neat/species/README.md +25 -25
  156. package/src/neat/species/core/README.md +20 -20
  157. package/src/neat/species/core/shared/README.md +18 -18
  158. package/src/neat/species/history/context/README.md +22 -22
  159. package/src/neat/telemetry/accessors/README.md +58 -58
  160. package/src/neat/telemetry/exports/README.md +233 -233
  161. package/src/neat/telemetry/facade/README.md +252 -252
  162. package/src/neat/telemetry/facade/archive/README.md +57 -57
  163. package/src/neat/telemetry/facade/buffer/README.md +43 -43
  164. package/src/neat/telemetry/facade/lineage/README.md +12 -12
  165. package/src/neat/telemetry/facade/objectives/README.md +44 -44
  166. package/src/neat/telemetry/facade/runtime/README.md +26 -26
  167. package/src/neat/telemetry/facade/species/README.md +27 -27
  168. package/src/neat/telemetry/metrics/README.md +696 -696
  169. package/src/neat/telemetry/recorder/README.md +57 -57
  170. package/src/neat/telemetry/types/README.md +32 -32
  171. package/src/neat/topology-intent/README.md +75 -75
  172. package/src/utils/README.md +193 -193
  173. package/test/examples/asciiMaze/browser-entry/README.md +92 -92
  174. package/test/examples/asciiMaze/dashboardManager/README.md +109 -109
  175. package/test/examples/asciiMaze/dashboardManager/telemetry/README.md +28 -28
  176. package/test/examples/asciiMaze/evolutionEngine/README.md +1527 -1527
  177. package/test/examples/asciiMaze/mazeMovement/README.md +105 -105
  178. package/test/examples/asciiMaze/mazeMovement/finalization/README.md +16 -16
  179. package/test/examples/asciiMaze/mazeMovement/policy/README.md +57 -57
  180. package/test/examples/asciiMaze/mazeMovement/runtime/README.md +52 -52
  181. package/test/examples/asciiMaze/mazeMovement/shaping/README.md +46 -46
  182. package/test/examples/flappy_bird/browser-entry/README.md +508 -508
  183. package/test/examples/flappy_bird/browser-entry/host/README.md +101 -101
  184. package/test/examples/flappy_bird/browser-entry/host/resize/README.md +144 -144
  185. package/test/examples/flappy_bird/browser-entry/network-view/README.md +194 -194
  186. package/test/examples/flappy_bird/browser-entry/playback/README.md +278 -278
  187. package/test/examples/flappy_bird/browser-entry/playback/background/README.md +129 -129
  188. package/test/examples/flappy_bird/browser-entry/playback/background/ground-grid/README.md +502 -502
  189. package/test/examples/flappy_bird/browser-entry/playback/frame-render/README.md +139 -139
  190. package/test/examples/flappy_bird/browser-entry/playback/snapshot/README.md +10 -10
  191. package/test/examples/flappy_bird/browser-entry/playback/trail/README.md +43 -43
  192. package/test/examples/flappy_bird/browser-entry/playback/worker-channel/README.md +30 -30
  193. package/test/examples/flappy_bird/browser-entry/runtime/README.md +59 -59
  194. package/test/examples/flappy_bird/browser-entry/visualization/README.md +276 -276
  195. package/test/examples/flappy_bird/browser-entry/worker-channel/README.md +16 -16
  196. package/test/examples/flappy_bird/constants/README.md +1070 -1070
  197. package/test/examples/flappy_bird/environment/README.md +22 -22
  198. package/test/examples/flappy_bird/evaluation/README.md +32 -32
  199. package/test/examples/flappy_bird/evaluation/rollout/README.md +141 -141
  200. package/test/examples/flappy_bird/flappy-evolution-worker/README.md +425 -425
  201. package/test/examples/flappy_bird/simulation-shared/README.md +170 -170
  202. package/test/examples/flappy_bird/simulation-shared/observation/README.md +109 -109
  203. package/test/examples/flappy_bird/trainer/README.md +325 -325
  204. package/test/examples/flappy_bird/trainer/evaluation/README.md +74 -74
  205. package/scripts/analyze-trace.ts +0 -590
  206. package/scripts/copy-examples.mjs +0 -114
  207. package/scripts/export-onnx.mjs +0 -86
  208. package/scripts/generate-bench-tables.mjs +0 -182
  209. package/scripts/generate-docs.ts +0 -2900
  210. package/scripts/write-dist-docs-pkg.mjs +0 -16
@@ -0,0 +1,63 @@
1
+ /*
2
+ * Generates per-folder README.md aggregating exported symbols' JSDoc.
3
+ * - Copies root README.md into docs/ (manual content retained)
4
+ * - Skips generating README for src root (leave top-level README manual)
5
+ * Usage: npm run docs:folders
6
+ *
7
+ * The folder split keeps this file orchestration-only: target resolution,
8
+ * source loading, symbol normalization, and markdown emission each live in a
9
+ * dedicated chapter file below.
10
+ */
11
+ import {
12
+ emitDirectoryDocs,
13
+ emitFolderIndex,
14
+ } from './output/generate-docs.output.js';
15
+ import { createGenerateDocsState } from './generate-docs.state.js';
16
+ import {
17
+ collectDirectorySymbols,
18
+ dedupeDirectorySymbols,
19
+ } from './symbols/generate-docs.symbols.js';
20
+ import {
21
+ initializeDocsTarget,
22
+ loadTargetSourceFiles,
23
+ resolveDocsTarget,
24
+ } from './generate-docs.targets.js';
25
+
26
+ /**
27
+ * Generates docs for the requested target.
28
+ *
29
+ * The script runs in four passes:
30
+ * 1. Resolve and prepare the target output tree.
31
+ * 2. Load source files into the shared ts-morph project.
32
+ * 3. Collect and normalize rendered symbols.
33
+ * 4. Emit directory README files and the optional folder index.
34
+ *
35
+ * @returns Nothing.
36
+ */
37
+ async function main(): Promise<void> {
38
+ const state = createGenerateDocsState();
39
+
40
+ // Step 1: Resolve and prepare the requested target.
41
+ const target = resolveDocsTarget(process.argv.slice(2));
42
+ await initializeDocsTarget(target);
43
+
44
+ // Step 2: Load the target source files.
45
+ const sourceFiles = await loadTargetSourceFiles(state, target);
46
+
47
+ // Step 3: Collect and normalize rendered symbols.
48
+ const directorySymbolMap = collectDirectorySymbols(sourceFiles);
49
+ dedupeDirectorySymbols(directorySymbolMap);
50
+
51
+ // Step 4: Emit README files and the optional folder index.
52
+ await emitDirectoryDocs(state, directorySymbolMap, target);
53
+ if (target.includeFolderIndex) {
54
+ await emitFolderIndex(state, directorySymbolMap, target);
55
+ }
56
+
57
+ console.log(`[docs:${target.name}] Per-folder README generation complete.`);
58
+ }
59
+
60
+ main().catch((error: unknown) => {
61
+ console.error(error);
62
+ process.exit(1);
63
+ });
@@ -0,0 +1,112 @@
1
+ /*
2
+ * Shared contracts for the folder-based docs generator.
3
+ *
4
+ * The split keeps traversal, ordering, and markdown emission in separate
5
+ * modules, so these interfaces act as the small vocabulary that lets those
6
+ * chapters collaborate without reaching into each other's implementation.
7
+ */
8
+
9
+ import type { Project } from 'ts-morph';
10
+
11
+ /**
12
+ * Configures one docs-generation target.
13
+ */
14
+ export interface DocsTargetConfig {
15
+ name: string;
16
+ sourceDir: string;
17
+ docsDir: string;
18
+ rootDocsDir: string;
19
+ rootReadmeSource?: string;
20
+ rootReadmeDestination?: string;
21
+ excludeRootSourceFiles?: boolean;
22
+ includeFolderIndex?: boolean;
23
+ publishedRootDir?: string;
24
+ preservePublishedEntries?: readonly string[];
25
+ }
26
+
27
+ /**
28
+ * Renders one documented parameter description for README output.
29
+ */
30
+ export interface RenderedParameter {
31
+ name: string;
32
+ type?: string;
33
+ doc?: string;
34
+ }
35
+
36
+ /**
37
+ * Stores the normalized docs-ready view of one exported or documented symbol.
38
+ */
39
+ export interface RenderedSymbol {
40
+ kind: string;
41
+ name: string;
42
+ filePath: string;
43
+ parent?: string;
44
+ signature?: string;
45
+ jsdoc: {
46
+ summary?: string;
47
+ description?: string;
48
+ params?: RenderedParameter[];
49
+ returns?: string;
50
+ deprecated?: string;
51
+ examples?: string[];
52
+ };
53
+ }
54
+
55
+ /**
56
+ * Represents one folder inside the generated docs index tree.
57
+ */
58
+ export interface FolderIndexNode {
59
+ name: string;
60
+ path: string;
61
+ sourceDirectoryPath: string;
62
+ children: Map<string, FolderIndexNode>;
63
+ fileCount?: number;
64
+ }
65
+
66
+ /**
67
+ * Captures the supported `docs.order.json` controls for one directory.
68
+ */
69
+ export interface DirectoryDocsOrderConfig {
70
+ introFile?: string;
71
+ fileOrder?: string[];
72
+ symbolOrder?: Record<string, string[]>;
73
+ folderOrder?: string[];
74
+ hiddenFiles?: string[];
75
+ hiddenSymbols?: string[];
76
+ }
77
+
78
+ /**
79
+ * Stores one validated directory-order config plus its source path.
80
+ */
81
+ export interface LoadedDirectoryDocsOrderConfig {
82
+ configPath: string;
83
+ config: DirectoryDocsOrderConfig;
84
+ }
85
+
86
+ /**
87
+ * Represents the promoted file-summary content for a source file.
88
+ */
89
+ export interface RenderedFileSummary {
90
+ description?: string;
91
+ examples?: string[];
92
+ }
93
+
94
+ /**
95
+ * Groups rendered symbols by absolute directory path, then by absolute file path.
96
+ */
97
+ export type DirectorySymbolMap = Map<string, Map<string, RenderedSymbol[]>>;
98
+
99
+ /**
100
+ * Owns mutable state shared across one docs-generation run.
101
+ */
102
+ export interface GenerateDocsState {
103
+ project: Project;
104
+ resolvedDirectoryDocsOrderConfigCache: Map<
105
+ string,
106
+ LoadedDirectoryDocsOrderConfig | undefined
107
+ >;
108
+ directoryDocsOrderConfigCache: Map<
109
+ string,
110
+ Promise<LoadedDirectoryDocsOrderConfig | undefined>
111
+ >;
112
+ }
@@ -0,0 +1,167 @@
1
+ /*
2
+ * Builds the generated folder index markdown for docs output.
3
+ *
4
+ * This chapter owns tree construction and recursive index rendering so the
5
+ * output root can stay focused on orchestrating file writes.
6
+ */
7
+
8
+ import * as path from 'path';
9
+
10
+ import type {
11
+ DirectorySymbolMap,
12
+ DocsTargetConfig,
13
+ FolderIndexNode,
14
+ GenerateDocsState,
15
+ } from '../generate-docs.types.js';
16
+ import {
17
+ resolveSortedFolderIndexChildNames,
18
+ resolveVisibleDirectoryFiles,
19
+ } from './generate-docs.output.ordering.utils.js';
20
+
21
+ /**
22
+ * Builds markdown for the generated folder index.
23
+ *
24
+ * @param state - Shared docs-generator state.
25
+ * @param directorySymbolMap - Normalized directory symbol map.
26
+ * @param target - Target configuration.
27
+ * @returns Folder index markdown.
28
+ */
29
+ export function buildFolderIndexMarkdown(
30
+ state: GenerateDocsState,
31
+ directorySymbolMap: DirectorySymbolMap,
32
+ target: DocsTargetConfig,
33
+ ): string {
34
+ const rootNode: FolderIndexNode = {
35
+ name: 'src',
36
+ path: 'src',
37
+ sourceDirectoryPath: target.sourceDir,
38
+ children: new Map(),
39
+ fileCount: 0,
40
+ };
41
+
42
+ const relativeDirectories = [...directorySymbolMap.keys()]
43
+ .map((directoryPath) => path.relative(target.sourceDir, directoryPath))
44
+ .filter((relativeDirectory) => !relativeDirectory.startsWith('..'));
45
+
46
+ for (const relativeDirectory of relativeDirectories) {
47
+ insertFolderIndexNode(
48
+ state,
49
+ rootNode,
50
+ relativeDirectory,
51
+ target,
52
+ directorySymbolMap,
53
+ );
54
+ }
55
+
56
+ const lines = [
57
+ '# Docs Index',
58
+ '',
59
+ 'Auto-generated index of source folders (click to open folder README).',
60
+ '',
61
+ ];
62
+
63
+ renderFolderIndexNode(state, rootNode, 0, lines);
64
+ return `${lines.join('\n')}\n`;
65
+ }
66
+
67
+ /**
68
+ * Inserts one relative directory into the folder index tree.
69
+ *
70
+ * @param state - Shared docs-generator state.
71
+ * @param rootNode - Root folder index node.
72
+ * @param relativeDirectory - Relative directory from the target source root.
73
+ * @param target - Target configuration.
74
+ * @param directorySymbolMap - Directory symbol map used for file counts.
75
+ * @returns Nothing.
76
+ */
77
+ function insertFolderIndexNode(
78
+ state: GenerateDocsState,
79
+ rootNode: FolderIndexNode,
80
+ relativeDirectory: string,
81
+ target: DocsTargetConfig,
82
+ directorySymbolMap: DirectorySymbolMap,
83
+ ): void {
84
+ const absoluteDirectoryPath = path.join(
85
+ target.sourceDir,
86
+ relativeDirectory === '' ? '' : relativeDirectory,
87
+ );
88
+ const fileSymbolMap = directorySymbolMap.get(absoluteDirectoryPath);
89
+
90
+ if (relativeDirectory === '') {
91
+ if (fileSymbolMap) {
92
+ rootNode.fileCount = resolveVisibleDirectoryFiles(
93
+ state,
94
+ absoluteDirectoryPath,
95
+ [...fileSymbolMap.keys()],
96
+ ).length;
97
+ }
98
+ return;
99
+ }
100
+
101
+ const pathParts = relativeDirectory.replace(/\\/g, '/').split('/');
102
+
103
+ let currentNode = rootNode;
104
+ let accumulatedPath = rootNode.path;
105
+ let accumulatedSourceDirectoryPath = rootNode.sourceDirectoryPath;
106
+
107
+ for (const pathPart of pathParts) {
108
+ accumulatedPath = `${accumulatedPath}/${pathPart}`;
109
+ accumulatedSourceDirectoryPath = path.join(
110
+ accumulatedSourceDirectoryPath,
111
+ pathPart,
112
+ );
113
+
114
+ if (!currentNode.children.has(pathPart)) {
115
+ currentNode.children.set(pathPart, {
116
+ name: pathPart,
117
+ path: accumulatedPath,
118
+ sourceDirectoryPath: accumulatedSourceDirectoryPath,
119
+ children: new Map(),
120
+ });
121
+ }
122
+
123
+ currentNode = currentNode.children.get(pathPart)!;
124
+ }
125
+
126
+ if (fileSymbolMap) {
127
+ currentNode.fileCount = resolveVisibleDirectoryFiles(
128
+ state,
129
+ absoluteDirectoryPath,
130
+ [...fileSymbolMap.keys()],
131
+ ).length;
132
+ }
133
+ }
134
+
135
+ /**
136
+ * Renders one folder index node and its children recursively.
137
+ *
138
+ * @param state - Shared docs-generator state.
139
+ * @param node - Current folder index node.
140
+ * @param level - Nesting level.
141
+ * @param lines - Output line buffer.
142
+ * @returns Nothing.
143
+ */
144
+ function renderFolderIndexNode(
145
+ state: GenerateDocsState,
146
+ node: FolderIndexNode,
147
+ level: number,
148
+ lines: string[],
149
+ ): void {
150
+ const indent = ' '.repeat(Math.max(0, level));
151
+ const label = node.path === 'src' && level === 0 ? 'src (root)' : node.name;
152
+ const countSuffix = node.fileCount
153
+ ? ` — ${node.fileCount} file${node.fileCount > 1 ? 's' : ''}`
154
+ : '';
155
+
156
+ lines.push(`${indent}- [${label}](${node.path}/README.md)${countSuffix}`);
157
+
158
+ const childNames = resolveSortedFolderIndexChildNames(state, node);
159
+ for (const childName of childNames) {
160
+ renderFolderIndexNode(
161
+ state,
162
+ node.children.get(childName)!,
163
+ level + 1,
164
+ lines,
165
+ );
166
+ }
167
+ }
@@ -0,0 +1,353 @@
1
+ /*
2
+ * Resolves ordering and visibility policy for generated output.
3
+ *
4
+ * This chapter folds docs.order.json preferences together with the stable
5
+ * fallback heuristics used to order files, symbols, and folder-index entries.
6
+ */
7
+
8
+ import * as path from 'path';
9
+
10
+ import { FILE_SUMMARY_SYMBOL_NAME } from '../generate-docs.constants.js';
11
+ import { getCachedDirectoryDocsOrderConfig } from '../generate-docs.order.js';
12
+ import type {
13
+ FolderIndexNode,
14
+ GenerateDocsState,
15
+ RenderedSymbol,
16
+ } from '../generate-docs.types.js';
17
+ import {
18
+ warnForUnknownConfiguredDirectoryFiles,
19
+ warnForUnknownConfiguredDirectoryIntroFile,
20
+ warnForUnknownConfiguredFileSectionSymbols,
21
+ warnForUnknownConfiguredFolderIndexChildren,
22
+ warnForUnknownConfiguredHiddenFiles,
23
+ warnForUnknownConfiguredHiddenSymbols,
24
+ } from './generate-docs.output.warnings.utils.js';
25
+
26
+ /**
27
+ * Resolves directory file order using config-first ordering with stable
28
+ * fallback to the existing heuristic rank.
29
+ *
30
+ * After explicit `fileOrder` entries are placed, fallback ranking prefers:
31
+ * index-style entrypoints, files with promoted summaries, non-utility files,
32
+ * type-focused files, then shorter file names before lexical tie-breaks.
33
+ *
34
+ * @param state - Shared docs-generator state.
35
+ * @param directoryPath - Absolute directory path.
36
+ * @param fileSymbolMap - Symbols grouped by file within the directory.
37
+ * @returns Files sorted for one directory README.
38
+ */
39
+ export function resolveSortedDirectoryFiles(
40
+ state: GenerateDocsState,
41
+ directoryPath: string,
42
+ fileSymbolMap: Map<string, RenderedSymbol[]>,
43
+ ): string[] {
44
+ const loadedConfig = getCachedDirectoryDocsOrderConfig(state, directoryPath);
45
+ const configuredFileOrder = loadedConfig?.config.fileOrder;
46
+
47
+ if (configuredFileOrder?.length) {
48
+ warnForUnknownConfiguredDirectoryFiles(
49
+ configuredFileOrder,
50
+ [...fileSymbolMap.keys()],
51
+ loadedConfig?.configPath,
52
+ );
53
+ }
54
+
55
+ const explicitFileOrderIndex = new Map(
56
+ (configuredFileOrder ?? []).map(
57
+ (fileName, index) => [fileName, index] as const,
58
+ ),
59
+ );
60
+
61
+ return [...fileSymbolMap.keys()].toSorted((leftFile, rightFile) => {
62
+ const leftExplicitOrder = explicitFileOrderIndex.get(
63
+ path.basename(leftFile),
64
+ );
65
+ const rightExplicitOrder = explicitFileOrderIndex.get(
66
+ path.basename(rightFile),
67
+ );
68
+
69
+ if (leftExplicitOrder !== undefined || rightExplicitOrder !== undefined) {
70
+ if (leftExplicitOrder === undefined) {
71
+ return 1;
72
+ }
73
+
74
+ if (rightExplicitOrder === undefined) {
75
+ return -1;
76
+ }
77
+
78
+ if (leftExplicitOrder !== rightExplicitOrder) {
79
+ return leftExplicitOrder - rightExplicitOrder;
80
+ }
81
+ }
82
+
83
+ return compareDirectoryReadmeFiles(leftFile, rightFile, fileSymbolMap);
84
+ });
85
+ }
86
+
87
+ /**
88
+ * Resolves visible files for one directory README after applying optional
89
+ * `hiddenFiles` filtering.
90
+ *
91
+ * @param state - Shared docs-generator state.
92
+ * @param directoryPath - Absolute directory path.
93
+ * @param sortedFiles - Already sorted directory files.
94
+ * @returns Visible files that should remain in the generated output.
95
+ */
96
+ export function resolveVisibleDirectoryFiles(
97
+ state: GenerateDocsState,
98
+ directoryPath: string,
99
+ sortedFiles: readonly string[],
100
+ ): string[] {
101
+ const loadedConfig = getCachedDirectoryDocsOrderConfig(state, directoryPath);
102
+ const configuredHiddenFiles = loadedConfig?.config.hiddenFiles;
103
+
104
+ if (configuredHiddenFiles?.length) {
105
+ warnForUnknownConfiguredHiddenFiles(
106
+ configuredHiddenFiles,
107
+ sortedFiles,
108
+ loadedConfig?.configPath,
109
+ );
110
+ }
111
+
112
+ const hiddenFileNames = new Set(configuredHiddenFiles ?? []);
113
+ return sortedFiles.filter(
114
+ (filePath) => !hiddenFileNames.has(path.basename(filePath)),
115
+ );
116
+ }
117
+
118
+ /**
119
+ * Resolves hidden symbol names for one directory README.
120
+ *
121
+ * @param state - Shared docs-generator state.
122
+ * @param directoryPath - Absolute directory path.
123
+ * @param fileSymbolMap - Symbols grouped by file within the directory.
124
+ * @returns Hidden symbol-name set for render-time filtering.
125
+ */
126
+ export function resolveHiddenDirectorySymbolNames(
127
+ state: GenerateDocsState,
128
+ directoryPath: string,
129
+ fileSymbolMap: Map<string, RenderedSymbol[]>,
130
+ ): ReadonlySet<string> {
131
+ const loadedConfig = getCachedDirectoryDocsOrderConfig(state, directoryPath);
132
+ const configuredHiddenSymbols = loadedConfig?.config.hiddenSymbols;
133
+
134
+ if (configuredHiddenSymbols?.length) {
135
+ warnForUnknownConfiguredHiddenSymbols(
136
+ configuredHiddenSymbols,
137
+ fileSymbolMap,
138
+ loadedConfig?.configPath,
139
+ );
140
+ }
141
+
142
+ return new Set(configuredHiddenSymbols ?? []);
143
+ }
144
+
145
+ /**
146
+ * Resolves top-level symbol order for one rendered file section.
147
+ *
148
+ * @param state - Shared docs-generator state.
149
+ * @param filePath - Absolute source file path.
150
+ * @param topLevelSymbols - Stable fallback-sorted top-level symbols.
151
+ * @returns Top-level symbols ordered for rendering.
152
+ */
153
+ export function resolveSortedTopLevelFileSectionSymbols(
154
+ state: GenerateDocsState,
155
+ filePath: string,
156
+ topLevelSymbols: readonly RenderedSymbol[],
157
+ ): RenderedSymbol[] {
158
+ const directoryPath = path.dirname(filePath);
159
+ const loadedConfig = getCachedDirectoryDocsOrderConfig(state, directoryPath);
160
+ const configuredSymbolOrder =
161
+ loadedConfig?.config.symbolOrder?.[path.basename(filePath)];
162
+
163
+ if (!configuredSymbolOrder?.length) {
164
+ return [...topLevelSymbols];
165
+ }
166
+
167
+ warnForUnknownConfiguredFileSectionSymbols(
168
+ configuredSymbolOrder,
169
+ topLevelSymbols,
170
+ loadedConfig?.configPath,
171
+ filePath,
172
+ );
173
+
174
+ const explicitSymbolOrderIndex = new Map(
175
+ configuredSymbolOrder.map(
176
+ (symbolName, index) => [symbolName, index] as const,
177
+ ),
178
+ );
179
+
180
+ return [...topLevelSymbols].toSorted((leftSymbol, rightSymbol) => {
181
+ const leftExplicitOrder = explicitSymbolOrderIndex.get(leftSymbol.name);
182
+ const rightExplicitOrder = explicitSymbolOrderIndex.get(rightSymbol.name);
183
+
184
+ if (leftExplicitOrder !== undefined || rightExplicitOrder !== undefined) {
185
+ if (leftExplicitOrder === undefined) {
186
+ return 1;
187
+ }
188
+
189
+ if (rightExplicitOrder === undefined) {
190
+ return -1;
191
+ }
192
+
193
+ if (leftExplicitOrder !== rightExplicitOrder) {
194
+ return leftExplicitOrder - rightExplicitOrder;
195
+ }
196
+ }
197
+
198
+ return 0;
199
+ });
200
+ }
201
+
202
+ /**
203
+ * Resolves child-folder order for one folder-index node.
204
+ *
205
+ * @param state - Shared docs-generator state.
206
+ * @param node - Folder index node whose children should be ordered.
207
+ * @returns Sorted child folder names.
208
+ */
209
+ export function resolveSortedFolderIndexChildNames(
210
+ state: GenerateDocsState,
211
+ node: FolderIndexNode,
212
+ ): string[] {
213
+ const loadedConfig = getCachedDirectoryDocsOrderConfig(
214
+ state,
215
+ node.sourceDirectoryPath,
216
+ );
217
+ const configuredFolderOrder = loadedConfig?.config.folderOrder;
218
+
219
+ if (configuredFolderOrder?.length) {
220
+ warnForUnknownConfiguredFolderIndexChildren(
221
+ configuredFolderOrder,
222
+ [...node.children.keys()],
223
+ loadedConfig?.configPath,
224
+ node.sourceDirectoryPath,
225
+ );
226
+ }
227
+
228
+ const explicitFolderOrderIndex = new Map(
229
+ (configuredFolderOrder ?? []).map(
230
+ (folderName, index) => [folderName, index] as const,
231
+ ),
232
+ );
233
+
234
+ return [...node.children.keys()].toSorted((leftName, rightName) => {
235
+ const leftExplicitOrder = explicitFolderOrderIndex.get(leftName);
236
+ const rightExplicitOrder = explicitFolderOrderIndex.get(rightName);
237
+
238
+ if (leftExplicitOrder !== undefined || rightExplicitOrder !== undefined) {
239
+ if (leftExplicitOrder === undefined) {
240
+ return 1;
241
+ }
242
+
243
+ if (rightExplicitOrder === undefined) {
244
+ return -1;
245
+ }
246
+
247
+ if (leftExplicitOrder !== rightExplicitOrder) {
248
+ return leftExplicitOrder - rightExplicitOrder;
249
+ }
250
+ }
251
+
252
+ return leftName.localeCompare(rightName);
253
+ });
254
+ }
255
+
256
+ /**
257
+ * Warns when `introFile` references a file missing from the current folder.
258
+ *
259
+ * @param state - Shared docs-generator state.
260
+ * @param directoryPath - Absolute directory path.
261
+ * @param configuredIntroFile - Configured intro file name.
262
+ * @param sortedFiles - Actual files in the current directory README.
263
+ * @returns Nothing.
264
+ */
265
+ export function warnForConfiguredIntroFileIfNeeded(
266
+ state: GenerateDocsState,
267
+ directoryPath: string,
268
+ configuredIntroFile: string,
269
+ sortedFiles: readonly string[],
270
+ ): void {
271
+ const loadedConfig = getCachedDirectoryDocsOrderConfig(state, directoryPath);
272
+ warnForUnknownConfiguredDirectoryIntroFile(
273
+ configuredIntroFile,
274
+ sortedFiles,
275
+ loadedConfig?.configPath,
276
+ );
277
+ }
278
+
279
+ /**
280
+ * Ranks files within a directory README so entrypoints appear before helpers.
281
+ *
282
+ * The goal is not semantic perfection; it is a deterministic educational order
283
+ * that usually reads well for humans when no explicit `docs.order.json`
284
+ * override exists.
285
+ *
286
+ * @param filePath - Absolute source file path.
287
+ * @param fileSymbolMap - Symbols grouped by file within the directory.
288
+ * @returns Sort rank tuple.
289
+ */
290
+ function rankFileForDirectoryReadme(
291
+ filePath: string,
292
+ fileSymbolMap: Map<string, RenderedSymbol[]>,
293
+ ): number[] {
294
+ const fileName = path.basename(filePath).toLowerCase();
295
+ const renderedSymbols = fileSymbolMap.get(filePath) ?? [];
296
+
297
+ const hasFileSummary = renderedSymbols.some((renderedSymbol) => {
298
+ if (
299
+ renderedSymbol.kind !== 'File' ||
300
+ renderedSymbol.name !== FILE_SUMMARY_SYMBOL_NAME
301
+ ) {
302
+ return false;
303
+ }
304
+
305
+ return Boolean(renderedSymbol.jsdoc.description?.trim());
306
+ });
307
+
308
+ const isIndexFile = fileName === 'index.ts';
309
+ const isTypesFile =
310
+ fileName.includes('.types.') || fileName.endsWith('.types.ts');
311
+ const isUtilityLike =
312
+ /(\.utils\.|\.export-|\.import-|\.internal\.|\.private\.)/i.test(fileName);
313
+ const isEntrypointLike = !isUtilityLike;
314
+
315
+ return [
316
+ isIndexFile ? 0 : 1,
317
+ hasFileSummary ? 0 : 1,
318
+ isEntrypointLike ? 0 : 1,
319
+ isTypesFile ? 0 : 1,
320
+ fileName.length,
321
+ ];
322
+ }
323
+
324
+ /**
325
+ * Compares two files using the existing directory README heuristic.
326
+ *
327
+ * @param leftFile - Left file path.
328
+ * @param rightFile - Right file path.
329
+ * @param fileSymbolMap - Symbols grouped by file within the directory.
330
+ * @returns Negative when left sorts before right.
331
+ */
332
+ function compareDirectoryReadmeFiles(
333
+ leftFile: string,
334
+ rightFile: string,
335
+ fileSymbolMap: Map<string, RenderedSymbol[]>,
336
+ ): number {
337
+ const leftRank = rankFileForDirectoryReadme(leftFile, fileSymbolMap);
338
+ const rightRank = rankFileForDirectoryReadme(rightFile, fileSymbolMap);
339
+
340
+ for (
341
+ let index = 0;
342
+ index < Math.max(leftRank.length, rightRank.length);
343
+ index += 1
344
+ ) {
345
+ const leftValue = leftRank[index] ?? 0;
346
+ const rightValue = rightRank[index] ?? 0;
347
+ if (leftValue !== rightValue) {
348
+ return leftValue - rightValue;
349
+ }
350
+ }
351
+
352
+ return leftFile.localeCompare(rightFile);
353
+ }