aisp-validator 0.1.0 → 0.2.1

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.
Files changed (3) hide show
  1. package/bin/cli.js +62 -13
  2. package/package.json +1 -1
  3. package/src/index.js +164 -7
package/bin/cli.js CHANGED
@@ -9,7 +9,7 @@ import { readFile } from 'fs/promises';
9
9
  import { existsSync } from 'fs';
10
10
 
11
11
  const HELP = `
12
- AISP Validator - Validate AISP 5.1 documents
12
+ AISP Validator v0.2.1 - Validate AISP 5.1 documents
13
13
 
14
14
  Usage:
15
15
  aisp-validator <command> [file]
@@ -19,6 +19,7 @@ Commands:
19
19
  validate <file> Validate an AISP document
20
20
  tier <file> Get quality tier (⊘ to ◊⁺⁺)
21
21
  density <file> Get density score (δ)
22
+ debug <file> Show detailed density breakdown
22
23
  help Show this help message
23
24
 
24
25
  Quality Tiers:
@@ -28,10 +29,18 @@ Quality Tiers:
28
29
  ◊⁻ Bronze δ ≥ 0.20
29
30
  ⊘ Reject δ < 0.20
30
31
 
32
+ Density Formulas:
33
+ δ (semantic) = (blockScore × 0.4) + (bindingScore × 0.6)
34
+ ρ (pure) = |AISP_symbols| ÷ |non_ws_tokens|
35
+
36
+ blockScore: Required blocks present (⟦Ω⟧, ⟦Σ⟧, ⟦Γ⟧, ⟦Λ⟧, ⟦Ε⟧)
37
+ bindingScore: Semantic operators (≜, ≔, ∀, ∃, λ, ⇒, ∈, etc.)
38
+ pureDensity: Ratio of AISP symbols to total tokens
39
+
31
40
  Examples:
32
41
  npx aisp-validator validate spec.aisp
33
42
  npx aisp-validator tier spec.aisp
34
- npx aisp-validator spec.aisp
43
+ npx aisp-validator debug spec.aisp
35
44
  `;
36
45
 
