patram 0.11.0 → 0.12.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.
Files changed (110) hide show
  1. package/bin/patram.js +4 -4
  2. package/lib/cli/commands/fields.js +0 -4
  3. package/lib/cli/commands/queries.js +10 -20
  4. package/lib/cli/commands/query.js +1 -8
  5. package/lib/cli/commands/refs.js +3 -10
  6. package/lib/cli/commands/show.js +1 -8
  7. package/lib/cli/help-metadata.js +71 -106
  8. package/lib/cli/main.js +10 -10
  9. package/lib/cli/parse-arguments-helpers.js +165 -59
  10. package/lib/cli/parse-arguments.js +4 -4
  11. package/lib/cli/render-help.js +2 -2
  12. package/lib/config/defaults.js +33 -25
  13. package/lib/config/load-patram-config.d.ts +8 -33
  14. package/lib/config/load-patram-config.js +9 -33
  15. package/lib/config/load-patram-config.types.d.ts +3 -40
  16. package/lib/config/manage-stored-queries-helpers.d.ts +4 -4
  17. package/lib/config/manage-stored-queries-helpers.js +91 -33
  18. package/lib/config/manage-stored-queries.d.ts +4 -4
  19. package/lib/config/manage-stored-queries.js +11 -5
  20. package/lib/config/patram-config.d.ts +34 -34
  21. package/lib/config/patram-config.js +3 -3
  22. package/lib/config/patram-config.types.d.ts +5 -11
  23. package/lib/config/resolve-patram-graph-config.d.ts +5 -1
  24. package/lib/config/resolve-patram-graph-config.js +3 -119
  25. package/lib/config/schema.d.ts +158 -269
  26. package/lib/config/schema.js +72 -210
  27. package/lib/config/validate-patram-config-value.js +6 -31
  28. package/lib/config/validation.d.ts +2 -12
  29. package/lib/config/validation.js +125 -483
  30. package/lib/find-close-match.d.ts +4 -1
  31. package/lib/graph/build-graph-identity.d.ts +1 -32
  32. package/lib/graph/build-graph-identity.js +5 -269
  33. package/lib/graph/build-graph.d.ts +13 -4
  34. package/lib/graph/build-graph.js +347 -488
  35. package/lib/graph/build-graph.types.d.ts +8 -9
  36. package/lib/graph/check-directive-metadata-helpers.d.ts +30 -0
  37. package/lib/graph/check-directive-metadata-helpers.js +126 -0
  38. package/lib/graph/check-directive-metadata.d.ts +8 -9
  39. package/lib/graph/check-directive-metadata.js +70 -561
  40. package/lib/graph/check-directive-path-target.d.ts +6 -13
  41. package/lib/graph/check-directive-path-target.js +26 -57
  42. package/lib/graph/check-directive-value.d.ts +1 -5
  43. package/lib/graph/check-directive-value.js +40 -180
  44. package/lib/graph/check-graph.d.ts +5 -5
  45. package/lib/graph/check-graph.js +8 -6
  46. package/lib/graph/document-node-identity.d.ts +23 -7
  47. package/lib/graph/document-node-identity.js +417 -160
  48. package/lib/graph/graph-node.d.ts +42 -0
  49. package/lib/graph/graph-node.js +83 -0
  50. package/lib/graph/inspect-reverse-references.js +16 -11
  51. package/lib/graph/load-project-graph.d.ts +7 -7
  52. package/lib/graph/load-project-graph.js +7 -7
  53. package/lib/graph/parse-where-clause.types.d.ts +3 -2
  54. package/lib/graph/query/cypher-reader.d.ts +59 -0
  55. package/lib/graph/query/cypher-reader.js +151 -0
  56. package/lib/graph/query/cypher-support.d.ts +79 -0
  57. package/lib/graph/query/cypher-support.js +213 -0
  58. package/lib/graph/query/cypher-tokenize.d.ts +13 -0
  59. package/lib/graph/query/cypher-tokenize.js +225 -0
  60. package/lib/graph/query/cypher.types.d.ts +43 -0
  61. package/lib/graph/query/execute.d.ts +7 -7
  62. package/lib/graph/query/execute.js +71 -33
  63. package/lib/graph/query/inspect.js +58 -24
  64. package/lib/graph/query/parse-cypher-patterns.d.ts +27 -0
  65. package/lib/graph/query/parse-cypher-patterns.js +382 -0
  66. package/lib/graph/query/parse-cypher.d.ts +7 -0
  67. package/lib/graph/query/parse-cypher.js +580 -0
  68. package/lib/graph/query/parse-query.d.ts +13 -0
  69. package/lib/graph/query/parse-query.js +97 -0
  70. package/lib/graph/query/resolve.js +77 -23
  71. package/lib/output/command-output.js +12 -5
  72. package/lib/output/compact-layout.js +221 -0
  73. package/lib/output/format-output-item-block.js +31 -1
  74. package/lib/output/format-output-metadata.js +16 -29
  75. package/lib/output/format-stored-query-block.js +95 -0
  76. package/lib/output/layout-incoming-references.js +101 -19
  77. package/lib/output/layout-stored-queries.js +23 -330
  78. package/lib/output/list-queries.js +1 -1
  79. package/lib/output/render-field-discovery.js +11 -2
  80. package/lib/output/render-output-view.js +9 -5
  81. package/lib/output/renderers/json.js +5 -26
  82. package/lib/output/renderers/plain.js +155 -35
  83. package/lib/output/renderers/rich.js +250 -36
  84. package/lib/output/resolved-link-layout.js +43 -0
  85. package/lib/output/rich-source/render.js +193 -35
  86. package/lib/output/show-document.js +25 -18
  87. package/lib/output/view-model/index.js +124 -103
  88. package/lib/parse/jsdoc/parse-jsdoc-blocks.js +1 -1
  89. package/lib/parse/jsdoc/parse-jsdoc-claims.js +12 -6
  90. package/lib/parse/markdown/parse-markdown-claims.js +99 -62
  91. package/lib/parse/markdown/parse-markdown-directives.d.ts +10 -6
  92. package/lib/parse/markdown/parse-markdown-directives.js +104 -18
  93. package/lib/parse/markdown/parse-markdown-prose.d.ts +27 -0
  94. package/lib/parse/markdown/parse-markdown-prose.js +243 -0
  95. package/lib/parse/parse-claims.d.ts +2 -6
  96. package/lib/parse/parse-claims.js +11 -53
  97. package/lib/parse/tagged-fenced/tagged-fenced-blocks.d.ts +4 -4
  98. package/lib/parse/tagged-fenced/tagged-fenced-blocks.js +4 -4
  99. package/lib/parse/yaml/parse-yaml-claims.js +4 -4
  100. package/lib/patram.d.ts +3 -5
  101. package/lib/patram.js +1 -1
  102. package/lib/scan/discover-fields.js +194 -55
  103. package/lib/scan/list-source-files.d.ts +4 -4
  104. package/lib/scan/list-source-files.js +4 -4
  105. package/package.json +1 -1
  106. package/lib/directive-validation-test-helpers.js +0 -87
  107. package/lib/graph/query/parse.d.ts +0 -75
  108. package/lib/graph/query/parse.js +0 -1064
  109. package/lib/output/derived-summary.js +0 -280
  110. package/lib/output/format-derived-summary-row.js +0 -9
