provenance-cli 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.
- provenance_cli-0.1.0/LICENSE +21 -0
- provenance_cli-0.1.0/PKG-INFO +423 -0
- provenance_cli-0.1.0/README.md +397 -0
- provenance_cli-0.1.0/pyproject.toml +38 -0
- provenance_cli-0.1.0/setup.cfg +4 -0
- provenance_cli-0.1.0/src/prov/__init__.py +4 -0
- provenance_cli-0.1.0/src/prov/cli.py +105 -0
- provenance_cli-0.1.0/src/prov/commands/__init__.py +32 -0
- provenance_cli-0.1.0/src/prov/commands/check_slug.py +27 -0
- provenance_cli-0.1.0/src/prov/commands/context.py +74 -0
- provenance_cli-0.1.0/src/prov/commands/diff.py +106 -0
- provenance_cli-0.1.0/src/prov/commands/domain.py +57 -0
- provenance_cli-0.1.0/src/prov/commands/find.py +31 -0
- provenance_cli-0.1.0/src/prov/commands/impact.py +70 -0
- provenance_cli-0.1.0/src/prov/commands/init.py +41 -0
- provenance_cli-0.1.0/src/prov/commands/orient.py +62 -0
- provenance_cli-0.1.0/src/prov/commands/rebuild.py +57 -0
- provenance_cli-0.1.0/src/prov/commands/reconcile.py +62 -0
- provenance_cli-0.1.0/src/prov/commands/scope.py +70 -0
- provenance_cli-0.1.0/src/prov/commands/sync.py +201 -0
- provenance_cli-0.1.0/src/prov/commands/validate.py +111 -0
- provenance_cli-0.1.0/src/prov/commands/write.py +135 -0
- provenance_cli-0.1.0/src/prov/indexing.py +119 -0
- provenance_cli-0.1.0/src/prov/model.py +55 -0
- provenance_cli-0.1.0/src/prov/spec_io.py +401 -0
- provenance_cli-0.1.0/src/prov/writer.py +180 -0
- provenance_cli-0.1.0/src/provenance_cli.egg-info/PKG-INFO +423 -0
- provenance_cli-0.1.0/src/provenance_cli.egg-info/SOURCES.txt +29 -0
- provenance_cli-0.1.0/src/provenance_cli.egg-info/dependency_links.txt +1 -0
- provenance_cli-0.1.0/src/provenance_cli.egg-info/entry_points.txt +2 -0
- provenance_cli-0.1.0/src/provenance_cli.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025
|
|
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.
|
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: provenance-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Living requirements index + CLI for spec-driven development
|
|
5
|
+
Author: Provenance
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/nndn/Provenance
|
|
8
|
+
Project-URL: Repository, https://github.com/nndn/Provenance
|
|
9
|
+
Keywords: spec,requirements,provenance,cli,spec-driven
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Software Development
|
|
22
|
+
Requires-Python: >=3.9
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Dynamic: license-file
|
|
26
|
+
|
|
27
|
+
# Provenance
|
|
28
|
+
|
|
29
|
+
> Living requirements index + CLI for spec-driven development. Works with any AI agent.
|
|
30
|
+
|
|
31
|
+
**Provenance** (prov) keeps your requirements in plain markdown next to your code, gives you a CLI to query them, and teaches your AI agent to read before it writes.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Installation
|
|
36
|
+
|
|
37
|
+
**Requirements:** Python 3.9+
|
|
38
|
+
|
|
39
|
+
### Install the `prov` CLI (recommended)
|
|
40
|
+
|
|
41
|
+
Install from PyPI (after release) or GitHub:
|
|
42
|
+
|
|
43
|
+
| Platform | Command |
|
|
44
|
+
|----------|---------|
|
|
45
|
+
| **macOS / Linux / Windows (PyPI)** | `pipx install provenance-cli` |
|
|
46
|
+
| **macOS / Linux (GitHub)** | `pipx install 'provenance-cli @ git+https://github.com/nndn/Provenance.git'` |
|
|
47
|
+
| **Any (pip)** | `pip install provenance-cli` or `pip install 'provenance-cli @ git+https://github.com/nndn/Provenance.git'` |
|
|
48
|
+
|
|
49
|
+
**Recommendation:** Use [pipx](https://pypa.github.io/pipx/) for CLI tools — it installs `prov` in an isolated environment without affecting your project dependencies.
|
|
50
|
+
|
|
51
|
+
```sh
|
|
52
|
+
# Install pipx first (if needed)
|
|
53
|
+
# macOS: brew install pipx && pipx ensurepath
|
|
54
|
+
# Linux: apt install pipx # or your package manager
|
|
55
|
+
# Windows: pip install pipx && pipx ensurepath
|
|
56
|
+
|
|
57
|
+
pipx install provenance-cli # from PyPI (recommended)
|
|
58
|
+
# or, before release:
|
|
59
|
+
pipx install 'provenance-cli @ git+https://github.com/nndn/Provenance.git'
|
|
60
|
+
prov --help
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
To install a specific version:
|
|
64
|
+
|
|
65
|
+
```sh
|
|
66
|
+
pipx install 'provenance-cli==0.1.0' # from PyPI
|
|
67
|
+
pipx install 'provenance-cli @ git+https://github.com/nndn/Provenance.git@v0.1.0' # from GitHub
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Install into a project (copy prov into your repo)
|
|
71
|
+
|
|
72
|
+
If you prefer to copy the CLI into your project instead of a global install:
|
|
73
|
+
|
|
74
|
+
```sh
|
|
75
|
+
git clone https://github.com/nndn/Provenance.git /tmp/provenance
|
|
76
|
+
cd /path/to/your-project
|
|
77
|
+
sh /tmp/provenance/install.sh
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
This creates `prov/prov.py` and `prov/CONTEXT.md` in your project. Run with:
|
|
81
|
+
|
|
82
|
+
```sh
|
|
83
|
+
python prov/prov.py orient
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Publishing to PyPI
|
|
89
|
+
|
|
90
|
+
Releases are published automatically when you create a GitHub release. One-time setup:
|
|
91
|
+
|
|
92
|
+
1. Create an account at [pypi.org](https://pypi.org) and [test.pypi.org](https://test.pypi.org) (optional, for test releases).
|
|
93
|
+
|
|
94
|
+
2. Enable trusted publishing on PyPI:
|
|
95
|
+
- Create a new project at pypi.org (name: `provenance-cli`) or use an existing one.
|
|
96
|
+
- Go to **Your project** → **Publishing** → **Add a new pending publisher**.
|
|
97
|
+
- Owner: `nndn`, Repository: `Provenance`, Workflow: `publish-pypi.yml`.
|
|
98
|
+
|
|
99
|
+
3. Create a release:
|
|
100
|
+
```sh
|
|
101
|
+
git tag v0.1.0
|
|
102
|
+
git push origin v0.1.0
|
|
103
|
+
```
|
|
104
|
+
Then create the release on GitHub ( Releases → Create a new release → Choose the tag).
|
|
105
|
+
|
|
106
|
+
The workflow builds and publishes to PyPI on release publish.
|
|
107
|
+
|
|
108
|
+
**Manual publish:**
|
|
109
|
+
```sh
|
|
110
|
+
pip install build twine
|
|
111
|
+
python -m build
|
|
112
|
+
twine upload dist/*
|
|
113
|
+
```
|
|
114
|
+
(requires `TWINE_USERNAME` and `TWINE_PASSWORD` or API token.)
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## What you get
|
|
119
|
+
|
|
120
|
+
| File | Purpose |
|
|
121
|
+
|---|---|
|
|
122
|
+
| `prov/prov.py` | CLI — scope, context, impact, validate, diff, write, reconcile |
|
|
123
|
+
| `agent.md` | Agent rules — drop into Cursor, Claude, or any agent config |
|
|
124
|
+
| `scripts/install-spec-pre-commit.sh` | Git hook — validates spec on every commit |
|
|
125
|
+
|
|
126
|
+
No external dependencies. Python 3.9+. Everything is plain text — grep always works.
|
|
127
|
+
|
|
128
|
+
**Repo structure (for contributors):** CLI source lives in `src/prov.py`. This repo's own spec (meta) is in `specs/`. After install, user projects get `prov/prov.py` (copied from `src/prov.py`) and use `prov/` for their spec files. To run the CLI from this repo: `SPEC_DIR=specs python src/prov.py <command>`.
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Quick start
|
|
133
|
+
|
|
134
|
+
```sh
|
|
135
|
+
# Option A: Install CLI globally (from GitHub)
|
|
136
|
+
pipx install provenance-cli
|
|
137
|
+
|
|
138
|
+
# Option B: Install into your project
|
|
139
|
+
git clone https://github.com/nndn/Provenance.git /tmp/provenance
|
|
140
|
+
cd /path/to/your-project
|
|
141
|
+
sh /tmp/provenance/install.sh
|
|
142
|
+
|
|
143
|
+
# Then: edit prov/CONTEXT.md (or prov/CONTEXT.md) and run
|
|
144
|
+
prov orient # if installed globally
|
|
145
|
+
# or
|
|
146
|
+
python prov/prov.py orient # if using project-local copy
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
After install:
|
|
150
|
+
|
|
151
|
+
```
|
|
152
|
+
your-project/
|
|
153
|
+
prov/
|
|
154
|
+
CONTEXT.md ← edit this: project name, purpose, domain map
|
|
155
|
+
prov.py ← the CLI
|
|
156
|
+
agent.md ← copy to your AI agent config
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Set up your AI agent
|
|
162
|
+
|
|
163
|
+
Copy `agent.md` to wherever your agent reads rules:
|
|
164
|
+
|
|
165
|
+
| Agent | Location |
|
|
166
|
+
|---|---|
|
|
167
|
+
| Cursor | `.cursorrules` or `.cursor/rules/prov.md` |
|
|
168
|
+
| Claude Code | `CLAUDE.md` |
|
|
169
|
+
| Codex / GPT | `AGENTS.md` |
|
|
170
|
+
| Any | append to your existing rules file |
|
|
171
|
+
|
|
172
|
+
Once the agent reads `agent.md`, it will automatically call `prov scope` before touching code, `prov validate` before committing, and `prov diff` for human review.
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## CLI
|
|
177
|
+
|
|
178
|
+
Run `prov <command>` (if installed globally) or `python prov/prov.py <command>` (project-local).
|
|
179
|
+
|
|
180
|
+
```sh
|
|
181
|
+
prov orient # start every session here
|
|
182
|
+
|
|
183
|
+
prov scope <path> # what governs this file or directory?
|
|
184
|
+
prov context <slug> # full entry: statement, provenance, deps, code refs
|
|
185
|
+
prov impact <slug> # blast radius before changing anything
|
|
186
|
+
|
|
187
|
+
prov find <keywords> # search when you don't know the slug
|
|
188
|
+
prov domain <name> # load a full domain
|
|
189
|
+
|
|
190
|
+
prov check-slug <slug> # is this slug available?
|
|
191
|
+
prov write # add entries (JSON input, validates before writing)
|
|
192
|
+
|
|
193
|
+
prov validate # run before every commit — zero errors only
|
|
194
|
+
prov diff [ref] # semantic change manifest vs HEAD or any ref
|
|
195
|
+
prov reconcile <path> # detect code↔spec drift
|
|
196
|
+
prov rebuild # rebuild .spec/ cache from files
|
|
197
|
+
|
|
198
|
+
prov init # scaffold CONTEXT.md in a new project
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## What a spec entry looks like
|
|
204
|
+
|
|
205
|
+
```
|
|
206
|
+
session-expiry: Sessions expire after 30 days of inactivity.
|
|
207
|
+
> "standard session timeout, nothing crazy"
|
|
208
|
+
! assumed 30 days — "nothing crazy" is unconfirmed
|
|
209
|
+
@ C:jwt-stateless
|
|
210
|
+
~ src/middleware/session.py:44
|
|
211
|
+
~ src/middleware/session.py:101
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
| Part | Meaning |
|
|
215
|
+
|---|---|
|
|
216
|
+
| `session-expiry` | Slug — permanent, globally unique, used in `spec:` backlinks in code |
|
|
217
|
+
| Statement | What the system does. Current state only. Never "previously", "changed from". |
|
|
218
|
+
| `>` | Provenance — user's words where possible. Required on every entry. |
|
|
219
|
+
| `!` | Assumption the agent filled in — needs user confirmation before removing. |
|
|
220
|
+
| `@` | This entry depends on another slug. |
|
|
221
|
+
| `~` | Code file implementing this. One line per file. |
|
|
222
|
+
| `[planned]` | Not yet coded. Remove when implemented, add `~` lines. |
|
|
223
|
+
|
|
224
|
+
**Node types (column 0):**
|
|
225
|
+
|
|
226
|
+
```
|
|
227
|
+
slug: requirement — observable behavior
|
|
228
|
+
C:slug: constraint — non-negotiable rule
|
|
229
|
+
Q:slug: question — unresolved decision blocking implementation
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Domain file structure
|
|
233
|
+
|
|
234
|
+
```markdown
|
|
235
|
+
# Auth
|
|
236
|
+
|
|
237
|
+
> OAuth-based auth and stateless JWT sessions.
|
|
238
|
+
|
|
239
|
+
## Constraints
|
|
240
|
+
|
|
241
|
+
C:oauth-only: OAuth only — no email/password.
|
|
242
|
+
|
|
243
|
+
> "I don't want to deal with password resets"
|
|
244
|
+
|
|
245
|
+
## Requirements
|
|
246
|
+
|
|
247
|
+
google-login: Users authenticate via Google OAuth.
|
|
248
|
+
|
|
249
|
+
> "we'll just do Google login for now"
|
|
250
|
+
> @ C:oauth-only
|
|
251
|
+
> ~ src/api/auth/google.py
|
|
252
|
+
|
|
253
|
+
session-expiry: Sessions expire after 30 days of inactivity.
|
|
254
|
+
|
|
255
|
+
> "standard session timeout, nothing crazy"
|
|
256
|
+
! assumed 30 days — unconfirmed
|
|
257
|
+
@ C:jwt-stateless
|
|
258
|
+
~ src/middleware/session.py:44
|
|
259
|
+
|
|
260
|
+
## Open Questions
|
|
261
|
+
|
|
262
|
+
Q:admin-scope: Does admin-revoke apply to one session or all user sessions?
|
|
263
|
+
|
|
264
|
+
> blocks: admin-revoke
|
|
265
|
+
|
|
266
|
+
## Out of scope
|
|
267
|
+
|
|
268
|
+
MFA, SSO/SAML.
|
|
269
|
+
|
|
270
|
+
## Refs
|
|
271
|
+
|
|
272
|
+
~ src/api/auth/
|
|
273
|
+
~ src/middleware/session.py
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
## Code backlinks
|
|
279
|
+
|
|
280
|
+
Every function or block that implements a spec entry carries a `spec:` comment:
|
|
281
|
+
|
|
282
|
+
```python
|
|
283
|
+
# spec: session-expiry
|
|
284
|
+
def refresh_session(token: str) -> Session: ...
|
|
285
|
+
|
|
286
|
+
# spec: billing-cap, C:usage-hard-limit
|
|
287
|
+
class PlanLimitMiddleware: ...
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
```typescript
|
|
291
|
+
// spec: admin-revoke
|
|
292
|
+
async function revokeSession(userId: string): Promise<void>
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
`prov validate` checks that every `spec:` slug in code has a matching entry. `prov reconcile` surfaces drift when code and spec get out of sync.
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## Pre-commit hook
|
|
300
|
+
|
|
301
|
+
```sh
|
|
302
|
+
./scripts/install-spec-pre-commit.sh
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
When spec files are staged, the hook:
|
|
306
|
+
1. Runs `prov validate` — blocks commit on any error
|
|
307
|
+
2. Runs `prov rebuild` — regenerates `.spec/` cache
|
|
308
|
+
3. Stages `.spec/` automatically
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
## Adding a new domain
|
|
313
|
+
|
|
314
|
+
1. Create `prov/<domain>.md` with the standard structure (see above)
|
|
315
|
+
2. Add it to the `## Domain map` in `prov/CONTEXT.md`:
|
|
316
|
+
```
|
|
317
|
+
auth prov/auth.md
|
|
318
|
+
```
|
|
319
|
+
3. Run `python prov/prov.py orient` to verify it loads
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
|
|
323
|
+
## Writing new entries
|
|
324
|
+
|
|
325
|
+
### Via CLI (validated, shows preview)
|
|
326
|
+
|
|
327
|
+
```sh
|
|
328
|
+
echo '{
|
|
329
|
+
"domain": "auth",
|
|
330
|
+
"entries": [{
|
|
331
|
+
"slug": "password-reset",
|
|
332
|
+
"type": "requirement",
|
|
333
|
+
"statement": "Users can reset their password via email link.",
|
|
334
|
+
"provenance": "\"I need a forgot password flow\"",
|
|
335
|
+
"planned": true
|
|
336
|
+
}]
|
|
337
|
+
}' | python prov/prov.py write --yes
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### Directly in markdown
|
|
341
|
+
|
|
342
|
+
Edit the domain file. Follow the format above. Run `python prov/prov.py validate` when done.
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
## CONTEXT.md structure
|
|
347
|
+
|
|
348
|
+
```markdown
|
|
349
|
+
# <Project Name>
|
|
350
|
+
|
|
351
|
+
> One sentence: what it does and who uses it.
|
|
352
|
+
|
|
353
|
+
## Purpose
|
|
354
|
+
|
|
355
|
+
2-3 sentences on the problem being solved.
|
|
356
|
+
|
|
357
|
+
## User goals
|
|
358
|
+
|
|
359
|
+
1. Primary goal
|
|
360
|
+
2. Secondary goal
|
|
361
|
+
|
|
362
|
+
## Hard constraints
|
|
363
|
+
|
|
364
|
+
C:example: Non-negotiable rule.
|
|
365
|
+
|
|
366
|
+
> "why"
|
|
367
|
+
|
|
368
|
+
## Non-goals
|
|
369
|
+
|
|
370
|
+
- Explicit out-of-scope items
|
|
371
|
+
|
|
372
|
+
## Domain map
|
|
373
|
+
|
|
374
|
+
auth prov/auth.md
|
|
375
|
+
billing prov/billing.md
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
---
|
|
379
|
+
|
|
380
|
+
## Commit message format
|
|
381
|
+
|
|
382
|
+
```sh
|
|
383
|
+
# Spec-only
|
|
384
|
+
prov(auth): add session-expiry requirement
|
|
385
|
+
prov(auth): implement admin-revoke, close Q:admin-scope
|
|
386
|
+
prov: reconcile src/api/
|
|
387
|
+
|
|
388
|
+
# Code + spec together (required)
|
|
389
|
+
feat(auth): implement session expiry
|
|
390
|
+
prov: implement session-expiry
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
---
|
|
394
|
+
|
|
395
|
+
## Validation checks
|
|
396
|
+
|
|
397
|
+
| Severity | Check | Meaning |
|
|
398
|
+
|---|---|---|
|
|
399
|
+
| ERROR | `ghost-scope` | Entry has no `>` line |
|
|
400
|
+
| ERROR | `dead-ref` | `~` path doesn't exist |
|
|
401
|
+
| ERROR | `phantom-slug` | `spec:` in code, no entry |
|
|
402
|
+
| ERROR | `duplicate-slug` | Same slug in two files |
|
|
403
|
+
| ERROR | `no-dangling-dep` | `@` target doesn't exist |
|
|
404
|
+
| WARN | `silent-impl` | `[planned]` but code has `spec:` |
|
|
405
|
+
| WARN | `orphan-question` | `Q:` not referenced by any `?` |
|
|
406
|
+
|
|
407
|
+
All ERRORs must be zero before committing.
|
|
408
|
+
|
|
409
|
+
---
|
|
410
|
+
|
|
411
|
+
## Fallback (no Python)
|
|
412
|
+
|
|
413
|
+
The spec is always greppable without any tooling:
|
|
414
|
+
|
|
415
|
+
```sh
|
|
416
|
+
grep -rh "^>" prov/*.md # domain summaries
|
|
417
|
+
grep -r "^Q:" prov/ # open questions
|
|
418
|
+
grep -r "\[planned\]" prov/ # backlog
|
|
419
|
+
grep -r "^ !" prov/ # unconfirmed assumptions
|
|
420
|
+
grep -r "^C:" prov/ # all constraints
|
|
421
|
+
grep -A 20 "^session-expiry:" prov/ # entry by slug
|
|
422
|
+
grep -r "~src/api/auth" prov/ # what owns this path
|
|
423
|
+
```
|