laneguard 0.2.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.
- laneguard-0.2.0/PKG-INFO +239 -0
- laneguard-0.2.0/README.md +228 -0
- laneguard-0.2.0/laneguard/__init__.py +3 -0
- laneguard-0.2.0/laneguard/__main__.py +3 -0
- laneguard-0.2.0/laneguard/claims.py +266 -0
- laneguard-0.2.0/laneguard/cli.py +84 -0
- laneguard-0.2.0/laneguard/errors.py +17 -0
- laneguard-0.2.0/laneguard/gitio.py +117 -0
- laneguard-0.2.0/laneguard/mcp.py +173 -0
- laneguard-0.2.0/laneguard/plan.py +157 -0
- laneguard-0.2.0/laneguard/report.py +11 -0
- laneguard-0.2.0/laneguard/scan.py +183 -0
- laneguard-0.2.0/laneguard/schema.py +17 -0
- laneguard-0.2.0/laneguard/schemas/claims.schema.json +106 -0
- laneguard-0.2.0/laneguard/schemas/plan.schema.json +92 -0
- laneguard-0.2.0/laneguard/schemas/scan.schema.json +157 -0
- laneguard-0.2.0/laneguard.egg-info/PKG-INFO +239 -0
- laneguard-0.2.0/laneguard.egg-info/SOURCES.txt +30 -0
- laneguard-0.2.0/laneguard.egg-info/dependency_links.txt +1 -0
- laneguard-0.2.0/laneguard.egg-info/entry_points.txt +2 -0
- laneguard-0.2.0/laneguard.egg-info/requires.txt +4 -0
- laneguard-0.2.0/laneguard.egg-info/top_level.txt +1 -0
- laneguard-0.2.0/pyproject.toml +38 -0
- laneguard-0.2.0/setup.cfg +4 -0
- laneguard-0.2.0/tests/test_claims.py +523 -0
- laneguard-0.2.0/tests/test_cli.py +273 -0
- laneguard-0.2.0/tests/test_gitio.py +147 -0
- laneguard-0.2.0/tests/test_mcp.py +403 -0
- laneguard-0.2.0/tests/test_plan.py +267 -0
- laneguard-0.2.0/tests/test_report.py +12 -0
- laneguard-0.2.0/tests/test_scan.py +515 -0
- laneguard-0.2.0/tests/test_schema.py +141 -0
laneguard-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: laneguard
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Coordinate parallel coding agents: disjoint backlogs and conflict prediction for in-flight branches.
|
|
5
|
+
License: MIT
|
|
6
|
+
Requires-Python: >=3.12
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Provides-Extra: dev
|
|
9
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
10
|
+
Requires-Dist: ruff>=0.6; extra == "dev"
|
|
11
|
+
|
|
12
|
+
# laneguard
|
|
13
|
+
|
|
14
|
+
Keep parallel coding agents in their lanes.
|
|
15
|
+
|
|
16
|
+
- `laneguard plan TASKS_DIR` checks a backlog of task files for disjoint file ownership **before** work starts.
|
|
17
|
+
- `laneguard scan REPO` compares in-flight branches and predicts merge conflicts **before** integration.
|
|
18
|
+
- `laneguard mcp` exposes both to coding agents as MCP tools.
|
|
19
|
+
|
|
20
|
+
Standard library only. Git is used read-only. Output is deterministic and compact; `--json` is the contract.
|
|
21
|
+
|
|
22
|
+
**Status:** v0.2 includes the claims ledger, schema command, and packaging. See [docs/spec.md](docs/spec.md) for the specification and [AGENTS.md](AGENTS.md) if you are an agent working on this repository.
|
|
23
|
+
|
|
24
|
+
## Install
|
|
25
|
+
|
|
26
|
+
Install from GitHub now:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pip install "laneguard @ git+https://github.com/55kov/laneguard.git"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Once published to PyPI:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pip install laneguard
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Usage
|
|
39
|
+
|
|
40
|
+
Run these Bash examples from the repository root with Python 3.12+ available
|
|
41
|
+
as `python3` and Git installed. Setup creates only disposable files under `/tmp`;
|
|
42
|
+
`laneguard` itself uses Git read-only. Run the blocks in order. Each output block
|
|
43
|
+
contains actual stdout, including the exit status printed by `printf`.
|
|
44
|
+
|
|
45
|
+
### Plan: explicit task ownership
|
|
46
|
+
|
|
47
|
+
Create two disjoint tasks, including one file that does not exist yet:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
example_dir=$(mktemp -d)
|
|
51
|
+
mkdir "$example_dir/tasks"
|
|
52
|
+
printf 'Files: README.md\n' > "$example_dir/tasks/docs.md"
|
|
53
|
+
printf 'Files: future.py\n' > "$example_dir/tasks/feature.md"
|
|
54
|
+
python3 -m laneguard plan "$example_dir/tasks"
|
|
55
|
+
printf 'exit: %s\n' "$?"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
```text
|
|
59
|
+
plan: disjoint
|
|
60
|
+
exit: 0
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
The default text is concise. Use `--repo .` to classify claims against Git's
|
|
64
|
+
tracked files, and `--json` for the structured `exists`/`new` arrays (`--repo`
|
|
65
|
+
also prints classifications in text mode). New files are allowed:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
python3 -m laneguard plan "$example_dir/tasks" --repo . --json
|
|
69
|
+
printf 'exit: %s\n' "$?"
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
{"kind":"plan","version":1,"tasks":[{"id":"docs","files":["README.md"],"exists":["README.md"],"new":[]},{"id":"feature","files":["future.py"],"exists":[],"new":["future.py"]}],"overlaps":[],"warnings":[]}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
```text
|
|
77
|
+
exit: 0
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Add a competing claim to see an overlap:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
printf 'Files: README.md\n' > "$example_dir/tasks/other.md"
|
|
84
|
+
python3 -m laneguard plan "$example_dir/tasks"
|
|
85
|
+
printf 'exit: %s\n' "$?"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
```text
|
|
89
|
+
overlap docs other: README.md
|
|
90
|
+
exit: 2
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Scan: a fully specified clean fixture
|
|
94
|
+
|
|
95
|
+
This creates a temporary bare repository with an empty base commit and two local
|
|
96
|
+
task branches pointing to it. Neither branch has changes. The fixture setup
|
|
97
|
+
writes only to the temporary repository, never the project repository:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
git init --bare --quiet "$example_dir/repo.git"
|
|
101
|
+
git -C "$example_dir/repo.git" fast-import --quiet <<'GIT'
|
|
102
|
+
commit refs/heads/main
|
|
103
|
+
mark :1
|
|
104
|
+
committer Example <example@example.com> 0 +0000
|
|
105
|
+
data 7
|
|
106
|
+
fixture
|
|
107
|
+
|
|
108
|
+
reset refs/heads/task/one
|
|
109
|
+
from :1
|
|
110
|
+
|
|
111
|
+
reset refs/heads/task/two
|
|
112
|
+
from :1
|
|
113
|
+
|
|
114
|
+
GIT
|
|
115
|
+
python3 -m laneguard scan "$example_dir/repo.git" --base main --branches 'task/*' --detail
|
|
116
|
+
printf 'exit: %s\n' "$?"
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
```text
|
|
120
|
+
scan: no likely conflicts
|
|
121
|
+
task/one: (no changes)
|
|
122
|
+
task/two: (no changes)
|
|
123
|
+
exit: 0
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
`--detail` lists each selected branch's changed files; omit it for compact
|
|
127
|
+
findings only. Use `--json` for structured hunk ranges and merge-base hashes.
|
|
128
|
+
Branches editing the same file in separate regions receive an informational
|
|
129
|
+
`shared-file` verdict, which does not cause exit 2. Overlapping ranges or ranges
|
|
130
|
+
within `--near` lines (default 3), and delete/rename versus modify cases, can
|
|
131
|
+
produce `likely-conflict` and exit 2.
|
|
132
|
+
|
|
133
|
+
For both `plan` and `scan`, exit **0** means no overlaps or likely conflicts,
|
|
134
|
+
**2** means overlaps or likely conflicts were found, and **1** means a usage,
|
|
135
|
+
input, or Git error. Exit 2 is a finding, not a command failure.
|
|
136
|
+
|
|
137
|
+
### MCP: a finite stdio round trip
|
|
138
|
+
|
|
139
|
+
MCP uses newline-delimited JSON-RPC 2.0. Pipe a concrete `ping` request; closing
|
|
140
|
+
stdin terminates the server at EOF:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
printf '%s\n' '{"jsonrpc":"2.0","id":1,"method":"ping"}' | python3 -m laneguard mcp
|
|
144
|
+
printf 'exit: %s\n' "$?"
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
```text
|
|
148
|
+
{"jsonrpc":"2.0","id":1,"result":{}}
|
|
149
|
+
exit: 0
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
The server also supports `initialize`, `tools/list`, and `tools/call` for
|
|
153
|
+
`laneguard_plan` and `laneguard_scan`. Tool arguments mirror the CLI inputs (for example,
|
|
154
|
+
`tasks_dir` for plan and `repo`, `base`, `branches`, `near`, `detail` for scan).
|
|
155
|
+
Tool results already include JSON, so no `json` argument is needed. CLI finding
|
|
156
|
+
exit codes apply to CLI invocations; MCP returns findings and tool errors in
|
|
157
|
+
JSON-RPC responses.
|
|
158
|
+
|
|
159
|
+
### Claims
|
|
160
|
+
|
|
161
|
+
Claim your task's files in a shared ledger before starting work.
|
|
162
|
+
If another owner holds an overlapping path, wait for their release before claiming
|
|
163
|
+
it and making changes.
|
|
164
|
+
Concurrent writers are serialized by an exclusive `FILE.lock` (retrying for up to
|
|
165
|
+
10 seconds, reclaiming locks older than 60 seconds), and writes atomically replace
|
|
166
|
+
the ledger using a temporary file in the same directory.
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
python3 -m laneguard claim --ledger "$example_dir/claims.json" --owner docs README.md
|
|
170
|
+
printf 'exit: %s\n' "$?"
|
|
171
|
+
python3 -m laneguard claim --ledger "$example_dir/claims.json" --owner feature README.md
|
|
172
|
+
printf 'exit: %s\n' "$?"
|
|
173
|
+
python3 -m laneguard release --ledger "$example_dir/claims.json" --owner docs README.md
|
|
174
|
+
printf 'exit: %s\n' "$?"
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
```text
|
|
178
|
+
claimed docs: README.md
|
|
179
|
+
exit: 0
|
|
180
|
+
refused feature README.md: held by docs (README.md)
|
|
181
|
+
exit: 2
|
|
182
|
+
released docs: README.md
|
|
183
|
+
exit: 0
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
List the live claims as JSON, trimming the temporary ledger path from the output:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
python3 -m laneguard claims --ledger "$example_dir/claims.json" --json | python3 -c 'import json, sys; d = json.load(sys.stdin); del d["ledger"]; print(json.dumps(d, separators=(",", ":")))'
|
|
190
|
+
printf 'exit: %s\n' "$?"
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
```json
|
|
194
|
+
{"kind":"claims","version":1,"claims":[],"refused":[],"released":[],"warnings":[]}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
```text
|
|
198
|
+
exit: 0
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Schemas
|
|
202
|
+
|
|
203
|
+
Print the packaged JSON Schema for `plan`, `scan`, or `claims`; here are the first
|
|
204
|
+
ten lines for `plan`:
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
python3 -m laneguard schema plan | head -n 10
|
|
208
|
+
printf 'exit: %s\n' "$?"
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
```text
|
|
212
|
+
{
|
|
213
|
+
"$id": "https://laneguard.dev/schemas/plan.schema.json",
|
|
214
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
215
|
+
"additionalProperties": false,
|
|
216
|
+
"properties": {
|
|
217
|
+
"kind": {
|
|
218
|
+
"const": "plan",
|
|
219
|
+
"type": "string"
|
|
220
|
+
},
|
|
221
|
+
"overlaps": {
|
|
222
|
+
exit: 0
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
In CI, save the full `laneguard schema <kind>` output and validate the corresponding
|
|
226
|
+
`--json` output with a JSON Schema draft 2020-12 validator.
|
|
227
|
+
|
|
228
|
+
Remove the disposable fixtures when finished:
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
rm -rf "$example_dir"
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## Development
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
python -m venv .venv && .venv/bin/pip install -e '.[dev]'
|
|
238
|
+
PY=.venv/bin/python sh check.sh
|
|
239
|
+
```
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
# laneguard
|
|
2
|
+
|
|
3
|
+
Keep parallel coding agents in their lanes.
|
|
4
|
+
|
|
5
|
+
- `laneguard plan TASKS_DIR` checks a backlog of task files for disjoint file ownership **before** work starts.
|
|
6
|
+
- `laneguard scan REPO` compares in-flight branches and predicts merge conflicts **before** integration.
|
|
7
|
+
- `laneguard mcp` exposes both to coding agents as MCP tools.
|
|
8
|
+
|
|
9
|
+
Standard library only. Git is used read-only. Output is deterministic and compact; `--json` is the contract.
|
|
10
|
+
|
|
11
|
+
**Status:** v0.2 includes the claims ledger, schema command, and packaging. See [docs/spec.md](docs/spec.md) for the specification and [AGENTS.md](AGENTS.md) if you are an agent working on this repository.
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
Install from GitHub now:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pip install "laneguard @ git+https://github.com/55kov/laneguard.git"
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Once published to PyPI:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pip install laneguard
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
Run these Bash examples from the repository root with Python 3.12+ available
|
|
30
|
+
as `python3` and Git installed. Setup creates only disposable files under `/tmp`;
|
|
31
|
+
`laneguard` itself uses Git read-only. Run the blocks in order. Each output block
|
|
32
|
+
contains actual stdout, including the exit status printed by `printf`.
|
|
33
|
+
|
|
34
|
+
### Plan: explicit task ownership
|
|
35
|
+
|
|
36
|
+
Create two disjoint tasks, including one file that does not exist yet:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
example_dir=$(mktemp -d)
|
|
40
|
+
mkdir "$example_dir/tasks"
|
|
41
|
+
printf 'Files: README.md\n' > "$example_dir/tasks/docs.md"
|
|
42
|
+
printf 'Files: future.py\n' > "$example_dir/tasks/feature.md"
|
|
43
|
+
python3 -m laneguard plan "$example_dir/tasks"
|
|
44
|
+
printf 'exit: %s\n' "$?"
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
```text
|
|
48
|
+
plan: disjoint
|
|
49
|
+
exit: 0
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The default text is concise. Use `--repo .` to classify claims against Git's
|
|
53
|
+
tracked files, and `--json` for the structured `exists`/`new` arrays (`--repo`
|
|
54
|
+
also prints classifications in text mode). New files are allowed:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
python3 -m laneguard plan "$example_dir/tasks" --repo . --json
|
|
58
|
+
printf 'exit: %s\n' "$?"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{"kind":"plan","version":1,"tasks":[{"id":"docs","files":["README.md"],"exists":["README.md"],"new":[]},{"id":"feature","files":["future.py"],"exists":[],"new":["future.py"]}],"overlaps":[],"warnings":[]}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
```text
|
|
66
|
+
exit: 0
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Add a competing claim to see an overlap:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
printf 'Files: README.md\n' > "$example_dir/tasks/other.md"
|
|
73
|
+
python3 -m laneguard plan "$example_dir/tasks"
|
|
74
|
+
printf 'exit: %s\n' "$?"
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
```text
|
|
78
|
+
overlap docs other: README.md
|
|
79
|
+
exit: 2
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Scan: a fully specified clean fixture
|
|
83
|
+
|
|
84
|
+
This creates a temporary bare repository with an empty base commit and two local
|
|
85
|
+
task branches pointing to it. Neither branch has changes. The fixture setup
|
|
86
|
+
writes only to the temporary repository, never the project repository:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
git init --bare --quiet "$example_dir/repo.git"
|
|
90
|
+
git -C "$example_dir/repo.git" fast-import --quiet <<'GIT'
|
|
91
|
+
commit refs/heads/main
|
|
92
|
+
mark :1
|
|
93
|
+
committer Example <example@example.com> 0 +0000
|
|
94
|
+
data 7
|
|
95
|
+
fixture
|
|
96
|
+
|
|
97
|
+
reset refs/heads/task/one
|
|
98
|
+
from :1
|
|
99
|
+
|
|
100
|
+
reset refs/heads/task/two
|
|
101
|
+
from :1
|
|
102
|
+
|
|
103
|
+
GIT
|
|
104
|
+
python3 -m laneguard scan "$example_dir/repo.git" --base main --branches 'task/*' --detail
|
|
105
|
+
printf 'exit: %s\n' "$?"
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
```text
|
|
109
|
+
scan: no likely conflicts
|
|
110
|
+
task/one: (no changes)
|
|
111
|
+
task/two: (no changes)
|
|
112
|
+
exit: 0
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
`--detail` lists each selected branch's changed files; omit it for compact
|
|
116
|
+
findings only. Use `--json` for structured hunk ranges and merge-base hashes.
|
|
117
|
+
Branches editing the same file in separate regions receive an informational
|
|
118
|
+
`shared-file` verdict, which does not cause exit 2. Overlapping ranges or ranges
|
|
119
|
+
within `--near` lines (default 3), and delete/rename versus modify cases, can
|
|
120
|
+
produce `likely-conflict` and exit 2.
|
|
121
|
+
|
|
122
|
+
For both `plan` and `scan`, exit **0** means no overlaps or likely conflicts,
|
|
123
|
+
**2** means overlaps or likely conflicts were found, and **1** means a usage,
|
|
124
|
+
input, or Git error. Exit 2 is a finding, not a command failure.
|
|
125
|
+
|
|
126
|
+
### MCP: a finite stdio round trip
|
|
127
|
+
|
|
128
|
+
MCP uses newline-delimited JSON-RPC 2.0. Pipe a concrete `ping` request; closing
|
|
129
|
+
stdin terminates the server at EOF:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
printf '%s\n' '{"jsonrpc":"2.0","id":1,"method":"ping"}' | python3 -m laneguard mcp
|
|
133
|
+
printf 'exit: %s\n' "$?"
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
```text
|
|
137
|
+
{"jsonrpc":"2.0","id":1,"result":{}}
|
|
138
|
+
exit: 0
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
The server also supports `initialize`, `tools/list`, and `tools/call` for
|
|
142
|
+
`laneguard_plan` and `laneguard_scan`. Tool arguments mirror the CLI inputs (for example,
|
|
143
|
+
`tasks_dir` for plan and `repo`, `base`, `branches`, `near`, `detail` for scan).
|
|
144
|
+
Tool results already include JSON, so no `json` argument is needed. CLI finding
|
|
145
|
+
exit codes apply to CLI invocations; MCP returns findings and tool errors in
|
|
146
|
+
JSON-RPC responses.
|
|
147
|
+
|
|
148
|
+
### Claims
|
|
149
|
+
|
|
150
|
+
Claim your task's files in a shared ledger before starting work.
|
|
151
|
+
If another owner holds an overlapping path, wait for their release before claiming
|
|
152
|
+
it and making changes.
|
|
153
|
+
Concurrent writers are serialized by an exclusive `FILE.lock` (retrying for up to
|
|
154
|
+
10 seconds, reclaiming locks older than 60 seconds), and writes atomically replace
|
|
155
|
+
the ledger using a temporary file in the same directory.
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
python3 -m laneguard claim --ledger "$example_dir/claims.json" --owner docs README.md
|
|
159
|
+
printf 'exit: %s\n' "$?"
|
|
160
|
+
python3 -m laneguard claim --ledger "$example_dir/claims.json" --owner feature README.md
|
|
161
|
+
printf 'exit: %s\n' "$?"
|
|
162
|
+
python3 -m laneguard release --ledger "$example_dir/claims.json" --owner docs README.md
|
|
163
|
+
printf 'exit: %s\n' "$?"
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
```text
|
|
167
|
+
claimed docs: README.md
|
|
168
|
+
exit: 0
|
|
169
|
+
refused feature README.md: held by docs (README.md)
|
|
170
|
+
exit: 2
|
|
171
|
+
released docs: README.md
|
|
172
|
+
exit: 0
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
List the live claims as JSON, trimming the temporary ledger path from the output:
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
python3 -m laneguard claims --ledger "$example_dir/claims.json" --json | python3 -c 'import json, sys; d = json.load(sys.stdin); del d["ledger"]; print(json.dumps(d, separators=(",", ":")))'
|
|
179
|
+
printf 'exit: %s\n' "$?"
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
```json
|
|
183
|
+
{"kind":"claims","version":1,"claims":[],"refused":[],"released":[],"warnings":[]}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
```text
|
|
187
|
+
exit: 0
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Schemas
|
|
191
|
+
|
|
192
|
+
Print the packaged JSON Schema for `plan`, `scan`, or `claims`; here are the first
|
|
193
|
+
ten lines for `plan`:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
python3 -m laneguard schema plan | head -n 10
|
|
197
|
+
printf 'exit: %s\n' "$?"
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
```text
|
|
201
|
+
{
|
|
202
|
+
"$id": "https://laneguard.dev/schemas/plan.schema.json",
|
|
203
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
204
|
+
"additionalProperties": false,
|
|
205
|
+
"properties": {
|
|
206
|
+
"kind": {
|
|
207
|
+
"const": "plan",
|
|
208
|
+
"type": "string"
|
|
209
|
+
},
|
|
210
|
+
"overlaps": {
|
|
211
|
+
exit: 0
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
In CI, save the full `laneguard schema <kind>` output and validate the corresponding
|
|
215
|
+
`--json` output with a JSON Schema draft 2020-12 validator.
|
|
216
|
+
|
|
217
|
+
Remove the disposable fixtures when finished:
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
rm -rf "$example_dir"
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## Development
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
python -m venv .venv && .venv/bin/pip install -e '.[dev]'
|
|
227
|
+
PY=.venv/bin/python sh check.sh
|
|
228
|
+
```
|