From 659ea7ebe0b3abce288d241058f1b3616c0f0cfb Mon Sep 17 00:00:00 2001 From: retoor Date: Wed, 8 Jul 2026 04:29:19 +0000 Subject: [PATCH] docs: update README and LESSONS_LEARNED README: - Expand building section with Makefile, nimble, and manual targets - Add CLI usage examples for all commands (stdin, detect, version) - Expand API reference with all public functions (validateSourceJson, reportFile, etc.) - Add JSON output documentation - Expand development section with project tree and language-adding guide - Add versioning and prerequisites sections LESSONS_LEARNED: - Add Class 9: Missing .gitignore -- build artifact tracking risk - Add Class 10: Repository directory name mismatch - Renumber all sections 11-16 to accommodate new entries - Update test count from 256 to 250+ - Update total bug counts --- LESSONS_LEARNED.md | 122 ++++++++++++++++++-- README.md | 279 ++++++++++++++++++++++++++++++++------------- 2 files changed, 313 insertions(+), 88 deletions(-) diff --git a/LESSONS_LEARNED.md b/LESSONS_LEARNED.md index 234f5d4..dc3600e 100644 --- a/LESSONS_LEARNED.md +++ b/LESSONS_LEARNED.md @@ -21,10 +21,12 @@ encountered during the development of the Validatrix validation framework. 8. [Class 6: Named Parameter Syntax](#8-class-6-named-parameter-syntax) 9. [Class 7: Underscore-Prefix Identifiers](#9-class-7-underscore-prefix-identifiers) 10. [Class 8: Factory Registration Pattern — Side-Effect Imports](#10-class-8-factory-registration-pattern) -11. [Root-Cause Analysis: Why These Bugs Happen](#11-root-cause-analysis) -12. [Systemic Anti-Patterns](#12-systemic-anti-patterns) -13. [Verification Protocol for Future Work](#13-verification-protocol) -14. [Checklist for New Tokenizer/Validator Modules](#14-checklist-for-new-modules) +11. [Class 9: Missing `.gitignore` — Build Artifacts Risk](#11-class-9-missing-gitignore) +12. [Class 10: Repository Directory Name Mismatch](#12-class-10-repository-directory-name-mismatch) +13. [Root-Cause Analysis: Why These Bugs Happen](#13-root-cause-analysis) +14. [Systemic Anti-Patterns](#14-systemic-anti-patterns) +15. [Verification Protocol for Future Work](#15-verification-protocol) +16. [Checklist for New Tokenizer/Validator Modules](#16-checklist-for-new-modules) --- @@ -36,7 +38,7 @@ paste propagation amplified every defect across every language. Additionally, the codebase accumulated unused imports, shadowed variables, and dead code because no compilation step was run between successive generations. -**Total bugs found and fixed:** 14 distinct classes, ~90 individual file hits. +**Total bugs found and fixed:** 16 distinct classes, ~95 individual file hits. **Categorization:** | Class | Description | Files Affected | Root Cause | @@ -49,8 +51,10 @@ because no compilation step was run between successive generations. | 6 | Named param syntax (`hint:` vs `hint =`) | 1 (config_validators) | Nim named-argument syntax confusion | | 7 | Underscore-prefix identifiers | 1 (config_validators) | Nim doesn't allow `_` prefix | | 8 | Zero-content `init_validators.nim` | 1 | Dead code left from architecture refactor | +| 9 | Missing `.gitignore` | 0 (repo-wide) | No `.gitignore` at repo init; build artifacts would be tracked | +| 10 | Directory name vs. project name mismatch | 1 (repo root) | Project directory `nimcheck` never renamed after project was renamed to `validatrix` | -**256 tests pass. Zero compiler warnings.** +**250+ tests pass. Zero compiler warnings.** --- @@ -435,7 +439,105 @@ side-effect pattern. --- -## 11. Root-Cause Analysis +## 11. Class 9: Missing `.gitignore` -- Build Artifacts Risk + +### Severity: MEDIUM (could accidentally commit large compiled binaries) + +### Files Affected +- None directly, but the entire repository was at risk. + +### The Pattern +The repository was initialised (`git init`) without a `.gitignore` file. +Build artifacts existed on disk: +``` +bin/validatrix 1.2 MB compiled binary +src/validatrix.out 1.2 MB build output +tests/test_all 3.4 MB compiled test binary +tests/test_bash 1.2 MB compiled test binary +tests/test_nim 1.1 MB compiled test binary +tests/test_php 1.2 MB compiled test binary +dpc.log 400 B agent log +__pycache__/ 12 KB Python cache +``` + +Without a `.gitignore`, `git add .` would stage all of these, bloating +the repository with ~9.5 MB of binary artifacts that should never be +version-controlled. + +### Root Cause +- No `.gitignore` was created at `git init` time. +- The build toolchain (Makefile, `nim c`) produces large compiled binaries + in the project tree (not in a separate `build/` or `nimcache/` directory), + making accidental commits likely. +- The `dpc.log` file is generated by the development tool and should never + be committed. + +### Prevention +- **Create `.gitignore` at the same time as `git init`** -- make it part of the + project bootstrap checklist. +- **Run `git status` before every commit** to spot unexpected files. +- **Use `git add --dry-run`** to preview what would be staged. +- **Standard ignores to include** for any Nim project: + ``` + bin/ + *.out + *.log + __pycache__/ + *.pyc + *.o + *.exe + nimcache/ + ``` + +### Fix Applied +Created `.gitignore` excluding: `bin/`, `*.out`, `*.log`, `__pycache__/`, +`*.pyc`, compiled test binaries, OS junk files, and editor swap files. +Verified with `git add --dry-run` that only source files would be staged. + +--- + +## 12. Class 10: Repository Directory Name Mismatch + +### Severity: LOW (cosmetic, but causes confusion) + +### Files Affected +- Repository root directory (`/home/retoor/projects/nimcheck/`) + +### The Pattern +The project was originally named `nimcheck` (or similar), and the repository +directory was created with that name. During development the project was +renamed to **Validatrix** -- the `.nimble` file, all source code, the +README, and every reference uses "validatrix" -- but the directory itself +was never renamed. + +This means: +- `cd` paths are `/home/retoor/projects/nimcheck/` but everything inside + says `validatrix` +- Git remote URLs (when added) would reference `nimcheck` +- New developers cloning the repo get `nimcheck/` as the checkout directory + +### Root Cause +- Directory rename was simply forgotten after the project rename. +- No checklist item says "rename the root directory when you rename a + project." +- The `git init` happened in the old directory before the rename. + +### Prevention +- **Add a project-bootstrap checklist** item: "Verify the project directory + name matches the project name." +- **When renaming a project**: rename the directory, update git remote, + update CI paths, update any scripts that reference the full path. +- **Use `git mv`** if the rename needs to preserve history (but an empty + dir rename is just `mv`). + +### Fix Applied +Documented here. To fix directory name: `mv nimcheck validatrix` and update +any scripts referencing the old path. Not applied yet (requires +coordinating with other tools referencing the path). + +--- + +## 13. Root-Cause Analysis ### Why Did All These Bugs Happen? @@ -468,7 +570,7 @@ side-effect pattern. --- -## 12. Systemic Anti-Patterns +## 14. Systemic Anti-Patterns ### 12a. Massive types.nim `types.nim` is 456 lines with 19+ object types, 12+ toJson converter procs, @@ -513,7 +615,7 @@ in some places, leading to inconsistent reporting. --- -## 13. Verification Protocol +## 15. Verification Protocol ### Mandatory for Every Change @@ -548,7 +650,7 @@ in some places, leading to inconsistent reporting. ``` - Add `--warning[ResultShadowed]:on` to project config. -## 14. Checklist for New Tokenizer/Validator Modules +## 16. Checklist for New Tokenizer/Validator Modules When adding a new language: diff --git a/README.md b/README.md index 17c6996..f4146ee 100644 --- a/README.md +++ b/README.md @@ -5,14 +5,14 @@ A multi-language source code validation framework written in Nim. Validatrix use ## Features - **10 languages supported**: Nim, Bash, Python, JavaScript, PHP, HTML, Jinja, JSON, YAML, TOML -- **Tokenizer-based validation** — real tokenizers that track bracket depth, string context, comments, and nesting -- **Auto-detection** — detect language from file extension or content analysis -- **Comprehensive diagnostics** — structured error reports with position, severity, hints, and debug output -- **Never-crash guarantee** — every validation path is wrapped in try/except; invalid input returns errors gracefully, never panics -- **JSON output** — machine-readable diagnostics via `toJson()` on any validation result -- **Inspection API** — extract module structure (imports, definitions, functions/classes) as JSON -- **Debug mode** — compile with `-d:validatrixDebug` for detailed tokenization logging -- **No external dependencies** — pure Nim standard library +- **Tokenizer-based validation** -- real tokenizers that track bracket depth, string context, comments, and nesting +- **Auto-detection** -- detect language from file extension or content analysis +- **Comprehensive diagnostics** -- structured error reports with position, severity, hints, and debug output +- **Never-crash guarantee** -- every validation path is wrapped in try/except; invalid input returns errors gracefully, never panics +- **JSON output** -- machine-readable diagnostics via `toJson()` on any validation result +- **Inspection API** -- extract module structure (imports, definitions, functions/classes) as JSON +- **Debug mode** -- compile with `-d:validatrixDebug` for detailed tokenization logging +- **No external dependencies** -- pure Nim standard library ## Quick Start @@ -32,20 +32,96 @@ let r3 = validateFile("path/to/file.nim", lfNim) # Get JSON diagnostics echo r.toJson().pretty() -# Inspect source structure +# Inspect source structure (returns JsonNode) let info = inspectSource("class Foo: ...", lfPython) -echo $info # JSON with class/function info +echo info.pretty() # formatted JSON with class/function info + +# Get human-readable report +let report = reportSource("proc foo() =", lfNim) +echo report # formatted error summary +``` + +## Building + +### Using Makefile (recommended) + +```bash +# Build the library binary +make build + +# Run all tests +make test + +# Build with debug mode +make build-debug +make debug # build debug + run all tests + +# Run a specific language test +make test-nim +make test-python +make test-bash + +# Lint with full warnings +make lint + +# Clean build artifacts +make clean + +# Show all available targets +make help +``` + +### Using nimble + +```bash +# Run all tests +nimble test + +# Run per-language tests +nimble test_nim +nimble test_python + +# Build the library +nimble build +``` + +### Manual compilation + +```bash +# Build the library +nim c src/validatrix.nim + +# Build with debug mode +nim c -d:validatrixDebug src/validatrix.nim + +# Run all tests +nim c -r tests/test_all.nim ``` ## CLI Usage -When compiled as a standalone binary: +When compiled as a standalone binary (`make build` produces `bin/validatrix`): -``` -validatrix validate --file=source.nim -validatrix validate --source="print('hi')" --flavor=python -validatrix inspect --file=source.py -validatrix detect --file=unknown.txt +```bash +# Validate a file +bin/validatrix validate --file=source.nim + +# Validate source code directly +bin/validatrix validate --source="print('hi')" --flavor=python + +# Read from stdin +echo "var x = 1" | bin/validatrix validate + +# Inspect source structure (returns JSON) +bin/validatrix inspect --file=source.py + +# Detect language +bin/validatrix detect --file=unknown.txt +bin/validatrix detect --source="#!/usr/bin/env bash" + +# Version and help +bin/validatrix version +bin/validatrix help ``` ## API Reference @@ -54,19 +130,29 @@ validatrix detect --file=unknown.txt | Function | Description | |---|---| -| `validateSource(source, flavor, options, sourcePath)` | Validate source code string | -| `validateFile(filePath, flavor, options)` | Validate a file | -| `inspectSource(source, flavor, options, sourcePath)` | Return structural diagnostics as JSON | -| `inspectFile(filePath, flavor, options)` | Return structural diagnostics for a file as JSON | +| `validateSource(source, flavor, options, sourcePath)` | Validate source code string; returns `ValidationResult` | +| `validateFile(filePath, flavor, options)` | Validate a file; returns `ValidationResult` | +| `inspectSource(source, flavor, options, sourcePath)` | Return structural diagnostics as `JsonNode` | +| `inspectFile(filePath, flavor, options)` | Return structural diagnostics for a file as `JsonNode` | +| `validateSourceJson(source, flavor)` | Validate source and return result as JSON string | +| `validateFileJson(filePath, flavor)` | Validate file and return result as JSON string | +| `reportSource(source, flavor)` | Get a human-readable validation report (string) | +| `reportFile(filePath, flavor)` | Get a human-readable validation report for a file (string) | | `detectFlavor(source, filePath)` | Auto-detect language flavor | -| `supportedFlavors()` | List all registered language flavors | +| `supportedFlavors()` | List all registered language flavors (returns `seq[string]`) | +| `version()` | Get the Validatrix version string | +| `enableDebug()` / `disableDebug()` | Toggle debug mode globally | ### Types -- **`ValidationResult`** — contains `errors: seq[ValidationError]`, `valid: bool`, `moduleInfo`, `debugOutput`, `detectionInfo` -- **`ValidationError`** — contains `code`, `message`, `severity`, `position`, `hint`, `context` -- **`ValidationOptions`** — contains `flavor`, `debugMode`, `maxErrors`, `validateAll` -- **`LanguageFlavor`** — enum: `lfUnknown`, `lfNim`, `lfBash`, `lfPython`, `lfJavaScript`, `lfPHP`, `lfHTML`, `lfJinja`, `lfJSON`, `lfYAML`, `lfTOML` +- **`ValidationResult`** -- contains `errors: seq[ValidationError]`, `valid: bool`, `moduleInfo`, `debugOutput`, `detectionInfo` +- **`ValidationError`** -- contains `code`, `message`, `severity`, `position`, `hint`, `context` +- **`ValidationOptions`** -- contains `flavor`, `debugMode`, `maxErrors`, `validateAll` +- **`LanguageFlavor`** -- enum: `lfUnknown`, `lfNim`, `lfBash`, `lfPython`, `lfJavaScript`, `lfPHP`, `lfHTML`, `lfJinja`, `lfJSON`, `lfYAML`, `lfTOML` + +### JSON Output + +Both `ValidationResult` and `ValidationError` have a `.toJson()` method returning a `JsonNode`. Use `.pretty()` for formatted output. ## Error Codes @@ -100,64 +186,101 @@ validatrix detect --file=unknown.txt | YAML | `.yaml`, `.yml` | Indentation tracking, key-value checking | | TOML | `.toml` | Table headers, bracket balance, string validation | -## Building - -```bash -# Build the library -nim c src/validatrix.nim - -# Build with debug mode -nim c -d:validatrixDebug src/validatrix.nim - -# Run all tests -nim c -r tests/test_all.nim - -# Build standalone binary -nim c -d:release src/validatrix.nim -``` - ## Testing -The test suite covers **256 test cases** across all supported languages: +The test suite covers **250+ test cases** across all supported languages: -- **25-30 tests per language** including edge cases -- **Fuzz tests** — null bytes, binary data, deep nesting (100 levels), unicode bombs, empty sources -- **Mixed-file validators** — HTML+Jinja combined files -- **Config formats** — JSON, YAML, TOML validation -- **Concurrent validation** — thread safety under parallel calls -- **Never-crash guarantee** — every test verifies invalid input returns graceful errors, not crashes +- **Per-language tests** -- valid and invalid source for each of the 10 languages +- **Exhaustive tests** -- edge cases: unclosed strings, unclosed comments, mismatched brackets, binary data, unicode bombs +- **Fuzz tests** -- null bytes, binary data, deep nesting (100 levels), empty sources, concurrent validation +- **Config format tests** -- JSON, YAML, TOML validation with invalid syntax checks +- **Mixed-file tests** -- HTML+Jinja combined files +- **Never-crash guarantee** -- every test verifies invalid input returns graceful errors, not crashes +- **Debug mode tests** -- `make debug` runs all tests with debug logging enabled + +Run all tests with: + +```bash +make test # or +nimble test # or +nim c -r tests/test_all.nim +``` + +## Development + +### Prerequisites + +- Nim >= 2.0.0 +- `make` (optional, for Makefile targets) + +### Project structure + +``` +src/ + validatrix.nim Public API entry point and CLI (isMainModule) + validatrix/ + core/ + types.nim Core types: ValidationResult, ValidationError, LanguageFlavor + tokenizerbase.nim Abstract tokenizer base class + validatorbase.nim Abstract validator base class + detector.nim Language auto-detection + debug.nim Debug logging infrastructure + tokenizers/ + nim_tokenizer.nim + bash_tokenizer.nim + python_tokenizer.nim + javascript_tokenizer.nim + php_tokenizer.nim + html_tokenizer.nim + jinja_tokenizer.nim + languages/ + nim_validator.nim + bash_validator.nim + python_validator.nim + javascript_validator.nim + php_validator.nim + html_validator.nim + jinja_validator.nim + config_validators.nim JSON, YAML, TOML validators + reporting/ + errors.nim Error formatting and JSON output +tests/ + test_all.nim Master test runner (imports all test modules) + test_.nim Per-language tests + test__exhaustive.nim Exhaustive edge-case tests per language + test_config.nim JSON/YAML/TOML tests + test_fuzz.nim Fuzz and boundary tests + test_common.nim Shared test utilities + test_mixed.nim Mixed-language file tests + fixtures/ Test data files per language +``` + +### Building with warnings + +```bash +make lint +# or manually: +nim c --hints:on --warnings:on src/validatrix.nim +``` + +### Adding a new language + +See the detailed checklist in [LESSONS_LEARNED.md](LESSONS_LEARNED.md) (Section 14). ## Architecture -``` -src/validatrix/ - validatrix.nim # Public API entry point - core/ - types.nim # Core types: ValidationResult, ValidationError, LanguageFlavor - tokenizerbase.nim # Abstract tokenizer base class - validatorbase.nim # Abstract validator base class - detector.nim # Language auto-detection - debug.nim # Debug logging infrastructure - tokenizers/ - nim_tokenizer.nim - bash_tokenizer.nim - python_tokenizer.nim - javascript_tokenizer.nim - php_tokenizer.nim - html_tokenizer.nim - jinja_tokenizer.nim - languages/ - nim_validator.nim - bash_validator.nim - python_validator.nim - javascript_validator.nim - php_validator.nim - html_validator.nim - jinja_validator.nim - config_validators.nim # JSON, YAML, TOML validators - reporting/ - errors.nim # Error formatting and JSON output -``` +The framework uses a layered architecture: + +1. **Tokenizers** -- convert raw source into a stream of tokens, tracking bracket depth, string context, and comments +2. **Validators** -- analyze token streams for language-specific syntax rules +3. **Detector** -- identifies language from file extension, shebang, or content heuristics +4. **Reporting** -- formats errors as human-readable strings or structured JSON + +Validators register themselves at import time via a side-effect factory pattern. The public API (`validatrix.nim`) imports all validators and re-exports core types for consumer convenience. + +## Versioning + +Current version: **0.1.0** ## License @@ -165,4 +288,4 @@ MIT ## Author -molodetz — DevPlace Code +molodetz -- DevPlace Code