sot-validator 0.1.0
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.
- package/README.md +89 -0
- package/bin/cli.js +105 -0
- package/index.js +131 -0
- package/package.json +37 -0
package/README.md
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# sot-validator
|
|
2
|
+
|
|
3
|
+
Validator for Source of Truth (`.sot`) files — epistemic quality verification for AI-safe documentation.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/sot-validator)
|
|
6
|
+
[](https://creativecommons.org/licenses/by/4.0/)
|
|
7
|
+
|
|
8
|
+
## What is a .sot file?
|
|
9
|
+
|
|
10
|
+
A **Source of Truth** (`.sot`) file is a markdown document structured to communicate explicit confidence levels for all claims, enabling readers (human or AI) to calibrate their trust appropriately.
|
|
11
|
+
|
|
12
|
+
Part of the [Clarity Gate](https://github.com/frmoretto/clarity-gate) ecosystem for epistemic quality verification.
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install -g sot-validator
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## CLI Usage
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# Validate a single file
|
|
24
|
+
sot-validator project.sot
|
|
25
|
+
|
|
26
|
+
# Validate multiple files
|
|
27
|
+
sot-validator docs/*.sot
|
|
28
|
+
|
|
29
|
+
# Output as JSON
|
|
30
|
+
sot-validator project.sot --json
|
|
31
|
+
|
|
32
|
+
# Quiet mode (errors only)
|
|
33
|
+
sot-validator project.sot -q
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## API Usage
|
|
37
|
+
|
|
38
|
+
```javascript
|
|
39
|
+
const { validate, isValid, detect } = require('sot-validator');
|
|
40
|
+
|
|
41
|
+
// Full validation with errors and warnings
|
|
42
|
+
const result = validate(fileContent);
|
|
43
|
+
console.log(result.valid); // boolean
|
|
44
|
+
console.log(result.errors); // array of error objects
|
|
45
|
+
console.log(result.warnings); // array of warning objects
|
|
46
|
+
|
|
47
|
+
// Quick check
|
|
48
|
+
if (isValid(fileContent)) {
|
|
49
|
+
console.log('Document passes validation');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Detect if content is .sot format
|
|
53
|
+
if (detect(fileContent)) {
|
|
54
|
+
console.log('This appears to be a .sot file');
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Validation Rules
|
|
59
|
+
|
|
60
|
+
### Required Elements
|
|
61
|
+
- `-- Source of Truth` header
|
|
62
|
+
- `**Last Updated:**` field
|
|
63
|
+
- `**Owner:**` field
|
|
64
|
+
- `**Status:**` field
|
|
65
|
+
- `## Verification Status` section
|
|
66
|
+
|
|
67
|
+
### Warnings
|
|
68
|
+
- Unqualified "VERIFIED" status (should be "with noted exceptions")
|
|
69
|
+
- Estimates in Verified Data section
|
|
70
|
+
- Missing staleness markers (`[STABLE]`, `[VOLATILE]`, etc.)
|
|
71
|
+
|
|
72
|
+
## Related
|
|
73
|
+
|
|
74
|
+
- [Clarity Gate](https://github.com/frmoretto/clarity-gate) - Pre-ingestion verification for RAG systems
|
|
75
|
+
- [Source of Truth Creator](https://github.com/frmoretto/source-of-truth-creator) - Create .sot files
|
|
76
|
+
- [cgd-validator](https://www.npmjs.com/package/cgd-validator) - Validate .cgd files
|
|
77
|
+
|
|
78
|
+
## File Format Specification
|
|
79
|
+
|
|
80
|
+
See the [SOT and CGD File Format Specification](https://github.com/frmoretto/clarity-gate/blob/main/docs/FILE_FORMAT_SPEC.md).
|
|
81
|
+
|
|
82
|
+
## License
|
|
83
|
+
|
|
84
|
+
CC BY 4.0 — Use freely with attribution.
|
|
85
|
+
|
|
86
|
+
## Author
|
|
87
|
+
|
|
88
|
+
Francesco Marinoni Moretto
|
|
89
|
+
GitHub: [@frmoretto](https://github.com/frmoretto)
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* sot-validator CLI
|
|
5
|
+
* Validate Source of Truth (.sot) files from the command line
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const { validate, VERSION } = require('../index.js');
|
|
11
|
+
|
|
12
|
+
const args = process.argv.slice(2);
|
|
13
|
+
|
|
14
|
+
if (args.includes('--version') || args.includes('-v')) {
|
|
15
|
+
console.log(`sot-validator v${VERSION}`);
|
|
16
|
+
process.exit(0);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (args.includes('--help') || args.includes('-h') || args.length === 0) {
|
|
20
|
+
console.log(`
|
|
21
|
+
sot-validator v${VERSION}
|
|
22
|
+
Validate Source of Truth (.sot) files for epistemic quality
|
|
23
|
+
|
|
24
|
+
Usage:
|
|
25
|
+
sot-validator <file.sot> [options]
|
|
26
|
+
sot-validator <file.sot> <file2.sot> ...
|
|
27
|
+
|
|
28
|
+
Options:
|
|
29
|
+
-h, --help Show this help message
|
|
30
|
+
-v, --version Show version number
|
|
31
|
+
-q, --quiet Only output errors (no warnings)
|
|
32
|
+
--json Output results as JSON
|
|
33
|
+
|
|
34
|
+
Examples:
|
|
35
|
+
sot-validator project.sot
|
|
36
|
+
sot-validator docs/*.sot --json
|
|
37
|
+
|
|
38
|
+
Part of the Clarity Gate ecosystem:
|
|
39
|
+
https://github.com/frmoretto/clarity-gate
|
|
40
|
+
|
|
41
|
+
File Format Specification:
|
|
42
|
+
https://github.com/frmoretto/clarity-gate/docs/FILE_FORMAT_SPEC.md
|
|
43
|
+
`);
|
|
44
|
+
process.exit(0);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const quiet = args.includes('-q') || args.includes('--quiet');
|
|
48
|
+
const json = args.includes('--json');
|
|
49
|
+
const files = args.filter(a => !a.startsWith('-'));
|
|
50
|
+
|
|
51
|
+
if (files.length === 0) {
|
|
52
|
+
console.error('Error: No files specified');
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
let hasErrors = false;
|
|
57
|
+
const results = [];
|
|
58
|
+
|
|
59
|
+
for (const file of files) {
|
|
60
|
+
const filePath = path.resolve(file);
|
|
61
|
+
|
|
62
|
+
if (!fs.existsSync(filePath)) {
|
|
63
|
+
console.error(`Error: File not found: ${file}`);
|
|
64
|
+
hasErrors = true;
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
69
|
+
const result = validate(content);
|
|
70
|
+
result.file = file;
|
|
71
|
+
results.push(result);
|
|
72
|
+
|
|
73
|
+
if (!result.valid) {
|
|
74
|
+
hasErrors = true;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (!json) {
|
|
78
|
+
if (result.valid && result.warnings.length === 0) {
|
|
79
|
+
console.log(`✓ ${file}: PASS`);
|
|
80
|
+
} else if (result.valid) {
|
|
81
|
+
console.log(`⚠ ${file}: PASS with warnings`);
|
|
82
|
+
if (!quiet) {
|
|
83
|
+
result.warnings.forEach(w => {
|
|
84
|
+
console.log(` Warning: ${w.message}`);
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
} else {
|
|
88
|
+
console.log(`✗ ${file}: FAIL`);
|
|
89
|
+
result.errors.forEach(e => {
|
|
90
|
+
console.log(` Error: ${e.message}`);
|
|
91
|
+
});
|
|
92
|
+
if (!quiet) {
|
|
93
|
+
result.warnings.forEach(w => {
|
|
94
|
+
console.log(` Warning: ${w.message}`);
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (json) {
|
|
102
|
+
console.log(JSON.stringify(results, null, 2));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
process.exit(hasErrors ? 1 : 0);
|
package/index.js
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* sot-validator
|
|
3
|
+
*
|
|
4
|
+
* Validator for Source of Truth (.sot) files
|
|
5
|
+
* Epistemic quality verification for AI-safe documentation
|
|
6
|
+
*
|
|
7
|
+
* Part of the Clarity Gate ecosystem:
|
|
8
|
+
* - .sot (Source of Truth) - Authoritative reference documents
|
|
9
|
+
* - .cgd (Clarity-Gated Document) - Verified for LLM ingestion
|
|
10
|
+
*
|
|
11
|
+
* @see https://github.com/frmoretto/clarity-gate
|
|
12
|
+
* @license CC-BY-4.0
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const VERSION = '0.1.0';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Validate a Source of Truth (.sot) file
|
|
19
|
+
* @param {string} content - The file content to validate
|
|
20
|
+
* @returns {ValidationResult} Validation result with errors and warnings
|
|
21
|
+
*/
|
|
22
|
+
function validate(content) {
|
|
23
|
+
const errors = [];
|
|
24
|
+
const warnings = [];
|
|
25
|
+
|
|
26
|
+
// Required: Header block
|
|
27
|
+
if (!content.includes('-- Source of Truth')) {
|
|
28
|
+
errors.push({
|
|
29
|
+
code: 'MISSING_HEADER',
|
|
30
|
+
message: 'Document must contain "-- Source of Truth" header',
|
|
31
|
+
line: 1
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Required: Last Updated
|
|
36
|
+
if (!content.match(/\*\*Last Updated:\*\*/)) {
|
|
37
|
+
errors.push({
|
|
38
|
+
code: 'MISSING_DATE',
|
|
39
|
+
message: 'Document must contain "**Last Updated:**" field',
|
|
40
|
+
line: null
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Required: Owner
|
|
45
|
+
if (!content.match(/\*\*Owner:\*\*/)) {
|
|
46
|
+
errors.push({
|
|
47
|
+
code: 'MISSING_OWNER',
|
|
48
|
+
message: 'Document must contain "**Owner:**" field',
|
|
49
|
+
line: null
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Required: Status
|
|
54
|
+
if (!content.match(/\*\*Status:\*\*/)) {
|
|
55
|
+
errors.push({
|
|
56
|
+
code: 'MISSING_STATUS',
|
|
57
|
+
message: 'Document must contain "**Status:**" field',
|
|
58
|
+
line: null
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Required: Verification Status table
|
|
63
|
+
if (!content.includes('## Verification Status')) {
|
|
64
|
+
errors.push({
|
|
65
|
+
code: 'MISSING_VERIFICATION_TABLE',
|
|
66
|
+
message: 'Document must contain "## Verification Status" section',
|
|
67
|
+
line: null
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Warning: Status says VERIFIED without qualification
|
|
72
|
+
if (content.match(/Status:\*\*\s*VERIFIED\s*$/m)) {
|
|
73
|
+
warnings.push({
|
|
74
|
+
code: 'UNQUALIFIED_VERIFIED',
|
|
75
|
+
message: 'Status "VERIFIED" should be qualified (e.g., "with noted exceptions")',
|
|
76
|
+
line: null
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Warning: Estimates in Verified Data section
|
|
81
|
+
const verifiedDataSection = content.match(/## Verified Data[\s\S]*?(?=##|$)/);
|
|
82
|
+
if (verifiedDataSection && verifiedDataSection[0].match(/~\d|estimated|approximately/i)) {
|
|
83
|
+
warnings.push({
|
|
84
|
+
code: 'ESTIMATES_IN_VERIFIED',
|
|
85
|
+
message: 'Estimates found in Verified Data section - move to Estimates section',
|
|
86
|
+
line: null
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Warning: Missing staleness markers
|
|
91
|
+
if (content.includes('## Verified Data') && !content.match(/\[STABLE\]|\[VOLATILE\]|\[CHECK BEFORE CITING\]|\[SNAPSHOT\]/)) {
|
|
92
|
+
warnings.push({
|
|
93
|
+
code: 'MISSING_STALENESS',
|
|
94
|
+
message: 'Verified Data should include staleness markers ([STABLE], [VOLATILE], etc.)',
|
|
95
|
+
line: null
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
valid: errors.length === 0,
|
|
101
|
+
errors,
|
|
102
|
+
warnings,
|
|
103
|
+
version: VERSION
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Check if content is a valid .sot file
|
|
109
|
+
* @param {string} content - The file content to check
|
|
110
|
+
* @returns {boolean} True if valid
|
|
111
|
+
*/
|
|
112
|
+
function isValid(content) {
|
|
113
|
+
return validate(content).valid;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Detect if a file is a .sot file based on content
|
|
118
|
+
* @param {string} content - The file content
|
|
119
|
+
* @returns {boolean} True if appears to be .sot format
|
|
120
|
+
*/
|
|
121
|
+
function detect(content) {
|
|
122
|
+
return content.includes('-- Source of Truth') &&
|
|
123
|
+
content.includes('## Verification Status');
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
module.exports = {
|
|
127
|
+
validate,
|
|
128
|
+
isValid,
|
|
129
|
+
detect,
|
|
130
|
+
VERSION
|
|
131
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "sot-validator",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Validator for Source of Truth (.sot) files - epistemic quality verification for AI-safe documentation",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"types": "index.d.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"sot-validator": "./bin/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"test": "echo \"Tests coming soon\" && exit 0"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"sot",
|
|
15
|
+
"source-of-truth",
|
|
16
|
+
"validator",
|
|
17
|
+
"epistemic",
|
|
18
|
+
"ai-safety",
|
|
19
|
+
"rag",
|
|
20
|
+
"documentation",
|
|
21
|
+
"clarity-gate",
|
|
22
|
+
"verification"
|
|
23
|
+
],
|
|
24
|
+
"author": "Francesco Marinoni Moretto",
|
|
25
|
+
"license": "CC-BY-4.0",
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "https://github.com/frmoretto/sot-validator"
|
|
29
|
+
},
|
|
30
|
+
"homepage": "https://github.com/frmoretto/clarity-gate",
|
|
31
|
+
"bugs": {
|
|
32
|
+
"url": "https://github.com/frmoretto/clarity-gate/issues"
|
|
33
|
+
},
|
|
34
|
+
"engines": {
|
|
35
|
+
"node": ">=16.0.0"
|
|
36
|
+
}
|
|
37
|
+
}
|