Skip to content

Commit 9fc6692

Browse files
authored
Add PRD §0.13-0.14: section variants and enhanced scan (#20)
Introduces two new PRD sections covering paired/grouped section variants (colon syntax ID=group:variant) and enhanced scan capabilities including variant-aware output, --check validation, and --pair enforcement. These features are scoped to Phase 3.
1 parent 88b558d commit 9fc6692

1 file changed

Lines changed: 207 additions & 0 deletions

File tree

prds/phase-0-prd.md

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,4 +192,211 @@ See `CONTRIBUTING.md` for commit message convention and pre‑push hooks.
192192

193193
These will be addressed in later phases as detailed in the main PRD roadmap.
194194

195+
---
196+
197+
## 0.13 Section Variants (Paired & Grouped Sections)
198+
199+
### 0.13.1 Motivation
200+
201+
Solo sections (`ID=foo`) toggle a single block on or off. **Variants** extend this by linking multiple sections under a shared group — toggling one variant on simultaneously toggles its siblings off. The primary use case is swapping between two alternative implementations (e.g., dev vs prod config, SQLite vs Postgres backend).
202+
203+
### 0.13.2 Marker Syntax
204+
205+
Variants use a **colon separator** in the section ID: `group:variant`.
206+
207+
```python
208+
# toggle:start ID=db:sqlite desc="SQLite backend"
209+
import sqlite3
210+
conn = sqlite3.connect("app.db")
211+
# toggle:end ID=db:sqlite
212+
213+
# toggle:start ID=db:postgres desc="Postgres backend"
214+
# import psycopg2
215+
# conn = psycopg2.connect("host=localhost")
216+
# toggle:end ID=db:postgres
217+
```
218+
219+
- The **group** is the portion before the colon (`db`).
220+
- The **variant** is the portion after the colon (`sqlite`, `postgres`).
221+
- IDs without a colon remain **solo sections** with unchanged behavior.
222+
- The `desc="..."` attribute remains optional and applies per-variant.
223+
- Variant markers follow the same `toggle:start` / `toggle:end` convention — no new keywords are added to file markers.
224+
225+
### 0.13.3 CLI Behavior
226+
227+
| CLI Argument | Variants Found | Behavior |
228+
|---|---|---|
229+
| `-S debug` (no colon, solo) | 1 | **Solo** — invert/force as existing behavior |
230+
| `-S db` (group, no variant) | 2 | **Pair flip** — swap active/inactive |
231+
| `-S db` (group, no variant) | 3+ | **Error**`"group 'db' has N variants; specify one with -S db:<name>"` |
232+
| `-S db:postgres` | any | **Activate** — uncomment `db:postgres`, comment all other `db:*` variants |
233+
| `-S db --force on` | any | **Force all** — comment every `db:*` variant |
234+
| `-S db --force off` | any | **Force all** — uncomment every `db:*` variant |
235+
236+
### 0.13.4 `--pair` Enforcement Flag
237+
238+
The `--pair` flag is a **pre-execution validation guard**. When supplied, the tool scans for all variants in the targeted group and errors if the count is not exactly 2. No file modifications occur on failure.
239+
240+
```bash
241+
# Succeeds — db has exactly 2 variants
242+
toggle -S db --pair myfile.py
243+
244+
# Errors before any changes
245+
# Error: --pair: group 'db' has 3 variants, expected exactly 2
246+
toggle -S db --pair myfile.py
247+
```
248+
249+
`--pair` is optional. Without it, a group of 2 still flips via `-S <group>`. The flag adds an explicit guardrail for cases where the pairing contract must be enforced.
250+
251+
| Flag | Type | Description |
252+
|---|---|---|
253+
| `--pair` | `bool` | Enforce exactly 2 variants in the targeted group. Error otherwise. |
254+
255+
### 0.13.5 Multi-File Variant Toggling
256+
257+
Variants work across files with `-R` (recursive) or multi-path arguments. The tool collects all occurrences of the group's variants across all targeted files and applies the toggle atomically.
258+
259+
```bash
260+
# Flip db pair across entire src/ tree
261+
toggle -S db --pair -R src/
262+
263+
# Activate postgres everywhere
264+
toggle -S db:postgres -R src/
265+
```
266+
267+
Cross-file consistency: all files should contain the same set of variants for a given group. Mismatches are reported as warnings (or errors with `--check`).
268+
269+
---
270+
271+
## 0.14 Section Scan Enhancements
272+
273+
### 0.14.1 Variant-Aware Scan Output
274+
275+
The existing `--scan` flag is extended to understand variant groups. Output groups variants under their parent group.
276+
277+
**Default table output:**
278+
279+
```
280+
SECTION TYPE STATE LINES DESCRIPTION
281+
debug solo commented 12-18 Debug output
282+
db:sqlite pair active 24-27 SQLite backend
283+
db:postgres pair commented 29-33 Postgres backend
284+
feature solo active 40-55 Experimental feature
285+
```
286+
287+
**Recursive summary (`--scan -R src/`):**
288+
289+
```
290+
SECTION TYPE FILES VARIANTS STATE
291+
debug solo 3 — mixed
292+
db pair 5 2 ok
293+
cache group 2 3 ok
294+
feature solo 1 — active
295+
```
296+
297+
The `TYPE` column is inferred:
298+
- **solo** — ID has no colon
299+
- **pair** — group has exactly 2 variants
300+
- **group** — group has 3+ variants
301+
302+
### 0.14.2 Detailed Section View (`--scan -S <id>`)
303+
304+
When `--scan` is combined with `-S`, show detailed file references for one section or group.
305+
306+
```bash
307+
toggle --scan -S db -R src/
308+
```
309+
310+
```
311+
GROUP: db (pair, 2 variants)
312+
313+
db:sqlite [active]
314+
src/config.py lines 24-27
315+
src/models/base.py lines 8-14
316+
tests/conftest.py lines 3-9
317+
318+
db:postgres [commented]
319+
src/config.py lines 29-33
320+
src/models/base.py lines 16-22
321+
tests/conftest.py lines 11-17
322+
```
323+
324+
### 0.14.3 Validation Mode (`--scan --check`)
325+
326+
The `--check` flag performs read-only validation and reports issues.
327+
328+
```bash
329+
toggle --scan --check -R src/
330+
```
331+
332+
```
333+
OK debug solo 3 files
334+
OK db pair 5 files, 2 variants
335+
WARN cache group 2 files, 3 variants (src/app.py missing cache:redis)
336+
ERR auth pair 1 file, 3 variants (--pair would fail: expected 2)
337+
```
338+
339+
Checks performed:
340+
- All start markers have matching end markers
341+
- `pair`-inferred groups have exactly 2 variants (warning if not)
342+
- Variant sets are consistent across files (same variants present in every file that references the group)
343+
- No duplicate section IDs within a single file
344+
345+
When combined with `--pair`, only groups that should be pairs are checked:
346+
```bash
347+
toggle --scan --check --pair -R src/
348+
```
349+
350+
### 0.14.4 JSON Output
351+
352+
All scan modes support `--json` for machine-readable output.
353+
354+
```bash
355+
toggle --scan -R src/ --json
356+
```
357+
358+
```json
359+
{
360+
"sections": [
361+
{
362+
"id": "debug",
363+
"type": "solo",
364+
"files": [
365+
{"path": "src/app.py", "start": 12, "end": 18, "state": "commented", "desc": "Debug output"}
366+
]
367+
},
368+
{
369+
"group": "db",
370+
"type": "pair",
371+
"variants": [
372+
{
373+
"id": "db:sqlite",
374+
"state": "active",
375+
"files": [
376+
{"path": "src/config.py", "start": 24, "end": 27},
377+
{"path": "src/models/base.py", "start": 8, "end": 14}
378+
]
379+
},
380+
{
381+
"id": "db:postgres",
382+
"state": "commented",
383+
"files": [
384+
{"path": "src/config.py", "start": 29, "end": 33},
385+
{"path": "src/models/base.py", "start": 16, "end": 22}
386+
]
387+
}
388+
]
389+
}
390+
]
391+
}
392+
```
393+
394+
### 0.14.5 New CLI Flags Summary
395+
396+
| Flag | Type | Phase | Description |
397+
|---|---|---|---|
398+
| `--pair` | `bool` | P3 | Enforce exactly 2 variants in targeted group |
399+
| `--check` | `bool` | P3 | Validate section integrity without modifying files |
400+
| `-S` with `--scan` | `String` | P3 | Filter scan output to a specific section or group |
401+
195402
</PRD>

0 commit comments

Comments
 (0)