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
package/bin/patram.js CHANGED
@@ -12,10 +12,10 @@ import { main } from '../lib/cli/main.js';
12
12
  * Detects direct process execution and forwards command handling to the shared
13
13
  * CLI runtime.
14
14
  *
15
- * Kind: entrypoint
16
- * Status: active
17
- * Tracked in: ../docs/plans/v0/source-anchor-dogfooding.md
18
- * Decided by: ../docs/decisions/cli-entrypoint-symlink.md
15
+ * kind: entrypoint
16
+ * status: active
17
+ * tracked_in: ../docs/plans/v0/source-anchor-dogfooding.md
18
+ * decided_by: ../docs/decisions/cli-entrypoint-symlink.md
19
19
  * @patram
20
20
  * @see {@link ../lib/cli/main.js}
21
21
  * @see {@link ../docs/patram.md}
@@ -49,9 +49,5 @@ function collectDefinedDiscoveryNames(repo_config) {
49
49
  defined_field_names.add(field_name);
50
50
  }
51
51
 
52
- for (const relation_name of Object.keys(repo_config?.relations ?? {})) {
53
- defined_field_names.add(relation_name);
54
- }
55
-
56
52
  return defined_field_names;
57
53
  }
@@ -101,14 +101,19 @@ async function runQueriesMutationCommand(parsed_command, io_context) {
101
101
  * @returns {{
102
102
  * success: true,
103
103
  * value:
104
- * | { action: 'add', description?: string, name: string, where: string }
104
+ * | {
105
+ * action: 'add',
106
+ * cypher?: string,
107
+ * description?: string,
108
+ * name: string,
109
+ * }
105
110
  * | { action: 'remove', name: string }
106
111
  * | {
107
112
  * action: 'update',
113
+ * cypher?: string,
108
114
  * description?: string,
109
115
  * name: string,
110
116
  * next_name?: string,
111
- * where?: string,
112
117
  * },
113
118
  * } | { error: import('../arguments.types.ts').CliParseError, success: false }}
114
119
  */
@@ -120,9 +125,9 @@ function parseStoredQueryMutation(command_arguments) {
120
125
  success: true,
121
126
  value: {
122
127
  action: 'add',
128
+ cypher: readOptionValue(command_arguments, '--cypher'),
123
129
  description: readOptionValue(command_arguments, '--desc'),
124
130
  name: command_arguments[1],
125
- where: readRequiredOptionValue(command_arguments, '--query'),
126
131
  },
127
132
  };
128
133
  }
@@ -142,10 +147,10 @@ function parseStoredQueryMutation(command_arguments) {
142
147
  success: true,
143
148
  value: {
144
149
  action: 'update',
150
+ cypher: readOptionValue(command_arguments, '--cypher'),
145
151
  description: readOptionValue(command_arguments, '--desc'),
146
152
  name: command_arguments[1],
147
153
  next_name: readOptionValue(command_arguments, '--name'),
148
- where: readOptionValue(command_arguments, '--query'),
149
154
  },
150
155
  };
151
156
  }
