graph-lcb 0.1.0__tar.gz
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.
- graph_lcb-0.1.0/LICENSE +21 -0
- graph_lcb-0.1.0/PKG-INFO +605 -0
- graph_lcb-0.1.0/README.md +594 -0
- graph_lcb-0.1.0/cli/__init__.py +244 -0
- graph_lcb-0.1.0/commands/__init__.py +1 -0
- graph_lcb-0.1.0/commands/admin.py +103 -0
- graph_lcb-0.1.0/commands/common.py +167 -0
- graph_lcb-0.1.0/commands/mutations.py +85 -0
- graph_lcb-0.1.0/commands/queries.py +69 -0
- graph_lcb-0.1.0/commands/records.py +129 -0
- graph_lcb-0.1.0/commands/visualization-templates/graphs.template.html +821 -0
- graph_lcb-0.1.0/commands/visualization.py +44 -0
- graph_lcb-0.1.0/graph_cli.py +15 -0
- graph_lcb-0.1.0/graph_lcb.egg-info/PKG-INFO +605 -0
- graph_lcb-0.1.0/graph_lcb.egg-info/SOURCES.txt +31 -0
- graph_lcb-0.1.0/graph_lcb.egg-info/dependency_links.txt +1 -0
- graph_lcb-0.1.0/graph_lcb.egg-info/entry_points.txt +2 -0
- graph_lcb-0.1.0/graph_lcb.egg-info/requires.txt +3 -0
- graph_lcb-0.1.0/graph_lcb.egg-info/top_level.txt +5 -0
- graph_lcb-0.1.0/graphs/engine.py +754 -0
- graph_lcb-0.1.0/graphs/types/__init__.py +105 -0
- graph_lcb-0.1.0/pyproject.toml +26 -0
- graph_lcb-0.1.0/schemas/__init__.py +1 -0
- graph_lcb-0.1.0/schemas/edges.schema.json +91 -0
- graph_lcb-0.1.0/schemas/entities.schema.json +76 -0
- graph_lcb-0.1.0/setup.cfg +4 -0
- graph_lcb-0.1.0/tests/test_case_insensitive_types.py +128 -0
- graph_lcb-0.1.0/tests/test_cli.py +123 -0
- graph_lcb-0.1.0/tests/test_engine_and_commands.py +404 -0
- graph_lcb-0.1.0/tests/test_graph_output.py +119 -0
- graph_lcb-0.1.0/tests/test_init.py +94 -0
- graph_lcb-0.1.0/tests/test_traversal.py +97 -0
- graph_lcb-0.1.0/tests/test_validate.py +182 -0
graph_lcb-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Lucas
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
graph_lcb-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,605 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: graph-lcb
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A local CLI for managing JSON-backed graphs with customizable entity and edge types.
|
|
5
|
+
Requires-Python: >=3.10
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Provides-Extra: test
|
|
9
|
+
Requires-Dist: pytest>=9.2.0; extra == "test"
|
|
10
|
+
Dynamic: license-file
|
|
11
|
+
|
|
12
|
+
# graph-cli
|
|
13
|
+
|
|
14
|
+
A local command-line tool for managing a JSON-backed graph with customizable
|
|
15
|
+
entity and edge types. The workspace is stored in `.graph/` under the current
|
|
16
|
+
working directory.
|
|
17
|
+
|
|
18
|
+

|
|
19
|
+

|
|
20
|
+

