path-link 0.2.0__py3-none-any.whl

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.
@@ -0,0 +1,668 @@
1
+ # Assistant Context — ptool-serena v0.2.0
2
+
3
+ **Last Updated:** 2025-10-10
4
+ **Status:** Active (Production)
5
+ **Canonical Reference:** This document + CLAUDE.md
6
+
7
+ ---
8
+
9
+ ## Overview
10
+
11
+ `ptool-serena` is a Python library for type-safe project path management using Pydantic models.
12
+
13
+ **Key Facts:**
14
+ - **Package:** `ptool-serena` → imports as `project_paths`
15
+ - **Pattern:** Dynamic Pydantic model creation via factory methods (v2 API)
16
+ - **Tool:** `uv` for dependency management
17
+ - **Python:** 3.11+
18
+ - **Coverage Target:** ≥90% (enforced in CI)
19
+
20
+ **This project uses PTOOL v2 rules:**
21
+ - All paths managed through validated models
22
+ - Direct instantiation forbidden (raises `NotImplementedError`)
23
+ - Factory methods required
24
+
25
+ ---
26
+
27
+ ## Quick Start (5 Minutes)
28
+
29
+ ### 1. Environment Setup
30
+
31
+ ```bash
32
+ # Install dependencies (uv handles venv automatically)
33
+ uv pip install -e ".[test]"
34
+
35
+ # One-liner smoke test (verify installation)
36
+ uv run python -c "from project_paths import ProjectPaths; p=ProjectPaths.from_pyproject(); print('✅ OK:', len(p.to_dict()), 'paths loaded')"
37
+ ```
38
+
39
+ ### 2. Basic Usage
40
+
41
+ ```python
42
+ from project_paths import ProjectPaths
43
+
44
+ # ✅ CORRECT: Use factory methods
45
+ paths = ProjectPaths.from_pyproject() # Load from pyproject.toml
46
+ # OR
47
+ paths = ProjectPaths.from_config(".paths") # Load from .paths file
48
+
49
+ # Access paths (all are pathlib.Path objects)
50
+ config_dir = paths.config_dir
51
+ settings = paths["settings_file"] # Dict-style access
52
+
53
+ # ❌ FORBIDDEN: Direct instantiation
54
+ # paths = ProjectPaths() # Raises NotImplementedError
55
+ ```
56
+
57
+ ### 3. Run Tests
58
+
59
+ ```bash
60
+ uv run pytest # All tests
61
+ uv run pytest --cov=src --cov-report=term # With coverage
62
+ uv run pytest tests/test_validators.py # Specific file
63
+ ```
64
+
65
+ ---
66
+
67
+ ## Essential Commands
68
+
69
+ | Purpose | Command |
70
+ |---------|---------|
71
+ | **Install** | `uv pip install -e ".[test]"` |
72
+ | **Smoke test** | `uv run python -c "from project_paths import ProjectPaths; p=ProjectPaths.from_pyproject(); print('✅ OK:', len(p.to_dict()))"` |
73
+ | **Run all tests** | `uv run pytest` |
74
+ | **Coverage check** | `uv run pytest --cov=src --cov-report=term-missing:skip-covered` |
75
+ | **Type check** | `uv run mypy src/` |
76
+ | **Lint** | `uv run ruff check .` |
77
+ | **Format** | `uv run ruff format .` |
78
+ | **Regenerate static model** | `uv run python -c "from project_paths import write_dataclass_file; write_dataclass_file()"` |
79
+ | **Verify static sync** | `git diff --exit-code src/project_paths/project_paths_static.py` |
80
+ | **Access AI guidelines** | `uv run python -c "from project_paths import get_ai_guidelines; print(get_ai_guidelines()[:200])"` |
81
+ | **Access dev guide** | `uv run python -c "from project_paths import get_developer_guide; print(get_developer_guide()[:200])"` |
82
+ | **Access metadata** | `uv run python -c "import json; from project_paths import get_metadata; print(json.loads(get_metadata())['version'])"` |
83
+ | **Run example** | `uv run python examples/minimal_project/src/main.py` |
84
+
85
+ ---
86
+
87
+ ## Critical Rules (PTOOL v2)
88
+
89
+ ### ✅ Do
90
+
91
+ - **Use factory methods:**
92
+ ```python
93
+ paths = ProjectPaths.from_pyproject() # For pyproject.toml
94
+ paths = ProjectPaths.from_config(".paths") # For .paths files
95
+ ```
96
+
97
+ - **Treat all values as `pathlib.Path` objects**
98
+
99
+ - **Create directories safely:**
100
+ ```python
101
+ path.mkdir(parents=True, exist_ok=True)
102
+ ```
103
+
104
+ - **Validate paths:**
105
+ ```python
106
+ from project_paths import validate_or_raise
107
+ from project_paths.builtin_validators import StrictPathValidator
108
+
109
+ validator = StrictPathValidator(
110
+ required=["config_dir", "data_dir"],
111
+ must_be_dir=["config_dir"],
112
+ allow_symlinks=False # Default: blocks symlinks
113
+ )
114
+ validate_or_raise(paths, validator)
115
+ ```
116
+
117
+ - **Keep `.paths` files simple:** key=value format only (no sections)
118
+
119
+ ### ❌ Don't
120
+
121
+ - **Call `ProjectPaths()` directly** — v2 forbids direct instantiation (raises `NotImplementedError`)
122
+ - **Use `os.path` or raw `Path(...)` joins** in application code
123
+ - **Add INI sections** to `.paths` files (use dotenv format)
124
+ - **Edit `project_paths_static.py` manually** (auto-generated file)
125
+ - **Modify `PYTHONPATH`** (use editable install instead)
126
+
127
+ ### 🛡️ Enforcement
128
+
129
+ **Compliance is automatically enforced by `tests/test_path_policy.py`**, which forbids:
130
+ - `os.path` usage in `src/**`
131
+ - Direct `Path(...)` calls in `src/**`
132
+ - Direct `ProjectPaths()` calls outside `src/project_paths/**` and `examples/**`
133
+
134
+ CI will fail if these patterns are detected.
135
+
136
+ ---
137
+
138
+ ## Instantiation Rules (v2)
139
+
140
+ **Factory methods only — direct instantiation is disabled.**
141
+
142
+ ```python
143
+ # ✅ CORRECT: Load from pyproject.toml
144
+ paths = ProjectPaths.from_pyproject()
145
+
146
+ # ✅ CORRECT: Load from custom .paths file
147
+ paths = ProjectPaths.from_config(".paths")
148
+ paths = ProjectPaths.from_config("configs/custom.paths")
149
+
150
+ # ❌ FORBIDDEN: Direct instantiation
151
+ paths = ProjectPaths() # Raises NotImplementedError by design
152
+ ```
153
+
154
+ **Why:** V2 enforces factory pattern to ensure config is always loaded from a known source.
155
+
156
+ ---
157
+
158
+ ## Static Model Sync
159
+
160
+ **When to regenerate:** After any change to `[tool.project_paths]` in `pyproject.toml`
161
+
162
+ ```bash
163
+ # 1. Regenerate static model
164
+ uv run python -c "from project_paths import write_dataclass_file; write_dataclass_file()"
165
+
166
+ # 2. Verify no drift (CI check)
167
+ git diff --exit-code src/project_paths/project_paths_static.py || \
168
+ (echo "❌ Static model drift detected. Commit the regenerated file." && exit 1)
169
+ ```
170
+
171
+ **Why:** Static model (`project_paths_static.py`) provides IDE autocomplete and type hints. Must match dynamic model or `tests/test_static_model_equivalence.py` fails.
172
+
173
+ **CI Enforcement:** `just check-regen` verifies static model is in sync.
174
+
175
+ ---
176
+
177
+ ## Security: TOCTOU Prevention
178
+
179
+ **TOCTOU** (Time-of-check to time-of-use) race conditions can create security vulnerabilities when filesystem state changes between checking a path and using it.
180
+
181
+ ### Unsafe Pattern (Vulnerable)
182
+
183
+ ```python
184
+ # ❌ VULNERABLE — filesystem can change between check and use
185
+ if not my_dir.exists():
186
+ my_dir.mkdir() # Race condition: symlink could be placed here
187
+
188
+ if not my_file.exists():
189
+ my_file.write_text("data") # Race condition: file could be created/linked
190
+ ```
191
+
192
+ ### Safe Pattern (Atomic)
193
+
194
+ ```python
195
+ # ✅ SAFE — atomic directory creation
196
+ try:
197
+ my_dir.mkdir(exist_ok=False)
198
+ except FileExistsError:
199
+ if not my_dir.is_dir(): # Re-verify it's actually a directory
200
+ raise
201
+
202
+ # ✅ SAFE — atomic file creation ('x' mode fails if exists)
203
+ try:
204
+ with my_file.open("x") as f:
205
+ f.write("data")
206
+ except FileExistsError:
207
+ print("File already exists")
208
+ ```
209
+
210
+ ### Validator Protection
211
+
212
+ **`StrictPathValidator(allow_symlinks=False)` blocks both live and dangling symlinks by default.**
213
+
214
+ ```python
215
+ from project_paths.builtin_validators import StrictPathValidator
216
+
217
+ # Blocks symlinks (default behavior)
218
+ validator = StrictPathValidator(
219
+ required=["config_dir"],
220
+ allow_symlinks=False # Default: False
221
+ )
222
+
223
+ # Allow symlinks only if explicitly needed
224
+ validator_permissive = StrictPathValidator(
225
+ required=["config_dir"],
226
+ allow_symlinks=True
227
+ )
228
+ ```
229
+
230
+ **Security features:**
231
+ - Symlink detection: `path.is_symlink()` check before validation
232
+ - Dangling link detection: Catches broken symlinks
233
+ - Re-validation: Paths re-checked at use time, not cached
234
+
235
+ ---
236
+
237
+ ## Validation Framework
238
+
239
+ ### Basic Validation
240
+
241
+ ```python
242
+ from project_paths import (
243
+ ProjectPaths,
244
+ validate_or_raise,
245
+ ValidationResult,
246
+ Finding,
247
+ Severity
248
+ )
249
+ from project_paths.builtin_validators import StrictPathValidator
250
+
251
+ # Load paths
252
+ paths = ProjectPaths.from_pyproject()
253
+
254
+ # Configure validator
255
+ validator = StrictPathValidator(
256
+ required=["config_dir", "data_dir"], # Must exist
257
+ must_be_dir=["config_dir"], # Must be directory
258
+ must_be_file=["settings_file"], # Must be file
259
+ allow_symlinks=False # Block symlinks (default)
260
+ )
261
+
262
+ # Validate (raises PathValidationError on failure)
263
+ try:
264
+ validate_or_raise(paths, validator)
265
+ print("✅ All paths valid!")
266
+ except PathValidationError as e:
267
+ print(f"❌ Validation failed:\n{e}")
268
+ ```
269
+
270
+ ### Manual Validation (No Exception)
271
+
272
+ ```python
273
+ # Get ValidationResult without raising
274
+ result = validator.validate(paths)
275
+
276
+ if result.ok():
277
+ print("✅ Validation passed")
278
+ else:
279
+ # Inspect errors
280
+ for error in result.errors():
281
+ print(f"ERROR [{error.code}] {error.field}: {error.message}")
282
+
283
+ # Inspect warnings
284
+ for warning in result.warnings():
285
+ print(f"WARN [{warning.code}] {warning.field}: {warning.message}")
286
+ ```
287
+
288
+ ### Custom Validators
289
+
290
+ ```python
291
+ from dataclasses import dataclass
292
+ from project_paths import ValidationResult, Finding, Severity
293
+
294
+ @dataclass
295
+ class MyValidator:
296
+ """Custom validator example."""
297
+ required_file: str
298
+
299
+ def validate(self, paths) -> ValidationResult:
300
+ result = ValidationResult()
301
+
302
+ # Check custom condition
303
+ config_path = paths.to_dict().get("config_dir")
304
+ if config_path and not (config_path / self.required_file).exists():
305
+ result.add(Finding(
306
+ severity=Severity.ERROR,
307
+ code="CUSTOM_FILE_MISSING",
308
+ field="config_dir",
309
+ message=f"Required file '{self.required_file}' not found"
310
+ ))
311
+
312
+ return result
313
+
314
+ # Use custom validator
315
+ validator = MyValidator(required_file="app.conf")
316
+ validate_or_raise(paths, validator)
317
+ ```
318
+
319
+ ---
320
+
321
+ ## Accessing Documentation Programmatically
322
+
323
+ **New in v0.2.0:** Documentation is bundled in the package and accessible offline.
324
+
325
+ The package includes three functions to access documentation programmatically, even in airgapped or offline environments. This is especially useful for AI assistants helping users with the package.
326
+
327
+ ```python
328
+ from project_paths import get_ai_guidelines, get_developer_guide, get_metadata
329
+ import json
330
+
331
+ # Get AI assistant guidelines (this file - comprehensive usage patterns)
332
+ ai_docs = get_ai_guidelines()
333
+ print(f"AI Guidelines: {len(ai_docs):,} characters")
334
+
335
+ # Get developer guide (CLAUDE.md - architecture, development setup)
336
+ dev_docs = get_developer_guide()
337
+ print(f"Developer Guide: {len(dev_docs):,} characters")
338
+
339
+ # Get machine-readable metadata (assistant_handoff.json)
340
+ metadata_json = get_metadata()
341
+ metadata = json.loads(metadata_json)
342
+ print(f"Version: {metadata['version']}")
343
+ print(f"Public APIs: {metadata['public_api']}")
344
+ print(f"CLI Commands: {len(metadata['cli_commands'])} available")
345
+ ```
346
+
347
+ **Use Cases:**
348
+ - **AI Assistants**: Provide context to AI agents helping users
349
+ - **Offline Environments**: Access docs without internet connection
350
+ - **Enterprise/Airgapped**: Full documentation in restricted environments
351
+ - **Automation**: Build tools that need package metadata programmatically
352
+
353
+ **Location:** Documentation is stored in `src/project_paths/docs/` and bundled via `[tool.setuptools.package-data]` in `pyproject.toml`.
354
+
355
+ ---
356
+
357
+ ## Troubleshooting
358
+
359
+ ### Import Errors
360
+
361
+ ```bash
362
+ # 1. Check Python version (must be 3.11+)
363
+ uv run python -c "import sys; print(sys.version)"
364
+
365
+ # 2. Verify editable install
366
+ uv pip list | grep ptool-serena # Should show editable install
367
+
368
+ # 3. Reinstall if needed
369
+ uv pip install -e ".[test]"
370
+
371
+ # 4. Test import
372
+ uv run python -c "import project_paths; print('✅ Import OK')"
373
+ ```
374
+
375
+ ### Test Failures
376
+
377
+ ```bash
378
+ # 1. Check if static model is out of sync
379
+ uv run pytest tests/test_static_model_equivalence.py -v
380
+
381
+ # 2. If failing, regenerate static model
382
+ uv run python -c "from project_paths import write_dataclass_file; write_dataclass_file()"
383
+
384
+ # 3. Re-run all tests
385
+ uv run pytest -v
386
+ ```
387
+
388
+ ### "NotImplementedError" When Creating ProjectPaths
389
+
390
+ **This is expected behavior!** Direct instantiation is forbidden in v2.
391
+
392
+ ```python
393
+ # ❌ This will fail
394
+ paths = ProjectPaths() # NotImplementedError
395
+
396
+ # ✅ Use factory methods instead
397
+ paths = ProjectPaths.from_pyproject()
398
+ ```
399
+
400
+ ### Static Model Base Path Mismatch
401
+
402
+ **Symptom:** `test_static_equals_dynamic_values` fails with base_dir mismatch
403
+
404
+ **Cause:** Static model was generated in different environment (e.g., Docker `/app`)
405
+
406
+ **Fix:**
407
+ ```bash
408
+ # Regenerate in current environment
409
+ uv run python -c "from project_paths import write_dataclass_file; write_dataclass_file()"
410
+
411
+ # Verify fix
412
+ uv run pytest tests/test_static_model_equivalence.py -v
413
+ ```
414
+
415
+ ### Coverage Too Low
416
+
417
+ **Current target:** ≥90%
418
+
419
+ ```bash
420
+ # Check current coverage
421
+ uv run pytest --cov=src --cov-report=term-missing:skip-covered
422
+
423
+ # Focus on uncovered lines
424
+ uv run pytest --cov=src --cov-report=term-missing | grep -A 5 "Missing"
425
+
426
+ # Add tests for uncovered code (priority: model.py, builder.py)
427
+ ```
428
+
429
+ ---
430
+
431
+ ## Architecture Quick Reference
432
+
433
+ **Pattern:** Dynamic Pydantic model creation via factory methods
434
+
435
+ ```
436
+ User Code
437
+
438
+ ProjectPaths.from_pyproject() ← Factory method
439
+
440
+ builder.build_field_definitions() ← Loads config, builds Pydantic fields
441
+
442
+ model.create_model() ← Generates dynamic Pydantic class
443
+
444
+ Returns: ProjectPathsDynamic ← Instance inheriting _ProjectPathsBase
445
+ ```
446
+
447
+ ### Core Components
448
+
449
+ 1. **model.py** - Factory methods (`from_pyproject()`, `from_config()`), `_ProjectPathsBase` class
450
+ 2. **builder.py** - Config parsing (`get_paths_from_pyproject`, `get_paths_from_dot_paths`), field generation
451
+ 3. **validation.py** - `ValidationResult`, `Finding`, `Severity`, `validate_or_raise()`
452
+ 4. **builtin_validators/strict.py** - `StrictPathValidator` implementation
453
+ 5. **builtin_validators/sandbox.py** - `SandboxPathValidator` implementation
454
+ 6. **get_paths.py** - Static model generator (`write_dataclass_file()`)
455
+ 7. **__init__.py** - Public API exports, documentation access functions (`get_ai_guidelines`, `get_developer_guide`, `get_metadata`)
456
+ 8. **docs/** - Bundled documentation (ai_guidelines.md, developer_guide.md, metadata.json)
457
+
458
+ **See CLAUDE.md for detailed architecture explanation.**
459
+
460
+ ---
461
+
462
+ ## Assistant Behavior Guidelines
463
+
464
+ When working with this codebase, AI assistants MUST:
465
+
466
+ 1. **Always use factory methods** — Never call `ProjectPaths()` directly
467
+ 2. **Keep static model in sync** — Regenerate after `pyproject.toml` changes
468
+ 3. **Follow `src` layout** — Use absolute imports: `from project_paths.model import ...`
469
+ 4. **Refer to this document first** — Before any path-related task
470
+ 5. **Verify changes** — Run tests after modifications: `uv run pytest`
471
+ 6. **Use atomic operations** — Follow TOCTOU prevention patterns
472
+ 7. **Validate before writing** — Use `validate_or_raise()` before filesystem operations
473
+
474
+ ### Example Pattern
475
+
476
+ ```python
477
+ from project_paths import ProjectPaths, validate_or_raise
478
+ from project_paths.builtin_validators import StrictPathValidator
479
+
480
+ # 1. Load paths
481
+ paths = ProjectPaths.from_pyproject()
482
+
483
+ # 2. Validate
484
+ validator = StrictPathValidator(
485
+ required=["config_dir", "data_dir"],
486
+ must_be_dir=["config_dir", "data_dir"],
487
+ allow_symlinks=False
488
+ )
489
+ validate_or_raise(paths, validator)
490
+
491
+ # 3. Use paths safely
492
+ config_dir = paths.config_dir
493
+ config_dir.mkdir(parents=True, exist_ok=True)
494
+
495
+ config_file = config_dir / "app.conf"
496
+ try:
497
+ with config_file.open("x") as f:
498
+ f.write("# Configuration\n")
499
+ except FileExistsError:
500
+ print("Config already exists")
501
+ ```
502
+
503
+ ---
504
+
505
+ ## Non-Negotiables
506
+
507
+ - **Do not modify `PYTHONPATH`** — All imports must resolve through editable install
508
+ - **Always work within activated virtual environment** — Use `uv` for consistency
509
+ - **Never edit auto-generated files** — `project_paths_static.py` is generated by tooling
510
+ - **Follow policy enforcement** — `tests/test_path_policy.py` will catch violations
511
+ - **Maintain test coverage** — Target ≥90%, enforced in CI
512
+
513
+ ---
514
+
515
+ ## Configuration Formats
516
+
517
+ ### pyproject.toml
518
+
519
+ ```toml
520
+ [tool.project_paths.paths]
521
+ config_dir = "config"
522
+ data_dir = "data"
523
+ logs_dir = "logs"
524
+
525
+ [tool.project_paths.files]
526
+ settings_file = "config/settings.json"
527
+ log_file = "logs/app.log"
528
+ ```
529
+
530
+ ### .paths (dotenv format)
531
+
532
+ ```bash
533
+ # Simple key=value format (NO SECTIONS)
534
+ config_dir=config
535
+ data_dir=data
536
+ logs_dir=logs
537
+ settings_file=config/settings.json
538
+ log_file=logs/app.log
539
+ ```
540
+
541
+ **Important:** `.paths` files use dotenv syntax (key=value) with **no `[section]` headers**.
542
+
543
+ ### Environment Variable Expansion
544
+
545
+ **Both pyproject.toml and .paths files support environment variable and home directory expansion.**
546
+
547
+ ```python
548
+ # Expansion happens automatically via os.path.expandvars() and os.path.expanduser()
549
+ ```
550
+
551
+ **Supported patterns:**
552
+ - `${VAR}` - Expands to environment variable (empty string if undefined)
553
+ - `$VAR` - Alternative syntax
554
+ - `~` - Expands to user's home directory (`Path.home()`)
555
+ - `~/path` - Path under home directory
556
+
557
+ **Example .paths file:**
558
+ ```bash
559
+ # Environment variables
560
+ data_dir=${DATA_ROOT}/files
561
+ cache_dir=/tmp/${USER}_cache
562
+
563
+ # Home directory expansion
564
+ config_dir=~/.config/myapp
565
+
566
+ # Combined
567
+ user_data=~/projects/${PROJECT_NAME}/data
568
+ ```
569
+
570
+ **Example pyproject.toml:**
571
+ ```toml
572
+ [tool.project_paths.paths]
573
+ data_dir = "${DATA_ROOT}/app_data"
574
+ config_dir = "~/.config/myapp"
575
+ ```
576
+
577
+ **Behavior:**
578
+ - Undefined environment variables expand to empty string (standard Python behavior)
579
+ - `~` always expands to actual user home directory
580
+ - Expansion occurs at load time in `builder.py:make_path_factory()`
581
+ - All paths are then resolved relative to `base_dir` unless absolute
582
+
583
+ ---
584
+
585
+ ## Documentation Index
586
+
587
+ **Primary References:**
588
+ - **CLAUDE.md** — Comprehensive development guide (architecture, patterns, testing)
589
+ - **README.md** — User-facing documentation and API reference
590
+ - **assistant_context.md** — This file (quick start + troubleshooting)
591
+
592
+ **Project Status:**
593
+ - **REFACTOR_PLAN_1.md** — Latest refactoring plan (evidence-based, YAGNI analysis)
594
+ - **REFACTOR_STATUS.md** — Execution status, metrics, and results
595
+ - **assistant_handoff.json** — Machine-readable project snapshot
596
+
597
+ **Policy & Standards:**
598
+ - **CODE_QUALITY.json** — Development policy (SOLID, KISS, YAGNI principles)
599
+ - **CHAIN_OF_THOUGHT_GOLDEN_ALL_IN_ONE.json** — Reasoning framework for changes
600
+
601
+ ---
602
+
603
+ ## Diagnostic Checklist
604
+
605
+ If you encounter issues, run these commands in order:
606
+
607
+ ```bash
608
+ # 1. Check Python version
609
+ uv run python -c "import sys; print('Python:', sys.version)" # Should be 3.11+
610
+
611
+ # 2. Check editable install
612
+ uv pip list | grep ptool-serena # Should show path with "(editable)"
613
+
614
+ # 3. Test import
615
+ uv run python -c "import project_paths; print('✅ Import OK')"
616
+
617
+ # 4. Run smoke test
618
+ uv run python -c "from project_paths import ProjectPaths; p=ProjectPaths.from_pyproject(); print('✅ OK:', len(p.to_dict()), 'paths loaded')"
619
+
620
+ # 5. Check config files
621
+ ls -l pyproject.toml .paths 2>/dev/null
622
+
623
+ # 6. Run full test suite
624
+ uv run pytest -v
625
+
626
+ # 7. Check coverage
627
+ uv run pytest --cov=src --cov-report=term
628
+
629
+ # 8. Verify static model sync
630
+ git diff src/project_paths/project_paths_static.py
631
+ ```
632
+
633
+ ---
634
+
635
+ ## Known Issues & Recent Fixes
636
+
637
+ ### ✅ Recently Resolved (2025-10-10)
638
+
639
+ 1. **main.py policy violation** — Fixed direct `ProjectPaths()` call → `ProjectPaths.from_pyproject()`
640
+ 2. **Static model base_dir hardcoding** — Fixed to use `Path.cwd` for portability (was hardcoded `/app`)
641
+ 3. **Pytest collection warning** — Renamed `TestCoverageAnalyzer` → `CoverageAnalyzer`
642
+
643
+ ### 🎯 Active Work
644
+
645
+ 1. **Coverage improvement** — Current state meets project standards; target ≥90% enforced in CI
646
+ 2. **Documentation consolidation** — Ongoing effort to reduce duplication between docs
647
+
648
+ ---
649
+
650
+ ## Summary
651
+
652
+ **ptool-serena (v0.2.0)** provides type-safe, validated path management for Python projects.
653
+
654
+ **Core Principles:**
655
+ - Factory methods only (v2 API)
656
+ - Protocol-based validation
657
+ - Atomic filesystem operations
658
+ - Test-enforced policy compliance
659
+
660
+ **If code touches the filesystem, it must use PTOOL.**
661
+
662
+ ---
663
+
664
+ **Project:** ptool-serena v0.2.0
665
+ **Python:** 3.11+
666
+ **License:** MIT
667
+ **Package Manager:** uv
668
+ **Last Verified:** 2025-10-10 (all commands tested against current codebase)