37
46
  async function main() {
@@ -42,11 +51,16 @@ async function main() {
42
51
  process.exit(0);
43
52
  }
44
53
 
54
+ if (args[0] === '--version' || args[0] === '-v') {
55
+ console.log('aisp-validator v0.2.1');
56
+ process.exit(0);
57
+ }
58
+
45
59
  let command = args[0];
46
60
  let file = args[1];
47
61
 
48
62
  // If first arg is a file (no command), default to validate
49
- if (command && !['validate', 'tier', 'density'].includes(command)) {
63
+ if (command && !['validate', 'tier', 'density', 'debug'].includes(command)) {
50
64
  file = command;
51
65
  command = 'validate';
52
66
  }
@@ -65,34 +79,69 @@ async function main() {
65
79
  try {
66
80
  await AISP.init();
67
81
  const content = await readFile(file, 'utf-8');
68
- const result = AISP.validate(content);
69
82
 
70
83
  switch (command) {
71
- case 'validate':
84
+ case 'validate': {
85
+ const result = AISP.validate(content);
72
86
  if (result.valid) {
73
87
  console.log(`✓ VALID`);
74
- console.log(` Tier: ${result.tier}`);
75
- console.log(` Density (δ): ${result.delta.toFixed(3)}`);
76
- console.log(` Ambiguity: ${result.ambiguity.toFixed(3)}`);
88
+ console.log(` Tier: ${result.tier} ${result.tierName}`);
89
+ console.log(` Semantic (δ): ${result.delta.toFixed(3)}`);
90
+ console.log(` Pure (ρ): ${result.pureDensity.toFixed(3)}`);
91
+ console.log(` Ambiguity: ${result.ambiguity.toFixed(3)}`);
77
92
  process.exit(0);
78
93
  } else {
79
94
  console.log(`✗ INVALID`);
80
95
  console.log(` Error: ${result.error || `Error code ${result.errorCode}`}`);
81
96
  if (result.tier) {
82
- console.log(` Tier: ${result.tier}`);
83
- console.log(` Density (δ): ${result.delta.toFixed(3)}`);
97
+ console.log(` Tier: ${result.tier} ${result.tierName}`);
98
+ console.log(` Semantic (δ): ${result.delta.toFixed(3)}`);
99
+ console.log(` Pure (ρ): ${result.pureDensity.toFixed(3)}`);
84
100
  }
85
101
  process.exit(1);
86
102
  }
87
103
  break;
104
+ }
88
105
 
89
- case 'tier':
90
- console.log(result.tier);
106
+ case 'tier': {
107
+ const result = AISP.validate(content);
108
+ console.log(`${result.tier} ${result.tierName}`);
91
109
  break;
110
+ }
92
111
 
93
- case 'density':
112
+ case 'density': {
113
+ const result = AISP.validate(content);
94
114
  console.log(result.delta.toFixed(4));
95
115
  break;
116
+ }
117
+
118
+ case 'debug': {
119
+ const debug = AISP.debug(content);
120
+ console.log(`\nAISP Density Debug`);
121
+ console.log(`==================`);
122
+ console.log(`\nTier: ${debug.tier} ${debug.tierName}`);
123
+ console.log(`Semantic (δ): ${debug.delta.toFixed(3)}`);
124
+ console.log(`Pure (ρ): ${debug.pureDensity.toFixed(3)}`);
125
+ console.log(`\nSemantic Score Breakdown:`);
126
+ console.log(` Block Score: ${(debug.blockScore * 100).toFixed(1)}% (weight: 40%)`);
127
+ console.log(` Binding Score: ${(debug.bindingScore * 100).toFixed(1)}% (weight: 60%)`);
128
+ console.log(`\nBlocks Found: ${debug.breakdown.blocksFound}/${debug.breakdown.blocksRequired}`);
129
+ console.log(` Required: ⟦Ω⟧, ⟦Σ⟧, ⟦Γ⟧, ⟦Λ⟧, ⟦Ε⟧`);
130
+ console.log(`\nSemantic Operators: ${debug.breakdown.totalBindings}`);
131
+ console.log(` ≜ definitions: ${debug.breakdown.definitions}`);
132
+ console.log(` ≔ assignments: ${debug.breakdown.assignments}`);
133
+ console.log(` ∀∃ quantifiers: ${debug.breakdown.quantifiers}`);
134
+ console.log(` λ lambdas: ${debug.breakdown.lambdas}`);
135
+ console.log(` ⇒⇔ implications: ${debug.breakdown.implications}`);
136
+ console.log(` ∈⊆∩∪ set ops: ${debug.breakdown.setOps}`);
137
+ console.log(`\nPure Density Breakdown:`);
138
+ console.log(` AISP Symbols: ${debug.breakdown.symbolCount}`);
139
+ console.log(` Total Tokens: ${debug.breakdown.tokenCount}`);
140
+ console.log(`\nFormulas:`);
141
+ console.log(` δ = (${debug.blockScore.toFixed(2)} × 0.4) + (${debug.bindingScore.toFixed(2)} × 0.6) = ${debug.delta.toFixed(3)}`);
142
+ console.log(` ρ = ${debug.breakdown.symbolCount} ÷ ${debug.breakdown.tokenCount} = ${debug.pureDensity.toFixed(3)}`);
143
+ break;
144
+ }
96
145
  }
97
146
  } catch (err) {
98
147
  console.error(`Error: ${err.message}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aisp-validator",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "AISP 5.1 document validator - validates AI Symbolic Protocol specifications with <2% ambiguity",
5
5
  "main": "src/index.js",
6
6
  "bin": {
package/src/index.js CHANGED
@@ -10,6 +10,127 @@ import { dirname, join } from 'path';
10
10
  const __filename = fileURLToPath(import.meta.url);
11
11
  const __dirname = dirname(__filename);
12
12
 
13
+ /**
14
+ * AISP Symbol Set (Σ_512 subset for density calculation)
15
+ * Formal symbols that define AISP semantic content
16
+ */
17
+ const AISP_SYMBOLS = [
18
+ // Block delimiters
19
+ '⟦', '⟧',
20
+ // Operators
21
+ '≜', '≔', '≡', '≢',
22
+ // Quantifiers
23
+ '∀', '∃',
24
+ // Lambda
25
+ 'λ',
26
+ // Logic
27
+ '⇒', '⇔', '→', '↔', '∧', '∨', '¬', '⊕',
28
+ // Sets
29
+ '∈', '∉', '⊆', '⊇', '∩', '∪', '∅', '𝒫',
30
+ // Relations
31
+ '≤', '≥', '<', '>',
32
+ // Types
33
+ 'ℕ', 'ℤ', 'ℝ', '𝔹', '𝕊',
34
+ // Document
35
+ '𝔸',
36
+ // Tier symbols
37
+ '◊', '⊘',
38
+ // Angle brackets (tuples)
39
+ '⟨', '⟩',
40
+ // Greek letters (commonly used)
41
+ 'α', 'β', 'γ', 'δ', 'ε', 'φ', 'τ', 'ρ', 'Ω', 'Σ', 'Γ', 'Λ', 'Ε', 'Θ', 'Χ', 'Δ', 'Π'
42
+ ];
43
+
44
+ /**
45
+ * Calculate pure density: |AISP_symbols| ÷ |non_ws_tokens|
46
+ * @param {string} text - AISP source
47
+ * @returns {object} { pureDensity, symbolCount, tokenCount }
48
+ */
49
+ function calculatePureDensity(text) {
50
+ // Count AISP symbols
51
+ let symbolCount = 0;
52
+ for (const symbol of AISP_SYMBOLS) {
53
+ const matches = text.split(symbol).length - 1;
54
+ symbolCount += matches;
55
+ }
56
+
57
+ // Count non-whitespace tokens (split on whitespace, filter empty)
58
+ const tokens = text.split(/\s+/).filter(t => t.length > 0);
59
+ const tokenCount = tokens.length;
60
+
61
+ // Pure density: ratio of AISP symbols to tokens
62
+ const pureDensity = tokenCount > 0 ? symbolCount / tokenCount : 0;
63
+
64
+ return {
65
+ pureDensity,
66
+ symbolCount,
67
+ tokenCount
68
+ };
69
+ }
70
+
71
+ /**
72
+ * Calculate semantic density using Block Coverage + Binding Density
73
+ * δ = (blockScore × 0.4) + (bindingScore × 0.6)
74
+ * @param {string} text - AISP source
75
+ * @returns {object} { delta, blockScore, bindingScore, breakdown, pureDensity }
76
+ */
77
+ function calculateSemanticDensity(text) {
78
+ // Required blocks present?
79
+ const blocks = ['⟦Ω', '⟦Σ', '⟦Γ', '⟦Λ', '⟦Ε'];
80
+ const blocksFound = blocks.filter(b => text.includes(b));
81
+ const blockScore = blocksFound.length / blocks.length;
82
+
83
+ // Binding density (semantic operators)
84
+ const definitions = (text.match(/≜/g) || []).length;
85
+ const assignments = (text.match(/≔/g) || []).length;
86
+ const quantifiers = (text.match(/[∀∃]/g) || []).length;
87
+ const lambdas = (text.match(/λ/g) || []).length;
88
+ const implications = (text.match(/[⇒⇔→↔]/g) || []).length;
89
+ const setOps = (text.match(/[∈⊆∩∪∅]/g) || []).length;
90
+
91
+ const totalBindings = definitions + assignments + quantifiers + lambdas + implications + setOps;
92
+ const bindingScore = Math.min(1, totalBindings / 20);
93
+
94
+ // Combined score (semantic delta)
95
+ const delta = (blockScore * 0.4) + (bindingScore * 0.6);
96
+
97
+ // Pure density (symbol/token ratio)
98
+ const pureResult = calculatePureDensity(text);
99
+
100
+ return {
101
+ delta,
102
+ blockScore,
103
+ bindingScore,
104
+ pureDensity: pureResult.pureDensity,
105
+ breakdown: {
106
+ blocksFound: blocksFound.length,
107
+ blocksRequired: blocks.length,
108
+ definitions,
109
+ assignments,
110
+ quantifiers,
111
+ lambdas,
112
+ implications,
113
+ setOps,
114
+ totalBindings,
115
+ symbolCount: pureResult.symbolCount,
116
+ tokenCount: pureResult.tokenCount
117
+ }
118
+ };
119
+ }
120
+
121
+ /**
122
+ * Get tier from delta value
123
+ * @param {number} delta
124
+ * @returns {object} { tier, tierValue, tierName }
125
+ */
126
+ function getTierFromDelta(delta) {
127
+ if (delta >= 0.75) return { tier: '◊⁺⁺', tierValue: 4, tierName: 'Platinum' };
128
+ if (delta >= 0.60) return { tier: '◊⁺', tierValue: 3, tierName: 'Gold' };
129
+ if (delta >= 0.40) return { tier: '◊', tierValue: 2, tierName: 'Silver' };
130
+ if (delta >= 0.20) return { tier: '◊⁻', tierValue: 1, tierName: 'Bronze' };
131
+ return { tier: '⊘', tierValue: 0, tierName: 'Reject' };
132
+ }
133
+
13
134
  const AISP = {
14
135
  _instance: null,
15
136
  _memory: null,
@@ -74,15 +195,40 @@ const AISP = {
74
195
  };
75
196
  }
76
197
 
77
- const result = this._instance.aisp_validate(docId);
198
+ const parseResult = this._instance.aisp_validate(docId);
199
+
200
+ // Use semantic density calculation instead of WASM density
201
+ const densityResult = calculateSemanticDensity(source);
202
+ const tierResult = getTierFromDelta(densityResult.delta);
78
203
 
79
204
  return {
80
- valid: result === 0,
81
- tier: this._getTierSymbol(this._instance.aisp_tier(docId)),
82
- tierValue: this._instance.aisp_tier(docId),
83
- delta: this._instance.aisp_density(docId),
205
+ valid: parseResult === 0,
206
+ tier: tierResult.tier,
207
+ tierValue: tierResult.tierValue,
208
+ tierName: tierResult.tierName,
209
+ delta: densityResult.delta,
210
+ pureDensity: densityResult.pureDensity,
84
211
  ambiguity: this._instance.aisp_ambig(docId),
85
- errorCode: result
212
+ errorCode: parseResult
213
+ };
214
+ },
215
+
216
+ /**
217
+ * Get detailed density breakdown for debugging
218
+ * @param {string} source - AISP source
219
+ * @returns {object} Detailed breakdown
220
+ */
221
+ debug(source) {
222
+ const densityResult = calculateSemanticDensity(source);
223
+ const tierResult = getTierFromDelta(densityResult.delta);
224
+
225
+ return {
226
+ ...tierResult,
227
+ delta: densityResult.delta,
228
+ pureDensity: densityResult.pureDensity,
229
+ blockScore: densityResult.blockScore,
230
+ bindingScore: densityResult.bindingScore,
231
+ breakdown: densityResult.breakdown
86
232
  };
87
233
  },
88
234
 
@@ -130,8 +276,19 @@ const AISP = {
130
276
  async validateFile(filePath) {
131
277
  const content = await readFile(filePath, 'utf-8');
132
278
  return this.validate(content);
279
+ },
280
+
281
+ /**
282
+ * Debug file - show density breakdown
283
+ * @param {string} filePath - Path to AISP file
284
+ * @returns {Promise<object>} Debug breakdown
285
+ */
286
+ async debugFile(filePath) {
287
+ const content = await readFile(filePath, 'utf-8');
288
+ return this.debug(content);
133
289
  }
134
290
  };
135
291
 
136
292
  export default AISP;
137
- export const { init, validate, isValid, getDensity, getTier, validateFile } = AISP;
293
+ export const { init, validate, isValid, getDensity, getTier, validateFile, debug, debugFile } = AISP;
294
+ export { calculateSemanticDensity, calculatePureDensity, getTierFromDelta, AISP_SYMBOLS };