|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
## Install
|
|
24
|
+
|
|
25
|
+
Requires Python 3.10 or newer and Git. Install the CLI directly from GitHub with:
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
pip install graphcli
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
This installs the `graph` command. To install the test dependencies and run the
|
|
32
|
+
test suite from a local development checkout instead:
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
python -m pip install -e ".[test]"
|
|
36
|
+
python -m pytest
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Workspace and files
|
|
40
|
+
|
|
41
|
+
Initialize a project explicitly:
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
graph init
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
This creates missing starter contract files and copies the bundled JSON
|
|
48
|
+
Schemas into `.graph/schemas/`. Existing contracts, schemas, and graph data
|
|
49
|
+
are preserved. Initialization does not create `graph.json`; the graph store
|
|
50
|
+
is written when a record is first added.
|
|
51
|
+
|
|
52
|
+
Graph operations do not initialize a workspace implicitly. If `.graph/` or
|
|
53
|
+
either contract file is missing, graph operations report that the workspace
|
|
54
|
+
must be initialized. `graph validate` reports an uninitialized workspace
|
|
55
|
+
without creating files. `graph contract` can display the starter contracts
|
|
56
|
+
without creating a workspace.
|
|
57
|
+
|
|
58
|
+
| Path | Purpose |
|
|
59
|
+
| --- | --- |
|
|
60
|
+
| `.graph/entities.json` | Entity type definitions and allowed node properties |
|
|
61
|
+
| `.graph/edges.json` | Edge type definitions, endpoint constraints, and allowed edge properties |
|
|
62
|
+
| `.graph/graph.json` | Persisted `nodes` and `edges` arrays |
|
|
63
|
+
| `.graph/schemas/entities.schema.json` | Bundled editor-facing JSON Schema for entity contracts |
|
|
64
|
+
| `.graph/schemas/edges.schema.json` | Bundled editor-facing JSON Schema for edge contracts |
|
|
65
|
+
| `.graph/view.html` | Generated visualization written by `graph view` |
|
|
66
|
+
|
|
67
|
+
The contracts and graph store are resolved relative to the process's current
|
|
68
|
+
working directory, not the location of the installed CLI. Run commands from
|
|
69
|
+
the project whose `.graph/` you intend to access.
|
|
70
|
+
|
|
71
|
+
## Contract format
|
|
72
|
+
|
|
73
|
+
An entity contract maps each entity type to a definition with a `properties`
|
|
74
|
+
object. An edge contract additionally defines the allowed source and target
|
|
75
|
+
entity types. The starter contracts created by `graph init` are:
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"$schema": "./schemas/entities.schema.json",
|
|
80
|
+
"API": {
|
|
81
|
+
"description": "An API or application service",
|
|
82
|
+
"properties": {
|
|
83
|
+
"language": { "type": "string", "required": true }
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
```json
|
|
90
|
+
{
|
|
91
|
+
"$schema": "./schemas/edges.schema.json",
|
|
92
|
+
"CALLS": {
|
|
93
|
+
"description": "A service synchronously invokes another service or API.",
|
|
94
|
+
"source": ["API"],
|
|
95
|
+
"target": ["API"],
|
|
96
|
+
"properties": {
|
|
97
|
+
"protocol": { "type": "string", "required": false }
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
You can add domain-specific types and properties. For example, an entity
|
|
104
|
+
contract may define:
|
|
105
|
+
|
|
106
|
+
```json
|
|
107
|
+
{
|
|
108
|
+
"API": {
|
|
109
|
+
"description": "An API or application service",
|
|
110
|
+
"properties": {
|
|
111
|
+
"language": { "type": "string", "required": true },
|
|
112
|
+
"framework": "string",
|
|
113
|
+
"base_url": { "type": "string", "required": false }
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
And an edge contract may define:
|
|
120
|
+
|
|
121
|
+
```json
|
|
122
|
+
{
|
|
123
|
+
"CALLS": {
|
|
124
|
+
"description": "One service invokes another.",
|
|
125
|
+
"source": ["API", "WORKER"],
|
|
126
|
+
"target": ["API"],
|
|
127
|
+
"properties": {
|
|
128
|
+
"method": { "type": "string", "required": false }
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Contract rules:
|
|
135
|
+
|
|
136
|
+
- Each top-level type name maps to a JSON object. Type names are
|
|
137
|
+
case-insensitive when used by commands and must be unique ignoring case.
|
|
138
|
+
The spelling in the contract is canonical for newly created records.
|
|
139
|
+
- Each entity requires a `properties` object. Each edge requires `source`,
|
|
140
|
+
`target`, and `properties`. `source` and `target` are lists of entity type
|
|
141
|
+
names; each referenced type must exist. The bundled JSON Schema expects these
|
|
142
|
+
lists to be non-empty.
|
|
143
|
+
- `description` is optional at runtime. It describes a type, not an individual
|
|
144
|
+
record. Edge records have their own optional free-form description.
|
|
145
|
+
- A property definition is either a shorthand type string, such as
|
|
146
|
+
`"framework": "string"`, or an object with `type` and optional `required`.
|
|
147
|
+
Supported types are `string`, `number`, `integer`, and `boolean`.
|
|
148
|
+
`required` defaults to `false`.
|
|
149
|
+
- `number` accepts JSON integers and decimal numbers, but not booleans.
|
|
150
|
+
`integer` accepts integers, but not booleans. Null, arrays, and objects are
|
|
151
|
+
not supported property types.
|
|
152
|
+
- The engine checks contract structure, type references, and property rules
|
|
153
|
+
during graph operations and `validate`. The bundled JSON Schema files support
|
|
154
|
+
editor validation and completion; `$schema` is metadata and is omitted from
|
|
155
|
+
`graph contract` output.
|
|
156
|
+
|
|
157
|
+
## Command conventions
|
|
158
|
+
|
|
159
|
+
```text
|
|
160
|
+
graph <command> [arguments] [options]
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
- Long options use either `--name value` or `--name=value`. Short options such
|
|
164
|
+
as `-n` are not supported.
|
|
165
|
+
- Options with comma-separated values accept one or more items without spaces,
|
|
166
|
+
for example `--type=API,WORKER`.
|
|
167
|
+
- JSON option values must be valid JSON. The examples below use single quotes
|
|
168
|
+
around JSON, as is customary in POSIX shells; use quoting appropriate for
|
|
169
|
+
your shell.
|
|
170
|
+
- `--help` or `-h` prints brief command help. `graph help` prints the command
|
|
171
|
+
list; `graph help COMMAND` prints that command's synopsis. Detailed option
|
|
172
|
+
behavior is documented below.
|
|
173
|
+
- `--` stops option parsing. Arguments after it are treated as positional
|
|
174
|
+
values.
|
|
175
|
+
- Commands requiring a graph workspace expect `graph init` to have been run
|
|
176
|
+
first. Help, `init`, `contract`, and `validate` do not require initialization.
|
|
177
|
+
|
|
178
|
+
## Command reference
|
|
179
|
+
|
|
180
|
+
### `graph --help`, `graph help`
|
|
181
|
+
|
|
182
|
+
```text
|
|
183
|
+
graph --help
|
|
184
|
+
graph help [COMMAND]
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Print the registered commands, or brief help for one command. These forms do
|
|
188
|
+
not read or create graph files.
|
|
189
|
+
|
|
190
|
+
### `graph init`
|
|
191
|
+
|
|
192
|
+
```text
|
|
193
|
+
graph init
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Create `.graph/`, starter `entities.json` and `edges.json` files, and missing
|
|
197
|
+
bundled schema files under `.graph/schemas/`.
|
|
198
|
+
|
|
199
|
+
- Takes no positional arguments or options.
|
|
200
|
+
- Existing contracts and schemas are never overwritten. Existing
|
|
201
|
+
`.graph/graph.json` is not modified.
|
|
202
|
+
- Safe to run again: it fills missing files but preserves existing ones.
|
|
203
|
+
- Does not create an empty `graph.json`; a graph store is written when a node
|
|
204
|
+
or edge is added.
|
|
205
|
+
- Prints `{"initialized":true,"directory":".graph"}` on success.
|
|
206
|
+
|
|
207
|
+
### `graph contract`
|
|
208
|
+
|
|
209
|
+
```text
|
|
210
|
+
graph contract [entities|edges] [--compact]
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Show contract definitions. This command can be used before initialization;
|
|
214
|
+
when no workspace contract files exist, it displays the built-in starter
|
|
215
|
+
contracts without writing them.
|
|
216
|
+
|
|
217
|
+
| Parameter | Meaning |
|
|
218
|
+
| --- | --- |
|
|
219
|
+
| `entities` | Show only entity contracts. `entity` is also accepted. |
|
|
220
|
+
| `edges` | Show only edge contracts. `edge` is also accepted. |
|
|
221
|
+
| Omitted category | Show both sections. |
|
|
222
|
+
| `--compact` | Render text summaries containing type descriptions, edge endpoint types, and property types/required markers instead of JSON. Takes no value. |
|
|
223
|
+
|
|
224
|
+
Default output is compact single-line JSON: when showing both categories the
|
|
225
|
+
top-level keys are `entities` and `edges`; when one category is selected, the
|
|
226
|
+
output is that contract object. `$schema` is omitted from this output.
|
|
227
|
+
Compact output is plain text, not JSON.
|
|
228
|
+
|
|
229
|
+
### `graph validate`
|
|
230
|
+
|
|
231
|
+
```text
|
|
232
|
+
graph validate
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Read-only validation of the current contracts and graph store. It does not
|
|
236
|
+
create, rewrite, or repair files. It reports all detected contract and record
|
|
237
|
+
violations in one response.
|
|
238
|
+
|
|
239
|
+
The JSON response has this shape:
|
|
240
|
+
|
|
241
|
+
```json
|
|
242
|
+
{
|
|
243
|
+
"valid": false,
|
|
244
|
+
"errors": [
|
|
245
|
+
{
|
|
246
|
+
"kind": "node",
|
|
247
|
+
"id": "orders-api",
|
|
248
|
+
"code": "missing_required_property",
|
|
249
|
+
"message": "missing required property: language"
|
|
250
|
+
}
|
|
251
|
+
],
|
|
252
|
+
"summary": {
|
|
253
|
+
"nodes": 1,
|
|
254
|
+
"edges": 0,
|
|
255
|
+
"errors": 1
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
`kind` identifies the contract, store, node, or edge involved. When an issue
|
|
261
|
+
belongs to a record, the issue may include its `id`; some errors may include
|
|
262
|
+
additional details such as valid types or properties. `summary.nodes` and
|
|
263
|
+
`summary.edges` count records in the store arrays, and `summary.errors` counts
|
|
264
|
+
reported issues.
|
|
265
|
+
|
|
266
|
+
If the store file does not exist, validation treats it as an empty graph. A
|
|
267
|
+
missing workspace or unreadable contract/store is reported in JSON with exit
|
|
268
|
+
code `4`; validation does not initialize or repair anything.
|
|
269
|
+
|
|
270
|
+
### `graph add-node`
|
|
271
|
+
|
|
272
|
+
```text
|
|
273
|
+
graph add-node ID NAME TYPE [--properties JSON] [--evidences JSON_ARRAY]
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
Create a node and append it to `.graph/graph.json`.
|
|
277
|
+
|
|
278
|
+
| Parameter | Meaning |
|
|
279
|
+
| --- | --- |
|
|
280
|
+
| `ID` | Required, unique node identifier. Must match `^[a-z0-9][a-z0-9._-]*$`: the first character is a lowercase ASCII letter or digit; later characters may also include `.`, `_`, and `-`. |
|
|
281
|
+
| `NAME` | Required display name, stored as supplied. |
|
|
282
|
+
| `TYPE` | Required entity type from `entities.json`; lookup is case-insensitive and the stored type uses the contract's canonical spelling. |
|
|
283
|
+
| `--properties JSON` | Complete properties object. Defaults to `{}`. Supplied keys must be defined in the entity contract, values must have the declared JSON type, and all required properties must be present. |
|
|
284
|
+
| `--evidences JSON_ARRAY` | Optional JSON array in which every item must be an object. Defaults to `[]`; evidence fields and nested values are user-defined. |
|
|
285
|
+
|
|
286
|
+
The node's metadata receives UTC `created_at` and `updated_at` timestamps.
|
|
287
|
+
The output is the complete node record, including `id`, `type`, `name`,
|
|
288
|
+
`properties`, `metadata`, and `evidences`.
|
|
289
|
+
|
|
290
|
+
Example:
|
|
291
|
+
|
|
292
|
+
```sh
|
|
293
|
+
graph add-node orders-api "Orders API" API \
|
|
294
|
+
--properties '{"language":"Python"}' \
|
|
295
|
+
--evidences '[{"source":"src/orders/api.py","locator":{"start_line":12,"end_line":28},"note":"API implementation"}]'
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### `graph add-edge`
|
|
299
|
+
|
|
300
|
+
```text
|
|
301
|
+
graph add-edge SOURCE_ID EDGE_TYPE TARGET_ID
|
|
302
|
+
[--description TEXT]
|
|
303
|
+
[--properties JSON]
|
|
304
|
+
[--evidences JSON_ARRAY]
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
Create a directed edge between existing nodes.
|
|
308
|
+
|
|
309
|
+
| Parameter | Meaning |
|
|
310
|
+
| --- | --- |
|
|
311
|
+
| `SOURCE_ID` | Required existing source node ID. |
|
|
312
|
+
| `EDGE_TYPE` | Required edge type from `edges.json`, case-insensitive; the stored spelling is canonical. |
|
|
313
|
+
| `TARGET_ID` | Required existing target node ID. |
|
|
314
|
+
| `--description TEXT` | Optional free-form relationship description; defaults to the empty string. If there is already any edge between the same endpoints, the new edge must have a non-empty description. |
|
|
315
|
+
| `--properties JSON` | Complete properties object. Defaults to `{}` and is checked against the edge type's property contract. |
|
|
316
|
+
| `--evidences JSON_ARRAY` | Optional array of evidence objects; defaults to `[]`. |
|
|
317
|
+
|
|
318
|
+
The edge contract must allow the source node's entity type in `source` and the
|
|
319
|
+
target node's entity type in `target`. An edge ID is generated as a UUID, and
|
|
320
|
+
the edge receives UTC creation/update timestamps.
|
|
321
|
+
|
|
322
|
+
Two edges with the same type, endpoints, and properties are rejected as
|
|
323
|
+
duplicates even if their descriptions differ. Any additional edge between the
|
|
324
|
+
same endpoints must have a non-empty description; for the same edge type,
|
|
325
|
+
properties must also differ to distinguish the edge. The output is the full
|
|
326
|
+
edge record, with `target_type` derived from the target node for CLI output.
|
|
327
|
+
|
|
328
|
+
Example:
|
|
329
|
+
|
|
330
|
+
```sh
|
|
331
|
+
graph add-edge orders-api CALLS stock-api \
|
|
332
|
+
--description "Checks stock availability" \
|
|
333
|
+
--properties '{"method":"GET"}' \
|
|
334
|
+
--evidences '[{"source":"src/orders/client.py","locator":{"start_line":20,"end_line":35}}]'
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
### `graph nodes`
|
|
338
|
+
|
|
339
|
+
```text
|
|
340
|
+
graph nodes [ID]
|
|
341
|
+
[--type TYPE[,TYPE...]]
|
|
342
|
+
[--properties JSON]
|
|
343
|
+
[--prefix TEXT] [--suffix TEXT] [--contains TEXT]
|
|
344
|
+
[--limit N] [--fields FIELD[,FIELD...]]
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
Get one node by ID or list/filter nodes.
|
|
348
|
+
|
|
349
|
+
| Parameter | Meaning |
|
|
350
|
+
| --- | --- |
|
|
351
|
+
| `ID` | Optional exact node ID. Returns the complete record directly, not a list envelope. It cannot be combined with `--properties` or `--fields`. |
|
|
352
|
+
| `--type TYPE[,TYPE...]` | Keep nodes whose entity type matches any listed type, case-insensitively. |
|
|
353
|
+
| `--properties JSON` | Keep nodes whose properties match every supplied key/value. Values are compared for equality; extra properties on a node are allowed. |
|
|
354
|
+
| `--prefix TEXT` | Case-insensitive prefix match against node `name`. |
|
|
355
|
+
| `--suffix TEXT` | Case-insensitive suffix match against node `name`. |
|
|
356
|
+
| `--contains TEXT` | Case-insensitive substring match against node `name`. |
|
|
357
|
+
| `--limit N` | Optional positive integer. Applied after filtering; `1` or greater. |
|
|
358
|
+
| `--fields FIELD[,FIELD...]` | Return only the selected fields, in the requested order. Allowed fields: `id`, `type`, `name`, `properties`, `metadata`, `evidences`. Not valid with an ID lookup. |
|
|
359
|
+
|
|
360
|
+
All list filters combine with AND, except multiple values within `--type`,
|
|
361
|
+
which combine with OR. List output is an object containing `rows`, `total`,
|
|
362
|
+
and `truncated`. `total` is the count after filtering but before the limit;
|
|
363
|
+
`truncated` is true if the limit omitted matches. Without `--fields`, rows
|
|
364
|
+
contain full node records. Node list order follows the order in `graph.json`.
|
|
365
|
+
|
|
366
|
+
Examples:
|
|
367
|
+
|
|
368
|
+
```sh
|
|
369
|
+
graph nodes
|
|
370
|
+
graph nodes orders-api
|
|
371
|
+
graph nodes --type=API,WORKER --contains=order --properties '{"language":"Python"}'
|
|
372
|
+
graph nodes --prefix=order --limit=10 --fields=id,name,type
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
### `graph edges`
|
|
376
|
+
|
|
377
|
+
```text
|
|
378
|
+
graph edges [EDGE_ID]
|
|
379
|
+
[--type TYPE[,TYPE...]]
|
|
380
|
+
[--properties JSON]
|
|
381
|
+
[--from SOURCE_ID] [--to TARGET_ID]
|
|
382
|
+
[--limit N]
|
|
383
|
+
[--fields FIELD[,FIELD...]]
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
Get one edge by its generated ID or list/filter edges.
|
|
387
|
+
|
|
388
|
+
| Parameter | Meaning |
|
|
389
|
+
| --- | --- |
|
|
390
|
+
| `EDGE_ID` | Optional exact edge ID. Returns the complete edge record directly and cannot be combined with filters. |
|
|
391
|
+
| `--type TYPE[,TYPE...]` | Keep edges whose type matches any listed contract type, case-insensitively. Each requested type must exist. |
|
|
392
|
+
| `--properties JSON` | Keep edges matching every supplied property key/value. |
|
|
393
|
+
| `--from SOURCE_ID` | Keep edges whose source is this existing node ID. |
|
|
394
|
+
| `--to TARGET_ID` | Keep edges whose target is this existing node ID. |
|
|
395
|
+
| `--limit N` | Optional positive integer. Applied after filtering; `1` or greater. |
|
|
396
|
+
| `--fields FIELD[,FIELD...]` | Return objects with only selected fields, in requested order. Allowed fields: `id`, `type`, `source`, `target`, `target_type`, `description`, `properties`, `metadata`, `evidences`. |
|
|
397
|
+
|
|
398
|
+
Filters combine with AND; multiple `--type` values combine with OR.
|
|
399
|
+
`--from` and `--to` can be used together. An unknown endpoint ID is an error.
|
|
400
|
+
List output uses the same `rows`, `total`, `truncated` envelope as `nodes`.
|
|
401
|
+
Without `--fields`, each row is the compact tuple
|
|
402
|
+
`[source_id, type, target_id, target_type]`; `target_type` is derived from the
|
|
403
|
+
target node, not stored on the edge. Rows are sorted by source ID, type, target
|
|
404
|
+
ID, then edge ID.
|
|
405
|
+
|
|
406
|
+
Examples:
|
|
407
|
+
|
|
408
|
+
```sh
|
|
409
|
+
graph edges --type=CALLS --from=orders-api --limit=10
|
|
410
|
+
graph edges --to=stock-api --properties '{"method":"GET"}' \
|
|
411
|
+
--fields=id,type,source,target,target_type,description,properties
|
|
412
|
+
graph edges 6c7f7d2c-22f0-49d2-a7f3-37d9b8cb0988
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
### `graph edit`
|
|
416
|
+
|
|
417
|
+
```text
|
|
418
|
+
graph edit node ID
|
|
419
|
+
[--name TEXT] [--properties JSON] [--evidences JSON_ARRAY]
|
|
420
|
+
|
|
421
|
+
graph edit edge EDGE_ID
|
|
422
|
+
[--description TEXT] [--properties JSON] [--evidences JSON_ARRAY]
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
Update a node or edge in place. IDs, node/edge types, and edge endpoints are
|
|
426
|
+
not editable.
|
|
427
|
+
|
|
428
|
+
For nodes:
|
|
429
|
+
|
|
430
|
+
- `ID` is the existing node ID.
|
|
431
|
+
- `--name TEXT` replaces the display name.
|
|
432
|
+
- `--properties JSON` replaces the entire properties object, not just selected
|
|
433
|
+
keys. The resulting object must satisfy the current entity contract.
|
|
434
|
+
- `--evidences JSON_ARRAY` replaces the complete evidence list; `[]` clears it.
|
|
435
|
+
|
|
436
|
+
For edges:
|
|
437
|
+
|
|
438
|
+
- `EDGE_ID` is the existing generated edge ID.
|
|
439
|
+
- `--description TEXT` replaces the description.
|
|
440
|
+
- `--properties JSON` replaces the entire properties object and must satisfy
|
|
441
|
+
the current edge contract.
|
|
442
|
+
- `--evidences JSON_ARRAY` replaces the complete evidence list; `[]` clears it.
|
|
443
|
+
|
|
444
|
+
At least one editable option is required. Omitted fields remain unchanged.
|
|
445
|
+
Metadata `updated_at` is refreshed after a successful edit. Edge edits also
|
|
446
|
+
recheck duplicate-edge and parallel-edge description rules. The command prints
|
|
447
|
+
the updated full record.
|
|
448
|
+
|
|
449
|
+
Examples:
|
|
450
|
+
|
|
451
|
+
```sh
|
|
452
|
+
graph edit node orders-api --name "Orders service"
|
|
453
|
+
graph edit node orders-api --properties '{"language":"Python","framework":"FastAPI"}'
|
|
454
|
+
graph edit edge 6c7f7d2c-22f0-49d2-a7f3-37d9b8cb0988 \
|
|
455
|
+
--description "Uses the stock lookup endpoint" --properties '{"method":"GET"}'
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
### `graph delete`
|
|
459
|
+
|
|
460
|
+
```text
|
|
461
|
+
graph delete node ID
|
|
462
|
+
graph delete edge EDGE_ID
|
|
463
|
+
graph delete edge SOURCE_ID EDGE_TYPE TARGET_ID
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
Delete a node or edge:
|
|
467
|
+
|
|
468
|
+
- `delete node ID` removes the node and every edge connected to it. The output
|
|
469
|
+
contains `deleted_node` and the number of removed `deleted_edges`.
|
|
470
|
+
- `delete edge EDGE_ID` deletes exactly one edge by ID.
|
|
471
|
+
- `delete edge SOURCE_ID EDGE_TYPE TARGET_ID` selects edges by type and
|
|
472
|
+
endpoints. If exactly one matches, it is deleted. If several match, none are
|
|
473
|
+
deleted; the CLI displays the candidate records and IDs so one can be
|
|
474
|
+
deleted by ID.
|
|
475
|
+
|
|
476
|
+
The tuple form requires both endpoint nodes to exist. Edge type lookup is
|
|
477
|
+
case-insensitive. Node and edge IDs cannot be supplied with `--id`; they are
|
|
478
|
+
positional. A successful deletion prints the deleted record. An ambiguous
|
|
479
|
+
edge selection returns exit code `2` and leaves the graph unchanged.
|
|
480
|
+
|
|
481
|
+
Examples:
|
|
482
|
+
|
|
483
|
+
```sh
|
|
484
|
+
graph delete node orders-api
|
|
485
|
+
graph delete edge 6c7f7d2c-22f0-49d2-a7f3-37d9b8cb0988
|
|
486
|
+
graph delete edge orders-api CALLS stock-api
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
### `graph traverse`
|
|
490
|
+
|
|
491
|
+
```text
|
|
492
|
+
graph traverse NODE_ID
|
|
493
|
+
[--depth N]
|
|
494
|
+
[--direction in|out|both]
|
|
495
|
+
[--edge TYPE[,TYPE...]]
|
|
496
|
+
[--limit N]
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
Perform a breadth-first traversal from one existing node.
|
|
500
|
+
|
|
501
|
+
| Parameter | Meaning |
|
|
502
|
+
| --- | --- |
|
|
503
|
+
| `NODE_ID` | Required anchor node; it is always included in the output. |
|
|
504
|
+
| `--depth N` | Maximum number of edge hops; positive integer, default `1`. |
|
|
505
|
+
| `--direction in|out|both` | Direction to follow at every hop; default `both`. `in` follows incoming edges to their source; `out` follows outgoing edges to their target. |
|
|
506
|
+
| `--edge TYPE[,TYPE...]` | Optional set of allowed edge types. Names are case-insensitive and must exist in the edge contract. |
|
|
507
|
+
| `--limit N` | Optional positive maximum number of reached nodes, excluding the anchor. Applied as nodes are reached. |
|
|
508
|
+
|
|
509
|
+
The result is compact JSON:
|
|
510
|
+
|
|
511
|
+
```json
|
|
512
|
+
{
|
|
513
|
+
"nodes": [["orders-api", "API", "Orders API"], ["stock-api", "API", "Stock API"]],
|
|
514
|
+
"edges": [["orders-api", "CALLS", "stock-api", "API"]],
|
|
515
|
+
"truncated": false
|
|
516
|
+
}
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
Node tuples are `[id, type, name]`; edge tuples are
|
|
520
|
+
`[source_id, type, target_id, target_type]`. Edge tuples preserve the stored
|
|
521
|
+
source-to-target orientation even when traversing `in`. The anchor is first;
|
|
522
|
+
other nodes and edges are ordered deterministically. The edge list can include
|
|
523
|
+
cross-links or cycle-closing edges encountered during expansion, not only the
|
|
524
|
+
edges of a traversal tree.
|
|
525
|
+
|
|
526
|
+
`truncated` is true only when the node limit excludes reachable nodes; merely
|
|
527
|
+
reaching `--depth` does not set it. If the limit cuts off a frontier, node IDs
|
|
528
|
+
are accepted in lexical order.
|
|
529
|
+
|
|
530
|
+
Example:
|
|
531
|
+
|
|
532
|
+
```sh
|
|
533
|
+
graph traverse orders-api --depth=2 --direction=out --edge=CALLS,PUBLISHES --limit=20
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
### `graph path`
|
|
537
|
+
|
|
538
|
+
```text
|
|
539
|
+
graph path SOURCE_ID TARGET_ID
|
|
540
|
+
[--direction out|in|both]
|
|
541
|
+
[--edge TYPE[,TYPE...]]
|
|
542
|
+
[--max-depth N]
|
|
543
|
+
[--limit N]
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
Find simple paths between two existing nodes. A simple path does not visit a
|
|
547
|
+
node more than once.
|
|
548
|
+
|
|
549
|
+
| Parameter | Meaning |
|
|
550
|
+
| --- | --- |
|
|
551
|
+
| `SOURCE_ID` | Required starting node ID. |
|
|
552
|
+
| `TARGET_ID` | Required destination node ID. |
|
|
553
|
+
| `--direction [out,in,both]` | Direction in which to follow edges; default `out`. `in` traverses incoming edges backward; `both` follows either orientation. Output edges retain their stored orientation. |
|
|
554
|
+
| `--edge TYPE[,TYPE...]` | Optional set of allowed edge types. Names are case-insensitive and must exist. |
|
|
555
|
+
| `--max-depth N` | Optional non-negative maximum hop count. If omitted, the search allows up to the number of graph nodes minus one hops. `0` permits only a zero-hop path when source and target are the same node. |
|
|
556
|
+
| `--limit N` | Positive maximum number of paths to return; default `1`. |
|
|
557
|
+
|
|
558
|
+
Paths are ordered shortest first with deterministic tie-breaking. The result
|
|
559
|
+
has `paths` and `truncated` fields. Each path contains `nodes` as
|
|
560
|
+
`[id, type, name]` tuples, `edges` as
|
|
561
|
+
`[edge_id, source_id, type, target_id, target_type]` tuples, and `hops`.
|
|
562
|
+
If there is no route, `paths` is empty. When source and target are the same
|
|
563
|
+
node, a zero-hop path is valid. `truncated` means another path was found
|
|
564
|
+
beyond the requested limit; it does not indicate that search work was capped.
|
|
565
|
+
Parallel edges can produce distinct paths.
|
|
566
|
+
|
|
567
|
+
Example:
|
|
568
|
+
|
|
569
|
+
```sh
|
|
570
|
+
graph path orders-api database --direction=both --edge=CALLS,READS \
|
|
571
|
+
--max-depth=6 --limit=5
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
Path search can enumerate many candidate simple paths in a dense graph. Use
|
|
575
|
+
`--max-depth`, `--edge`, and a modest `--limit` to narrow a query.
|
|
576
|
+
|
|
577
|
+
### `graph view`
|
|
578
|
+
|
|
579
|
+
```text
|
|
580
|
+
graph view [--no-open]
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
Generate a self-contained HTML visualization at `.graph/view.html`. The page
|
|
584
|
+
includes the graph records and contract descriptions and supports graph
|
|
585
|
+
exploration in a browser.
|
|
586
|
+
|
|
587
|
+
- Requires an initialized workspace.
|
|
588
|
+
- Overwrites the generated `view.html`; it does not modify `graph.json`.
|
|
589
|
+
- By default, asks the system browser to open the generated page.
|
|
590
|
+
- `--no-open` skips the browser-open attempt. It takes no value.
|
|
591
|
+
- Prints a JSON object containing the absolute output `path`, node and edge
|
|
592
|
+
counts, and `opened` status.
|
|
593
|
+
|
|
594
|
+
## Exit codes
|
|
595
|
+
|
|
596
|
+
| Code | Meaning |
|
|
597
|
+
| --- | --- |
|
|
598
|
+
| `0` | Command completed successfully; `validate` found no violations. |
|
|
599
|
+
| `2` | Usage or operation error, such as invalid arguments, invalid data for an operation, a missing initialized workspace, or ambiguous edge deletion. |
|
|
600
|
+
| `3` | A requested graph record was not found, or `validate` found contract/store violations. |
|
|
601
|
+
| `4` | `validate` could not run because the workspace, contract, or graph store was unavailable or unreadable. |
|
|
602
|
+
|
|
603
|
+
`validate` always prints a JSON result when it can handle the failure, including
|
|
604
|
+
for invalid or unavailable workspaces. Other errors are printed to standard
|
|
605
|
+
error.
|