@@ -200,22 +205,7 @@ function renderStoredQueryMutationResult(mutation_result, output_mode) {
200
205
 
201
206
  /**
202
207
  * @param {string[]} command_arguments
203
- * @param {'--desc' | '--name' | '--query'} option_name
204
- * @returns {string}
205
- */
206
- function readRequiredOptionValue(command_arguments, option_name) {
207
- const option_value = readOptionValue(command_arguments, option_name);
208
-
209
- if (option_value === undefined) {
210
- throw new Error(`Expected ${option_name} to be present.`);
211
- }
212
-
213
- return option_value;
214
- }
215
-
216
- /**
217
- * @param {string[]} command_arguments
218
- * @param {'--desc' | '--name' | '--query'} option_name
208
+ * @param {'--cypher' | '--desc' | '--name'} option_name
219
209
  * @returns {string | undefined}
220
210
  */
221
211
  function readOptionValue(command_arguments, option_name) {
@@ -10,7 +10,6 @@ import {
10
10
  shouldPageCommandOutput,
11
11
  writeCommandOutput,
12
12
  } from '../../output/command-output.js';
13
- import { createDerivedSummaryEvaluator } from '../../output/derived-summary.js';
14
13
  import { renderCheckDiagnostics } from '../../output/render-check-output.js';
15
14
  import {
16
15
  renderCliParseError,
@@ -83,16 +82,10 @@ export async function runQueryCommand(parsed_command, io_context) {
83
82
  return 1;
84
83
  }
85
84
 
86
- const derived_summary_evaluator = createDerivedSummaryEvaluator(
87
- project_graph_result.config,
88
- project_graph_result.graph,
89
- );
90
-
91
85
  await writeCommandOutput(
92
86
  io_context,
93
87
  parsed_command,
94
88
  createOutputView('query', query_result.nodes, {
95
- derived_summary_evaluator,
96
89
  ...createQueryOutputOptions(parsed_command, query_result, use_pager),
97
90
  repo_config: project_graph_result.config,
98
91
  }),
@@ -182,7 +175,7 @@ function createQueryOutputOptions(parsed_command, query_result, use_pager) {
182
175
  const offset = parsed_command.query_offset ?? 0;
183
176
 
184
177
  if (query_result.total_count === 0) {
185
- hints.push("Try: patram query --where '$class=task'");
178
+ hints.push('Try: patram query --cypher "MATCH (n:Task) RETURN n"');
186
179
  }
187
180
 
188
181
  if (
@@ -7,7 +7,6 @@ import process from 'node:process';
7
7
  import { loadProjectGraph } from '../../graph/load-project-graph.js';
8
8
  import { inspectReverseReferences } from '../../graph/inspect-reverse-references.js';
9
9
  import { writeCommandOutput } from '../../output/command-output.js';
10
- import { createDerivedSummaryEvaluator } from '../../output/derived-summary.js';
11
10
  import { createRefsOutputView } from '../../output/render-output-view.js';
12
11
 
13
12
  import { renderInvalidWhereDiagnostic } from '../render-help.js';
@@ -31,7 +30,7 @@ export async function runRefsCommand(parsed_command, io_context) {
31
30
  project_graph_result.graph,
32
31
  parsed_command.command_arguments[0],
33
32
  project_graph_result.config,
34
- resolveRefsWhereClause(parsed_command.command_arguments),
33
+ resolveRefsCypherQuery(parsed_command.command_arguments),
35
34
  );
36
35
 
37
36
  if (refs_output.diagnostics.length > 0) {
@@ -42,16 +41,10 @@ export async function runRefsCommand(parsed_command, io_context) {
42
41
  return 1;
43
42
  }
44
43
 
45
- const derived_summary_evaluator = createDerivedSummaryEvaluator(
46
- project_graph_result.config,
47
- project_graph_result.graph,
48
- );
49
-
50
44
  await writeCommandOutput(
51
45
  io_context,
52
46
  parsed_command,
53
47
  createRefsOutputView(refs_output, {
54
- derived_summary_evaluator,
55
48
  repo_config: project_graph_result.config,
56
49
  }),
57
50
  );
@@ -63,8 +56,8 @@ export async function runRefsCommand(parsed_command, io_context) {
63
56
  * @param {string[]} command_arguments
64
57
  * @returns {string | undefined}
65
58
  */
66
- function resolveRefsWhereClause(command_arguments) {
67
- if (command_arguments[1] !== '--where') {
59
+ function resolveRefsCypherQuery(command_arguments) {
60
+ if (command_arguments[1] !== '--cypher') {
68
61
  return undefined;
69
62
  }
70
63
 
@@ -6,7 +6,6 @@ import process from 'node:process';
6
6
 
7
7
  import { loadProjectGraph } from '../../graph/load-project-graph.js';
8
8
  import { writeCommandOutput } from '../../output/command-output.js';
9
- import { createDerivedSummaryEvaluator } from '../../output/derived-summary.js';
10
9
  import { createShowOutputView } from '../../output/render-output-view.js';
11
10
  import { loadShowOutput } from '../../output/show-document.js';
12
11
 
@@ -38,17 +37,11 @@ export async function runShowCommand(parsed_command, io_context) {
38
37
  return 1;
39
38
  }
40
39
 
41
- const derived_summary_evaluator = createDerivedSummaryEvaluator(
42
- project_graph_result.config,
43
- project_graph_result.graph,
44
- );
45
-
46
40
  await writeCommandOutput(
47
41
  io_context,
48
42
  parsed_command,
49
43
  createShowOutputView(show_output.value, {
50
- derived_summary_evaluator,
51
- document_node_ids: project_graph_result.graph.document_node_ids,
44
+ document_path_ids: project_graph_result.graph.document_path_ids,
52
45
  graph_nodes: project_graph_result.graph.nodes,
53
46
  repo_config: project_graph_result.config,
54
47
  }),
@@ -142,41 +142,42 @@ const COMMAND_DEFINITIONS = {
142
142
  },
143
143
  query: {
144
144
  allowed_option_names: new Set([
145
+ 'cypher',
145
146
  'explain',
146
147
  'limit',
147
148
  'lint',
148
149
  'offset',
149
- 'where',
150
150
  ]),
151
151
  examples: [
152
152
  'patram query active-plans',
153
- "patram query --where 'tracked_in=doc:docs/plans/v0/worktracking-agent-guidance.md'",
154
- "patram query --where 'status not in [done, dropped, superseded]'",
155
- "patram query --where '$class=plan and none(in:tracked_in, $class=decision)'",
156
- "patram query --where 'count(in:decided_by, $class=task) = 0'",
153
+ 'patram query --cypher "MATCH (n:Plan) WHERE n.status = \'active\' RETURN n"',
154
+ 'patram query --cypher "MATCH (n) WHERE id(n) = \'plan:v0/worktracking-agent-guidance\' RETURN n"',
155
+ "patram query --cypher \"MATCH (n) WHERE n.status NOT IN ['done', 'dropped', 'superseded'] RETURN n\"",
156
+ 'patram query --cypher "MATCH (n:Plan) WHERE NOT EXISTS { MATCH (decision:Decision)-[:TRACKED_IN]->(n) } RETURN n"',
157
+ 'patram query --cypher "MATCH (n:Decision) WHERE COUNT { MATCH (task:Task)-[:DECIDED_BY]->(n) } = 0 RETURN n"',
157
158
  'patram query ready-tasks --explain',
158
- "patram query --where '$class=decision and status=accepted and count(in:decided_by, $class=task) = 0' --lint",
159
+ 'patram query --cypher "MATCH (n:Decision) WHERE n.status = \'accepted\' AND COUNT { MATCH (task:Task)-[:DECIDED_BY]->(n) } = 0 RETURN n" --lint',
159
160
  'patram query active-plans --limit 10 --offset 20',
160
161
  ],
161
162
  extra_positionals_message:
162
- 'Query accepts either "--where" or a stored query name.',
163
+ 'Query accepts "--cypher" or a stored query name.',
163
164
  help_topics: ['query-language'],
164
165
  max_positionals: 1,
165
166
  min_positionals: 0,
166
167
  missing_argument_examples: [
167
168
  'patram query active-plans',
168
- "patram query --where 'tracked_in=doc:docs/plans/v0/worktracking-agent-guidance.md'",
169
+ 'patram query --cypher "MATCH (n:Plan) WHERE n.status = \'active\' RETURN n"',
169
170
  ],
170
- missing_argument_label: "<name> or --where '<clause>'",
171
+ missing_argument_label: "<name> or --cypher '<query>'",
171
172
  missing_usage_lines: [
172
173
  'patram query <name> [options]',
173
- "patram query --where '<clause>' [options]",
174
+ `patram query --cypher '<query>' [options]`,
174
175
  ],
175
176
  option_column_width: 19,
176
177
  options: [
177
178
  {
178
- description: 'Run an ad hoc query instead of a stored query',
179
- label: '--where <clause>',
179
+ description: 'Run an ad hoc Cypher query instead of a stored query',
180
+ label: '--cypher <query>',
180
181
  },
181
182
  {
182
183
  description: 'Skip the first N matches',
@@ -204,29 +205,28 @@ const COMMAND_DEFINITIONS = {
204
205
  },
205
206
  ],
206
207
  related: ['queries', 'show'],
207
- root_summary: 'Run a stored query or an ad hoc where clause',
208
+ root_summary: 'Run a stored query or an ad hoc Cypher query',
208
209
  summary:
209
- 'Run a stored query or an ad hoc where clause against graph nodes.',
210
+ 'Run a stored query or an ad hoc Cypher query against graph nodes.',
210
211
  syntax_lines: [
211
- '$id=<value> | $class=<value> | $path=<value> | status=<value>',
212
- '$id^=<prefix> | $path^=<prefix> | title~<text>',
213
- '<field> in [<value>, ...] | <field> not in [<value>, ...]',
214
- '<relation>:* | <relation>=<target-id>',
215
- 'any(<traversal>, <term> and <term>)',
216
- 'none(<traversal>, <term> and <term>)',
217
- 'count(<traversal>, <term> and <term>) <comparison> <number>',
212
+ 'MATCH (n) RETURN n',
213
+ "MATCH (n:Label) WHERE n.status = 'active' RETURN n",
214
+ "MATCH (n) WHERE id(n) = 'command:query' RETURN n",
215
+ 'MATCH (n) WHERE EXISTS { MATCH ... } RETURN n',
216
+ 'MATCH (n) WHERE COUNT { MATCH ... } = 0 RETURN n',
218
217
  ],
219
218
  usage_lines: [
220
219
  'patram query <name> [options]',
221
- "patram query --where '<clause>' [options]",
220
+ `patram query --cypher '<query>' [options]`,
222
221
  ],
223
222
  },
224
223
  queries: {
225
- allowed_option_names: new Set(['desc', 'name', 'query']),
224
+ allowed_option_names: new Set(['cypher', 'desc', 'name']),
226
225
  examples: [
227
226
  'patram queries',
228
- "patram queries add ready-tasks --query '$class=task and status=ready'",
227
+ `patram queries add active-plans --cypher "MATCH (n:Plan) WHERE n.status = 'active' RETURN n"`,
229
228
  "patram queries update ready-tasks --desc 'Show tasks that are ready.'",
229
+ `patram queries update ready-tasks --cypher "MATCH (n:Task) WHERE n.status = 'ready' RETURN n"`,
230
230
  'patram queries remove ready-tasks',
231
231
  ],
232
232
  extra_positionals_message:
@@ -238,15 +238,15 @@ const COMMAND_DEFINITIONS = {
238
238
  missing_argument_label: null,
239
239
  missing_usage_lines: [
240
240
  'patram queries',
241
- 'patram queries add <name> --query <clause>',
242
- 'patram queries update <name> [--name <new_name>] [--query <clause>] [--desc <text>]',
241
+ 'patram queries add <name> --cypher <query>',
242
+ 'patram queries update <name> [--name <new_name>] [--cypher <query>] [--desc <text>]',
243
243
  'patram queries remove <name>',
244
244
  ],
245
245
  option_column_width: 19,
246
246
  options: [
247
247
  {
248
- description: 'Persist a new stored query',
249
- label: '--query <clause>',
248
+ description: 'Persist a new stored Cypher query',
249
+ label: '--cypher <query>',
250
250
  },
251
251
  {
252
252
  description: 'Set or rename the stored query name for update',
@@ -271,16 +271,16 @@ const COMMAND_DEFINITIONS = {
271
271
  'List stored queries or mutate them through add, update, and remove.',
272
272
  usage_lines: [
273
273
  'patram queries [options]',
274
- 'patram queries add <name> --query <clause> [--desc <text>] [options]',
275
- 'patram queries update <name> [--name <new_name>] [--query <clause>] [--desc <text>] [options]',
274
+ `patram queries add <name> --cypher <query> [--desc <text>] [options]`,
275
+ 'patram queries update <name> [--name <new_name>] [--cypher <query>] [--desc <text>] [options]',
276
276
  'patram queries remove <name> [options]',
277
277
  ],
278
278
  },
279
279
  refs: {
280
- allowed_option_names: new Set(['where']),
280
+ allowed_option_names: new Set(['cypher']),
281
281
  examples: [
282
282
  'patram refs docs/decisions/query-language.md',
283
- "patram refs docs/decisions/query-language.md --where '$class=document'",
283
+ 'patram refs docs/decisions/query-language.md --cypher "MATCH (n:Document) RETURN n"',
284
284
  'patram refs docs/decisions/query-language.md --json',
285
285
  ],
286
286
  extra_positionals_message: 'Refs accepts exactly one file path.',
@@ -289,15 +289,15 @@ const COMMAND_DEFINITIONS = {
289
289
  min_positionals: 1,
290
290
  missing_argument_examples: [
291
291
  'patram refs docs/decisions/query-language.md',
292
- "patram refs docs/patram.md --where '$class=document'",
292
+ 'patram refs docs/patram.md --cypher "MATCH (n:Document) RETURN n"',
293
293
  ],
294
294
  missing_argument_label: '<file>',
295
295
  missing_usage_lines: ['patram refs <file>'],
296
296
  option_column_width: 19,
297
297
  options: [
298
298
  {
299
- description: 'Filter incoming source nodes with a where clause',
300
- label: '--where <clause>',
299
+ description: 'Filter incoming source nodes with a Cypher query',
300
+ label: '--cypher <query>',
301
301
  },
302
302
  {
303
303
  description: 'Print plain text output',
@@ -350,102 +350,67 @@ const COMMAND_DEFINITIONS = {
350
350
  const HELP_TOPIC_DEFINITIONS = {
351
351
  'query-language': {
352
352
  examples: [
353
- '$class=decision and status=accepted',
354
- '$class=task or status=done',
355
- '($class=task or status=blocked) and title~Show',
356
- '$path^=docs/plans/',
357
- 'title~query',
358
- 'tracked_in=doc:docs/plans/v0/worktracking-agent-guidance.md',
359
- 'implements_command=command:query',
360
- 'status not in [done, dropped, superseded]',
361
- 'any(in:tracked_in, $class=task and status in [pending, ready, in_progress, blocked])',
362
- 'none(in:tracked_in, $class=decision)',
363
- 'count(in:decided_by, $class=task) = 0',
364
- 'not uses_term=term:graph',
353
+ "MATCH (n:Decision) WHERE n.status = 'accepted' RETURN n",
354
+ "MATCH (n:Task) WHERE n.status IN ['pending', 'ready'] RETURN n",
355
+ "MATCH (n) WHERE path(n) ENDS WITH '/README.md' RETURN n",
356
+ 'MATCH (n:Plan) WHERE NOT EXISTS { MATCH (decision:Decision)-[:TRACKED_IN]->(n) } RETURN n',
357
+ 'MATCH (n:Decision) WHERE COUNT { MATCH (task:Task)-[:DECIDED_BY]->(n) } = 0 RETURN n',
358
+ "MATCH (n) WHERE EXISTS { MATCH (n)-[:IMPLEMENTS_COMMAND]->(command:Command) WHERE id(command) = 'command:query' } RETURN n",
365
359
  ],
366
- lead: 'Query language filters graph nodes with field, relation, traversal, and aggregate terms.',
360
+ lead: 'Query language uses a constrained Cypher subset for graph node selection.',
367
361
  operators: [
368
362
  {
369
- description: 'Exact field match or exact count comparison',
370
- label: '=',
363
+ description: 'Equality and exact value comparison',
364
+ label: '= | <>',
371
365
  },
372
366
  {
373
- description: 'Prefix match for structural id and path',
374
- label: '^=',
367
+ description: 'String prefix, suffix, and contains checks',
368
+ label: 'STARTS WITH | ENDS WITH | CONTAINS',
375
369
  },
376
370
  {
377
- description: 'Contains text for title',
378
- label: '~',
371
+ description: 'Set membership checks',
372
+ label: 'IN | NOT IN',
379
373
  },
380
374
  {
381
- description: 'Set membership for supported fields',
382
- label: 'in',
375
+ description: 'Boolean composition',
376
+ label: 'AND | OR | NOT',
383
377
  },
384
378
  {
385
- description: 'Set exclusion for supported fields',
386
- label: 'not in',
379
+ description: 'Relation existence subqueries',
380
+ label: 'EXISTS { ... }',
387
381
  },
388
382
  {
389
- description: 'Negate one term',
390
- label: 'not',
391
- },
392
- {
393
- description: 'Combine terms',
394
- label: 'and',
395
- },
396
- {
397
- description: 'Match either side',
398
- label: 'or',
399
- },
400
- {
401
- description: 'Group boolean expressions',
402
- label: '( )',
403
- },
404
- {
405
- description: 'Count comparisons',
406
- label: '!= < > >= <=',
383
+ description: 'Related-node count comparisons',
384
+ label: 'COUNT { ... }',
407
385
  },
408
386
  ],
409
387
  relation_terms: [
410
388
  {
411
- description: 'Match nodes with at least one outgoing relation',
412
- label: '<relation>:*',
413
- },
414
- {
415
- description: 'Match nodes linked to an exact target id',
416
- label: '<relation>=<target-id>',
389
+ description: 'Outgoing relation match',
390
+ label: '(n)-[:RELATION]->(target)',
417
391
  },
418
392
  {
419
- description: 'Traverse one incoming relation hop',
420
- label: 'in:<relation>',
393
+ description: 'Incoming relation match',
394
+ label: '(source)-[:RELATION]->(n)',
421
395
  },
422
396
  {
423
- description: 'Traverse one outgoing relation hop',
424
- label: 'out:<relation>',
397
+ description: 'Label-qualified related node pattern',
398
+ label: '(n)-[:RELATION]->(target:Label)',
425
399
  },
426
400
  ],
427
401
  terms: [
428
- 'Exact match: $id, $class, $path, status',
429
- 'Prefix match: $id, $path',
430
- 'Contains text: title',
431
- 'Set membership: $id, $class, $path, status, title',
402
+ 'Root match: MATCH (n) or MATCH (n:Label)',
403
+ 'Return shape: RETURN n',
404
+ 'Structural functions: id(n), path(n)',
405
+ 'Labels select class membership: MATCH (n:Label)',
406
+ 'Common fields: n.title, n.status, n.kind',
407
+ 'Subqueries: EXISTS { MATCH ... WHERE ... } and COUNT { MATCH ... WHERE ... }',
432
408
  ],
433
409
  usage_lines: [
434
- '<field>=<value>',
435
- '$id^=<prefix>',
436
- '$path^=<prefix>',
437
- 'title~<text>',
438
- '<field> in [<value>, ...]',
439
- '<field> not in [<value>, ...]',
440
- '<relation>:*',
441
- '<relation>=<target-id>',
442
- 'any(<traversal>, <term> and <term>)',
443
- 'none(<traversal>, <term> and <term>)',
444
- 'count(<traversal>, <term> and <term>) <comparison> <number>',
445
- 'not <term>',
446
- '<term> and <term>',
447
- '<term> or <term>',
448
- '(<expression>)',
410
+ 'MATCH (n) RETURN n',
411
+ 'MATCH (n:Label) WHERE <predicate> RETURN n',
412
+ 'MATCH (n) WHERE EXISTS { MATCH ... } RETURN n',
413
+ 'MATCH (n) WHERE COUNT { MATCH ... } <comparison> <number> RETURN n',
449
414
  ],
450
415
  },
451
416
  };
@@ -559,7 +524,7 @@ function listOptionLabels(command_name) {
559
524
  } else {
560
525
  option_labels.add('--limit');
561
526
  option_labels.add('--offset');
562
- option_labels.add('--where');
527
+ option_labels.add('--cypher');
563
528
  }
564
529
 
565
530
  return [...option_labels];
package/lib/cli/main.js CHANGED
@@ -16,16 +16,16 @@ import { runShowCommand } from './commands/show.js';
16
16
  * Loads repo state and routes `check`, `fields`, `query`, `queries`, and
17
17
  * `show` through the shared output pipeline.
18
18
  *
19
- * Kind: cli
20
- * Status: active
21
- * Implements Command: ../../docs/reference/commands/check.md
22
- * Implements Command: ../../docs/reference/commands/query.md
23
- * Implements Command: ../../docs/reference/commands/queries.md
24
- * Implements Command: ../../docs/reference/commands/refs.md
25
- * Implements Command: ../../docs/reference/commands/show.md
26
- * Tracked in: ../../docs/plans/v0/source-anchor-dogfooding.md
27
- * Decided by: ../../docs/decisions/cli-output-architecture.md
28
- * Decided by: ../../docs/decisions/cli-argument-parser.md
19
+ * kind: cli
20
+ * status: active
21
+ * implements_command: ../../docs/reference/commands/check.md
22
+ * implements_command: ../../docs/reference/commands/query.md
23
+ * implements_command: ../../docs/reference/commands/queries.md
24
+ * implements_command: ../../docs/reference/commands/refs.md
25
+ * implements_command: ../../docs/reference/commands/show.md
26
+ * tracked_in: ../../docs/plans/v0/source-anchor-dogfooding.md
27
+ * decided_by: ../../docs/decisions/cli-output-architecture.md
28
+ * decided_by: ../../docs/decisions/cli-argument-parser.md
29
29
  * @patram
30
30
  * @see {@link ./parse-arguments.js}
31
31
  * @see {@link ./commands/query.js}