@@ -1,19 +1,24 @@
1
1
  /**
2
2
  * @import { BuildGraphResult, GraphNode } from '../../graph/build-graph.types.ts';
3
- * @import { DerivedSummaryEvaluator } from '../derived-summary.js';
4
3
  * @import { PatramRepoConfig } from '../../config/load-patram-config.types.ts';
5
- * @import { OutputDerivedSummary, OutputMetadataField, OutputNodeItem, OutputResolvedLinkItem, OutputResolvedLinkTarget, OutputStoredQueryItem, OutputView, RefsOutputView, ShowOutputView } from '../output-view.types.ts';
4
+ * @import { OutputMetadataField, OutputNodeItem, OutputResolvedLinkItem, OutputResolvedLinkTarget, OutputStoredQueryItem, OutputView, RefsOutputView, ShowOutputView } from '../output-view.types.ts';
6
5
  */
7
6
  /* eslint-disable max-lines */
8
7
 
9
8
  import { resolveDocumentNodeId } from '../../graph/build-graph-identity.js';
9
+ import {
10
+ getGraphNodeClassName,
11
+ getGraphNodeId,
12
+ getGraphNodeMetadataValue,
13
+ getGraphNodePath,
14
+ } from '../../graph/graph-node.js';
10
15
 
11
16
  /**
12
17
  * Create a shared output view from one command result.
13
18
  *
14
19
  * @param {'query' | 'queries'} command_name
15
20
  * @param {GraphNode[] | { name: string, where: string, description?: string }[]} command_items
16
- * @param {{ derived_summary_evaluator?: DerivedSummaryEvaluator, hints?: string[], limit?: number, offset?: number, repo_config?: PatramRepoConfig, total_count?: number }=} command_options
21
+ * @param {{ hints?: string[], limit?: number, offset?: number, repo_config?: PatramRepoConfig, total_count?: number }=} command_options
17
22
  * @returns {OutputView}
18
23
  */
19
24
  export function createOutputView(command_name, command_items, command_options) {
@@ -37,7 +42,7 @@ export function createOutputView(command_name, command_items, command_options) {
37
42
  * Create a shared output view for the show command.
38
43
  *
39
44
  * @param {{ incoming_summary: Record<string, number>, path: string, rendered_source: string, resolved_links: Array<{ label: string, reference: number, target: { kind?: string, path: string, status?: string, title: string } }>, source: string }} show_output
40
- * @param {{ derived_summary_evaluator?: DerivedSummaryEvaluator, document_node_ids?: BuildGraphResult['document_node_ids'], graph_nodes?: BuildGraphResult['nodes'], repo_config?: PatramRepoConfig }=} command_options
45
+ * @param {{ document_path_ids?: BuildGraphResult['document_path_ids'], graph_nodes?: BuildGraphResult['nodes'], repo_config?: PatramRepoConfig }=} command_options
41
46
  * @returns {ShowOutputView}
42
47
  */
43
48
  export function createShowOutputView(show_output, command_options = {}) {
@@ -62,7 +67,7 @@ export function createShowOutputView(show_output, command_options = {}) {
62
67
  * Create a shared output view for the refs command.
63
68
  *
64
69
  * @param {{ incoming: Record<string, GraphNode[]>, node: GraphNode }} refs_output
65
- * @param {{ derived_summary_evaluator?: DerivedSummaryEvaluator, repo_config?: PatramRepoConfig }=} command_options
70
+ * @param {{ repo_config?: PatramRepoConfig }=} command_options
66
71
  * @returns {RefsOutputView}
67
72
  */
68
73
  export function createRefsOutputView(refs_output, command_options = {}) {
@@ -74,8 +79,6 @@ export function createRefsOutputView(refs_output, command_options = {}) {
74
79
  (graph_node) =>
75
80
  createOutputNodeItem(
76
81
  graph_node,
77
- command_options.derived_summary_evaluator?.evaluate(graph_node) ??
78
- null,
79
82
  command_options.repo_config?.fields ?? {},
80
83
  ),
81
84
  );
@@ -87,8 +90,6 @@ export function createRefsOutputView(refs_output, command_options = {}) {
87
90
  incoming,
88
91
  node: createOutputNodeItem(
89
92
  refs_output.node,
90
- command_options.derived_summary_evaluator?.evaluate(refs_output.node) ??
91
- null,
92
93
  command_options.repo_config?.fields ?? {},
93
94
  ),
94
95
  summary: {
@@ -100,7 +101,7 @@ export function createRefsOutputView(refs_output, command_options = {}) {
100
101
 
101
102
  /**
102
103
  * @param {GraphNode[]} graph_nodes
103
- * @param {{ derived_summary_evaluator?: DerivedSummaryEvaluator, hints?: string[], limit?: number, offset?: number, repo_config?: PatramRepoConfig, total_count?: number }=} command_options
104
+ * @param {{ hints?: string[], limit?: number, offset?: number, repo_config?: PatramRepoConfig, total_count?: number }=} command_options
104
105
  * @returns {OutputView}
105
106
  */
106
107
  function createQueryOutputView(graph_nodes, command_options = {}) {
@@ -110,11 +111,12 @@ function createQueryOutputView(graph_nodes, command_options = {}) {
110
111
  command: 'query',
111
112
  hints:
112
113
  command_options.hints ??
113
- (total_count === 0 ? ["Try: patram query --where '$class=task'"] : []),
114
+ (total_count === 0
115
+ ? ['Try: patram query --cypher "MATCH (n:Task) RETURN n"']
116
+ : []),
114
117
  items: graph_nodes.map((graph_node) =>
115
118
  createOutputNodeItem(
116
119
  graph_node,
117
- command_options.derived_summary_evaluator?.evaluate(graph_node) ?? null,
118
120
  command_options.repo_config?.fields ?? {},
119
121
  ),
120
122
  ),
@@ -166,11 +168,13 @@ function countIncomingReferenceItems(incoming) {
166
168
 
167
169
  /**
168
170
  * @param {GraphNode} graph_node
169
- * @param {OutputDerivedSummary | null} derived_summary
170
171
  * @param {NonNullable<PatramRepoConfig['fields']>} field_definitions
171
172
  * @returns {OutputNodeItem}
172
173
  */
173
- function createOutputNodeItem(graph_node, derived_summary, field_definitions) {
174
+ function createOutputNodeItem(graph_node, field_definitions) {
175
+ const description = getScalarGraphNodeField(
176
+ getGraphNodeMetadataValue(graph_node, 'description'),
177
+ );
174
178
  const title = getOutputNodeTitle(graph_node);
175
179
  const path = getOutputNodePath(graph_node);
176
180
  const node_class = getOutputNodeClass(graph_node);
@@ -179,12 +183,12 @@ function createOutputNodeItem(graph_node, derived_summary, field_definitions) {
179
183
 
180
184
  if (!title || !node_class) {
181
185
  throw new Error(
182
- `Expected graph node "${graph_node.id}" to have a title and path.`,
186
+ `Expected graph node "${getOutputNodeId(graph_node)}" to have a title and path.`,
183
187
  );
184
188
  }
185
189
 
186
- return {
187
- derived_summary: derived_summary ?? undefined,
190
+ /** @type {OutputNodeItem} */
191
+ const output_item = {
188
192
  fields,
189
193
  id: getOutputNodeId(graph_node),
190
194
  kind: 'node',
@@ -193,21 +197,54 @@ function createOutputNodeItem(graph_node, derived_summary, field_definitions) {
193
197
  title,
194
198
  visible_fields,
195
199
  };
200
+
201
+ if (description) {
202
+ output_item.description = description;
203
+ }
204
+
205
+ return output_item;
196
206
  }
197
207
 
198
208
  /**
199
209
  * @param {{ kind?: string, path: string, status?: string, title: string }} target
200
210
  * @param {NonNullable<PatramRepoConfig['fields']>} field_definitions
201
- * @param {OutputDerivedSummary | null} derived_summary
202
211
  * @param {GraphNode | undefined} graph_node
203
212
  * @returns {OutputResolvedLinkTarget}
204
213
  */
205
- function createResolvedLinkTarget(
206
- target,
207
- field_definitions,
208
- derived_summary,
209
- graph_node,
210
- ) {
214
+ function createResolvedLinkTarget(target, field_definitions, graph_node) {
215
+ const description = getScalarGraphNodeField(
216
+ graph_node
217
+ ? getGraphNodeMetadataValue(graph_node, 'description')
218
+ : undefined,
219
+ );
220
+ const fields = collectResolvedLinkFields(
221
+ target,
222
+ field_definitions,
223
+ graph_node,
224
+ );
225
+
226
+ return {
227
+ description,
228
+ fields,
229
+ id: graph_node ? getOutputNodeId(graph_node) : `doc:${target.path}`,
230
+ kind: resolveResolvedLinkKind(target, graph_node),
231
+ path: resolveResolvedLinkPath(target, graph_node),
232
+ title: resolveResolvedLinkTitle(target, graph_node),
233
+ visible_fields: createVisibleOutputFields(fields, field_definitions),
234
+ };
235
+ }
236
+
237
+ /**
238
+ * @param {{ kind?: string, path: string, status?: string, title: string }} target
239
+ * @param {NonNullable<PatramRepoConfig['fields']>} field_definitions
240
+ * @param {GraphNode | undefined} graph_node
241
+ * @returns {Record<string, string | string[]>}
242
+ */
243
+ function collectResolvedLinkFields(target, field_definitions, graph_node) {
244
+ if (graph_node) {
245
+ return collectOutputFields(graph_node, field_definitions);
246
+ }
247
+
211
248
  /** @type {Record<string, string | string[]>} */
212
249
  const fields = {};
213
250
 
@@ -215,18 +252,34 @@ function createResolvedLinkTarget(
215
252
  fields.status = target.status;
216
253
  }
217
254
 
218
- /** @type {OutputResolvedLinkTarget} */
219
- const resolved_target = {
220
- derived_summary: derived_summary ?? undefined,
221
- fields,
222
- id: graph_node ? getOutputNodeId(graph_node) : `doc:${target.path}`,
223
- kind: target.kind ?? 'document',
224
- path: target.path,
225
- title: target.title,
226
- visible_fields: createVisibleOutputFields(fields, field_definitions),
227
- };
255
+ return fields;
256
+ }
257
+
258
+ /**
259
+ * @param {{ kind?: string, path: string, status?: string, title: string }} target
260
+ * @param {GraphNode | undefined} graph_node
261
+ * @returns {string}
262
+ */
263
+ function resolveResolvedLinkKind(target, graph_node) {
264
+ return getOutputNodeClass(graph_node) ?? target.kind ?? 'document';
265
+ }
266
+
267
+ /**
268
+ * @param {{ kind?: string, path: string, status?: string, title: string }} target
269
+ * @param {GraphNode | undefined} graph_node
270
+ * @returns {string}
271
+ */
272
+ function resolveResolvedLinkPath(target, graph_node) {
273
+ return getOutputNodePath(graph_node) ?? target.path;
274
+ }
228
275
 
229
- return resolved_target;
276
+ /**
277
+ * @param {{ kind?: string, path: string, status?: string, title: string }} target
278
+ * @param {GraphNode | undefined} graph_node
279
+ * @returns {string}
280
+ */
281
+ function resolveResolvedLinkTitle(target, graph_node) {
282
+ return getOutputNodeTitle(graph_node) ?? target.title;
230
283
  }
231
284
 
232
285
  /**
@@ -242,32 +295,43 @@ function getScalarGraphNodeField(field_value) {
242
295
  }
243
296
 
244
297
  /**
245
- * @param {GraphNode} graph_node
298
+ * @param {GraphNode | undefined} graph_node
246
299
  * @returns {string | undefined}
247
300
  */
248
301
  function getOutputNodeTitle(graph_node) {
302
+ if (!graph_node) {
303
+ return undefined;
304
+ }
305
+
249
306
  return (
250
- getScalarGraphNodeField(graph_node.title) ??
251
- getScalarGraphNodeField(graph_node.label) ??
307
+ getScalarGraphNodeField(getGraphNodeMetadataValue(graph_node, 'title')) ??
252
308
  getOutputNodePath(graph_node) ??
253
309
  getScalarGraphNodeField(graph_node.key)
254
310
  );
255
311
  }
256
312
 
257
313
  /**
258
- * @param {GraphNode} graph_node
314
+ * @param {GraphNode | undefined} graph_node
259
315
  * @returns {string | undefined}
260
316
  */
261
317
  function getOutputNodePath(graph_node) {
262
- return getScalarGraphNodeField(graph_node.$path ?? graph_node.path);
318
+ if (!graph_node) {
319
+ return undefined;
320
+ }
321
+
322
+ return getScalarGraphNodeField(getGraphNodePath(graph_node));
263
323
  }
264
324
 
265
325
  /**
266
- * @param {GraphNode} graph_node
326
+ * @param {GraphNode | undefined} graph_node
267
327
  * @returns {string | undefined}
268
328
  */
269
329
  function getOutputNodeClass(graph_node) {
270
- return getScalarGraphNodeField(graph_node.$class ?? graph_node.kind);
330
+ if (!graph_node) {
331
+ return undefined;
332
+ }
333
+
334
+ return getScalarGraphNodeField(getGraphNodeClassName(graph_node));
271
335
  }
272
336
 
273
337
  /**
@@ -275,20 +339,18 @@ function getOutputNodeClass(graph_node) {
275
339
  * @returns {string}
276
340
  */
277
341
  function getOutputNodeId(graph_node) {
278
- return (
279
- getScalarGraphNodeField(graph_node.$id ?? graph_node.id) ?? graph_node.id
280
- );
342
+ return getGraphNodeId(graph_node);
281
343
  }
282
344
 
283
345
  /**
284
346
  * @param {{ label: string, reference: number, target: { kind?: string, path: string, status?: string, title: string } }} resolved_link
285
- * @param {{ derived_summary_evaluator?: DerivedSummaryEvaluator, document_node_ids?: BuildGraphResult['document_node_ids'], graph_nodes?: BuildGraphResult['nodes'], repo_config?: PatramRepoConfig }} command_options
347
+ * @param {{ document_path_ids?: BuildGraphResult['document_path_ids'], graph_nodes?: BuildGraphResult['nodes'], repo_config?: PatramRepoConfig }} command_options
286
348
  * @returns {OutputResolvedLinkItem}
287
349
  */
288
350
  function createResolvedLinkOutputItem(resolved_link, command_options) {
289
351
  const target_graph_node = resolveDocumentGraphNode(
290
352
  command_options.graph_nodes,
291
- command_options.document_node_ids,
353
+ command_options.document_path_ids,
292
354
  resolved_link.target.path,
293
355
  );
294
356
 
@@ -299,11 +361,6 @@ function createResolvedLinkOutputItem(resolved_link, command_options) {
299
361
  target: createResolvedLinkTarget(
300
362
  resolved_link.target,
301
363
  command_options.repo_config?.fields ?? {},
302
- target_graph_node
303
- ? (command_options.derived_summary_evaluator?.evaluate(
304
- target_graph_node,
305
- ) ?? null)
306
- : null,
307
364
  target_graph_node,
308
365
  ),
309
366
  };
@@ -311,20 +368,20 @@ function createResolvedLinkOutputItem(resolved_link, command_options) {
311
368
 
312
369
  /**
313
370
  * @param {BuildGraphResult['nodes'] | undefined} graph_nodes
314
- * @param {BuildGraphResult['document_node_ids'] | undefined} document_node_ids
371
+ * @param {BuildGraphResult['document_path_ids'] | undefined} document_path_ids
315
372
  * @param {string} document_path
316
373
  * @returns {GraphNode | undefined}
317
374
  */
318
375
  function resolveDocumentGraphNode(
319
376
  graph_nodes,
320
- document_node_ids,
377
+ document_path_ids,
321
378
  document_path,
322
379
  ) {
323
380
  if (!graph_nodes) {
324
381
  return undefined;
325
382
  }
326
383
 
327
- return graph_nodes[resolveDocumentNodeId(document_node_ids, document_path)];
384
+ return graph_nodes[resolveDocumentNodeId(document_path_ids, document_path)];
328
385
  }
329
386
 
330
387
  /**
@@ -335,10 +392,10 @@ function resolveDocumentGraphNode(
335
392
  function collectOutputFields(graph_node, field_definitions) {
336
393
  /** @type {Record<string, string | string[]>} */
337
394
  const fields = {};
395
+ const metadata_entries = Object.entries(graph_node.metadata ?? {});
338
396
 
339
- for (const [field_name, field_value] of Object.entries(graph_node)) {
397
+ for (const [field_name, field_value] of metadata_entries) {
340
398
  const normalized_value = getCollectedOutputFieldValue(
341
- graph_node,
342
399
  field_name,
343
400
  field_value,
344
401
  );
@@ -355,7 +412,9 @@ function collectOutputFields(graph_node, field_definitions) {
355
412
  continue;
356
413
  }
357
414
 
358
- const field_value = normalizeOutputFieldValue(graph_node[field_name]);
415
+ const field_value = normalizeOutputFieldValue(
416
+ getGraphNodeMetadataValue(graph_node, field_name),
417
+ );
359
418
 
360
419
  if (field_value !== undefined) {
361
420
  fields[field_name] = field_value;
@@ -366,12 +425,11 @@ function collectOutputFields(graph_node, field_definitions) {
366
425
  }
367
426
 
368
427
  /**
369
- * @param {GraphNode} graph_node
370
428
  * @param {string} field_name
371
429
  * @param {unknown} field_value
372
430
  * @returns {string | string[] | undefined}
373
431
  */
374
- function getCollectedOutputFieldValue(graph_node, field_name, field_value) {
432
+ function getCollectedOutputFieldValue(field_name, field_value) {
375
433
  if (isInternalOutputField(field_name)) {
376
434
  return undefined;
377
435
  }
@@ -382,39 +440,9 @@ function getCollectedOutputFieldValue(graph_node, field_name, field_value) {
382
440
  return undefined;
383
441
  }
384
442
 
385
- if (isLegacyMirrorOutputField(graph_node, field_name, normalized_value)) {
386
- return undefined;
387
- }
388
-
389
443
  return normalized_value;
390
444
  }
391
445
 
392
- /**
393
- * @param {GraphNode} graph_node
394
- * @param {string} field_name
395
- * @param {string | string[]} normalized_value
396
- * @returns {boolean}
397
- */
398
- function isLegacyMirrorOutputField(graph_node, field_name, normalized_value) {
399
- if (Array.isArray(normalized_value)) {
400
- return false;
401
- }
402
-
403
- if (field_name === 'kind') {
404
- return normalized_value === graph_node.$class;
405
- }
406
-
407
- if (field_name === 'path') {
408
- return normalized_value === graph_node.$path;
409
- }
410
-
411
- if (field_name === 'id') {
412
- return normalized_value === graph_node.$id;
413
- }
414
-
415
- return false;
416
- }
417
-
418
446
  /**
419
447
  * @param {Record<string, string | string[]>} fields
420
448
  * @param {NonNullable<PatramRepoConfig['fields']>} field_definitions
@@ -423,7 +451,9 @@ function isLegacyMirrorOutputField(graph_node, field_name, normalized_value) {
423
451
  function createVisibleOutputFields(fields, field_definitions) {
424
452
  return Object.entries(fields)
425
453
  .filter(
426
- ([field_name]) => field_definitions[field_name]?.display?.hidden !== true,
454
+ ([field_name]) =>
455
+ field_name !== 'description' &&
456
+ field_definitions[field_name]?.hidden !== true,
427
457
  )
428
458
  .sort(([left_name], [right_name]) =>
429
459
  compareOutputFieldNames(left_name, right_name, field_definitions),
@@ -436,16 +466,7 @@ function createVisibleOutputFields(fields, field_definitions) {
436
466
  * @returns {boolean}
437
467
  */
438
468
  function isInternalOutputField(field_name) {
439
- return (
440
- field_name === '$class' ||
441
- field_name === '$id' ||
442
- field_name === '$path' ||
443
- field_name === 'id' ||
444
- field_name === 'key' ||
445
- field_name === 'label' ||
446
- field_name === 'path' ||
447
- field_name === 'title'
448
- );
469
+ return field_name === 'title';
449
470
  }
450
471
 
451
472
  /**
@@ -456,9 +477,9 @@ function isInternalOutputField(field_name) {
456
477
  */
457
478
  function compareOutputFieldNames(left_name, right_name, field_definitions) {
458
479
  const left_order =
459
- field_definitions[left_name]?.display?.order ?? Number.MAX_SAFE_INTEGER;
480
+ field_definitions[left_name]?.order ?? Number.MAX_SAFE_INTEGER;
460
481
  const right_order =
461
- field_definitions[right_name]?.display?.order ?? Number.MAX_SAFE_INTEGER;
482
+ field_definitions[right_name]?.order ?? Number.MAX_SAFE_INTEGER;
462
483
 
463
484
  if (left_order !== right_order) {
464
485
  return left_order - right_order;
@@ -10,7 +10,7 @@ export function collectJsdocBlocks(source_text) {
10
10
  const jsdoc_blocks = [];
11
11
 
12
12
  for (let line_index = 0; line_index < source_lines.length; line_index += 1) {
13
- if (!source_lines[line_index].includes('/**')) {
13
+ if (!/^\s*\/\*\*/du.test(source_lines[line_index])) {
14
14
  continue;
15
15
  }
16
16
 
@@ -22,10 +22,10 @@ import { JSDOC_SOURCE_FILE_EXTENSIONS } from '../../config/source-file-defaults.
22
22
  * Activates one source anchor block, extracts directives and links, and
23
23
  * derives title and description claims from prose.
24
24
  *
25
- * Kind: parse
26
- * Status: active
27
- * Tracked in: ../../../docs/plans/v0/source-anchor-dogfooding.md
28
- * Decided by: ../../../docs/decisions/jsdoc-metadata-directive-syntax.md
25
+ * kind: parse
26
+ * status: active
27
+ * tracked_in: ../../../docs/plans/v0/source-anchor-dogfooding.md
28
+ * decided_by: ../../../docs/decisions/jsdoc-metadata-directive-syntax.md
29
29
  * @patram
30
30
  * @see {@link ../parse-claims.js}
31
31
  * @see {@link ../../../docs/decisions/jsdoc-metadata-directive-syntax.md}
@@ -34,7 +34,7 @@ import { JSDOC_SOURCE_FILE_EXTENSIONS } from '../../config/source-file-defaults.
34
34
  const JSDOC_EXTENSIONS = new Set(JSDOC_SOURCE_FILE_EXTENSIONS);
35
35
  const JSDOC_LINK_TAG_PATTERN = /^@(link|see)\s+(.+)$/du;
36
36
  const JSDOC_TAG_PATTERN = /^@[A-Za-z]+(?:\s|$)/du;
37
- const JSDOC_VISIBLE_DIRECTIVE_PATTERN = /^([A-Z][A-Za-z _-]*):\s+(.+)$/du;
37
+ const JSDOC_VISIBLE_DIRECTIVE_PATTERN = /^([a-z][a-z0-9_]*):\s+(.+)$/du;
38
38
 
39
39
  /**
40
40
  * Parse JSDoc metadata claims from one source file.
@@ -160,8 +160,14 @@ function matchJsdocDirectiveFields(file_path, block_line) {
160
160
  return null;
161
161
  }
162
162
 
163
+ const directive_name = normalizeDirectiveName(directive_match[1]);
164
+
165
+ if (!directive_name) {
166
+ return null;
167
+ }
168
+
163
169
  return {
164
- name: normalizeDirectiveName(directive_match[1]),
170
+ name: directive_name,
165
171
  origin: {
166
172
  column: block_line.column,
167
173
  line: block_line.line,