aisp-validator 0.2.1 → 0.3.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.
Files changed (4) hide show
  1. package/README.md +84 -83
  2. package/bin/cli.js +173 -19
  3. package/package.json +1 -1
  4. package/src/index.js +120 -23
package/README.md CHANGED
@@ -1,23 +1,36 @@
1
1
  # AISP Validator
2
2
 
3
- Validate [AISP 5.1](../AI_GUIDE.md) documents with <2% ambiguity using a <10KB WASM kernel.
3
+ [![npm version](https://img.shields.io/npm/v/aisp-validator.svg)](https://www.npmjs.com/package/aisp-validator)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
4
5
 
5
- ## Quick Start
6
+ **Validate AISP 5.1 documents** — AI Symbolic Protocol with <2% ambiguity.
6
7
 
7
- ### CLI
8
+ ## Install
8
9
 
9
10
  ```bash
10
- # Validate a file
11
+ npm install aisp-validator
12
+ ```
13
+
14
+ ## CLI Usage
15
+
16
+ ```bash
17
+ # Validate a document
11
18
  npx aisp-validator validate spec.aisp
12
19
 
13
- # Get quality tier
14
- npx aisp-validator tier spec.aisp
20
+ # Detailed output with JSON
21
+ npx aisp-validator validate spec.aisp --long
22
+ npx aisp-validator validate spec.aisp --json
23
+ ```
15
24
 
16
- # Get density score
17
- npx aisp-validator density spec.aisp
25
+ **Output:**
26
+ ```
27
+ ✓ VALID
28
+ Tier: ◊⁺⁺ Platinum
29
+ Semantic (δ): 1.000
30
+ Pure (ρ): 1.857
18
31
  ```
19
32
 
20
- ### Node.js
33
+ ## Node.js Usage
21
34
 
22
35
  ```javascript
23
36
  import AISP from 'aisp-validator';
@@ -25,112 +38,100 @@ import AISP from 'aisp-validator';
25
38
  await AISP.init();
26
39
 
27
40
  const result = AISP.validate(`
28
- 𝔸1.0.example@2026-01-14
41
+ 𝔸1.0.example@2026-01-16
29
42
  γ≔test
30
43
 
31
44
  ⟦Ω:Meta⟧{ ∀D:Ambig(D)<0.02 }
32
45
  ⟦Σ:Types⟧{ T≜ℕ }
33
46
  ⟦Γ:Rules⟧{ ∀x:T:x≥0 }
34
47
  ⟦Λ:Funcs⟧{ f≜λx.x }
35
- ⟦Ε⟧⟨δ≜0.75;φ≜100;τ≜◊⁺⁺⟩
48
+ ⟦Ε⟧⟨δ≜0.75;τ≜◊⁺⁺⟩
36
49
  `);
37
50
 
38
- console.log(result);
39
- // { valid: true, tier: '◊⁺⁺', delta: 0.78, ambiguity: 0.01 }
51
+ console.log(result.valid); // true
52
+ console.log(result.tier); // '◊⁺⁺'
53
+ console.log(result.tierName); // 'Platinum'
54
+ console.log(result.delta); // 0.82
40
55
  ```
41
56
 
42
- ### Browser
57
+ ## Browser Usage
43
58
 
44
59
  ```html
45
60
  <script type="module">
46
- import AISP from './browser/loader.js';
47
-
48
- await AISP.init('/wasm/aisp.wasm');
61
+ import AISP from 'aisp-validator/browser';
49
62
 
50
- const result = AISP.validate(document);
51
- console.log(result.tier); // '◊⁺⁺'
63
+ await AISP.init('/path/to/aisp.wasm');
64
+ const result = AISP.validate(source);
52
65
  </script>
53
66
  ```
54
67
 
55
- ## API
56
-
57
- ### `AISP.init(wasmPath?)`
58
- Initialize the WASM kernel. Call once before validation.
59
-
60
- ### `AISP.validate(source)`
61
- Validate an AISP document. Returns:
62
- ```javascript
63
- {
64
- valid: boolean, // true if valid
65
- tier: string, // '⊘' | '◊⁻' | '◊' | '◊⁺' | '◊⁺⁺'
66
- tierValue: number, // 0-4
67
- delta: number, // density δ [0, 1]
68
- ambiguity: number, // [0, 1], must be <0.02
69
- errorCode: number // 0 = success
70
- }
71
- ```
72
-
73
- ### `AISP.isValid(source)`
74
- Quick check: returns `true` if valid.
68
+ ## Quality Tiers
75
69
 
76
- ### `AISP.getTier(source)`
77
- Returns tier symbol: `'◊⁺⁺'`, `'◊⁺'`, `'◊'`, `'◊⁻'`, or `'⊘'`
70
+ | Tier | Symbol | δ Threshold | Description |
71
+ |------|--------|-------------|-------------|
72
+ | Platinum | ◊⁺⁺ | ≥ 0.75 | Production ready |
73
+ | Gold | ◊⁺ | ≥ 0.60 | Pre-production |
74
+ | Silver | ◊ | ≥ 0.40 | Development |
75
+ | Bronze | ◊⁻ | ≥ 0.20 | Draft |
76
+ | Reject | ⊘ | < 0.20 | Invalid |
78
77
 
79
- ### `AISP.getDensity(source)`
80
- Returns density score (δ) between 0 and 1.
78
+ ## Required Blocks
81
79
 
82
- ### `AISP.validateFile(path)` (Node.js only)
83
- Validate a file by path.
80
+ Every AISP document needs 5 blocks:
84
81
 
85
- ## Quality Tiers
82
+ | Block | Purpose |
83
+ |-------|---------|
84
+ | `⟦Ω⟧` | Meta/Foundation |
85
+ | `⟦Σ⟧` | Types/Glossary |
86
+ | `⟦Γ⟧` | Rules/Inference |
87
+ | `⟦Λ⟧` | Functions |
88
+ | `⟦Ε⟧` | Evidence |
86
89
 
87
- | Tier | Symbol | Threshold | Meaning |
88
- |------|--------|-----------|---------|
89
- | Platinum | ◊⁺⁺ | δ ≥ 0.75 | Production-ready |
90
- | Gold | ◊⁺ | δ ≥ 0.60 | High quality |
91
- | Silver | ◊ | δ ≥ 0.40 | Acceptable |
92
- | Bronze | ◊⁻ | δ ≥ 0.20 | Needs improvement |
93
- | Reject | ⊘ | δ < 0.20 | Insufficient AISP |
90
+ ## API
94
91
 
95
- ## Required AISP Blocks
92
+ | Method | Returns | Description |
93
+ |--------|---------|-------------|
94
+ | `AISP.init()` | Promise | Initialize WASM (call once) |
95
+ | `AISP.validate(src)` | Object | Full validation result |
96
+ | `AISP.isValid(src)` | boolean | Quick valid check |
97
+ | `AISP.getTier(src)` | string | Tier symbol only |
98
+ | `AISP.getDensity(src)` | number | Semantic density δ |
99
+ | `AISP.validateFile(path)` | Object | Validate file (Node.js) |
96
100
 
97
- Every valid AISP document must include:
101
+ ### Validation Result
98
102
 
99
- - `⟦Ω⟧` - Meta/foundation
100
- - `⟦Σ⟧` - Type definitions
101
- - `⟦Γ⟧` - Inference rules
102
- - `⟦Λ⟧` - Functions
103
- - `⟦Ε⟧` - Evidence
103
+ ```javascript
104
+ {
105
+ valid: true, // Document passes validation
106
+ tier: '◊⁺⁺', // Quality tier symbol
107
+ tierName: 'Platinum', // Tier name
108
+ tierValue: 4, // Numeric (0-4)
109
+ delta: 0.82, // Semantic density [0,1]
110
+ pureDensity: 1.85, // Symbol concentration
111
+ ambiguity: 0.01, // Must be <0.02
112
+ errorCode: 0 // 0 = success
113
+ }
114
+ ```
104
115
 
105
- ## Building from Source
116
+ ## What is AISP?
106
117
 
107
- ```bash
108
- # Prerequisites
109
- rustup target add wasm32-unknown-unknown
110
- npm install -g binaryen
118
+ **AI Symbolic Protocol** is a formal specification language for AI-to-AI communication:
111
119
 
112
- # Build
113
- cd wasm
114
- ./build.sh
120
+ - **<2% Ambiguity** — Eliminates interpretation errors
121
+ - **Formal Semantics** — Based on type theory
122
+ - **Machine-Readable** — Designed for AI agents
123
+ - **Human-Auditable** — Clear structure for review
115
124
 
116
- # Output: aisp.wasm (<10KB)
117
- ```
125
+ ## Links
118
126
 
119
- ## Architecture
127
+ - [AI Guide](https://github.com/bar181/aisp-open-core/blob/main/AI_GUIDE.md) — Full AISP 5.1 spec
128
+ - [Human Guide](https://github.com/bar181/aisp-open-core/blob/main/HUMAN_GUIDE.md) — Introduction
129
+ - [GitHub](https://github.com/bar181/aisp-open-core)
120
130
 
121
- The validator uses a Rust WASM kernel based on dependent type theory:
131
+ ## Author
122
132
 
123
- - **Zero-allocation**: Arena-based memory, no heap
124
- - **Type checking**: Based on lean-agentic
125
- - **Symbol table**: AISP Σ_512 glossary
126
- - **Density computation**: AISP symbol ratio
133
+ Bradley Ross [GitHub @bar181](https://github.com/bar181)
127
134
 
128
135
  ## License
129
136
 
130
- MIT License - see [LICENSE](./LICENSE)
131
-
132
- ## Links
133
-
134
- - [AISP 5.1 Specification](../AI_GUIDE.md)
135
- - [Reference (Rosetta Stone)](../reference.md)
136
- - [Repository](https://github.com/bar181/aisp-open-core)
137
+ MIT
package/bin/cli.js CHANGED
@@ -1,18 +1,21 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
3
  * AISP Validator CLI
4
- * Usage: aisp-validator <command> [file]
4
+ * Usage: aisp-validator <command> [file] [options]
5
5
  */
6
6
 
7
- import AISP from '../src/index.js';
8
- import { readFile } from 'fs/promises';
7
+ import AISP, { SUPPORTED_EXTENSIONS, SIZE_LIMITS } from '../src/index.js';
8
+ import { readFile, stat } from 'fs/promises';
9
9
  import { existsSync } from 'fs';
10
+ import { extname, basename } from 'path';
11
+
12
+ const VERSION = '0.3.0';
10
13
 
11
14
  const HELP = `
12
- AISP Validator v0.2.1 - Validate AISP 5.1 documents
15
+ AISP Validator v${VERSION} - Validate AISP 5.1 documents
13
16
 
14
17
  Usage:
15
- aisp-validator <command> [file]
18
+ aisp-validator <command> [file] [options]
16
19
  aisp-validator [file] Shorthand for validate
17
20
 
18
21
  Commands:
@@ -20,8 +23,18 @@ Commands:
20
23
  tier <file> Get quality tier (⊘ to ◊⁺⁺)
21
24
  density <file> Get density score (δ)
22
25
  debug <file> Show detailed density breakdown
26
+ long <file> Long-format output with full details
23
27
  help Show this help message
24
28
 
29
+ Options:
30
+ --long, -l Long-format output (detailed)
31
+ --json, -j JSON output
32
+ --max-size <n> Maximum document size in KB (default: 64)
33
+ --strict Force WASM validation (max 1KB)
34
+
35
+ Supported File Types:
36
+ ${SUPPORTED_EXTENSIONS.join(', ')}
37
+
25
38
  Quality Tiers:
26
39
  ◊⁺⁺ Platinum δ ≥ 0.75
27
40
  ◊⁺ Gold δ ≥ 0.60
@@ -41,8 +54,108 @@ Examples:
41
54
  npx aisp-validator validate spec.aisp
42
55
  npx aisp-validator tier spec.aisp
43
56
  npx aisp-validator debug spec.aisp
57
+ npx aisp-validator long spec.md --max-size 128
58
+ npx aisp-validator validate spec.aisp --json
44
59
  `;
45
60
 
61
+ /**
62
+ * Parse CLI arguments
63
+ */
64
+ function parseArgs(args) {
65
+ const result = {
66
+ command: 'validate',
67
+ file: null,
68
+ options: {
69
+ long: false,
70
+ json: false,
71
+ strict: false,
72
+ maxSize: SIZE_LIMITS.DEFAULT_MAX / 1024
73
+ }
74
+ };
75
+
76
+ const commands = ['validate', 'tier', 'density', 'debug', 'long', 'help'];
77
+ let i = 0;
78
+
79
+ while (i < args.length) {
80
+ const arg = args[i];
81
+
82
+ if (arg === '--long' || arg === '-l') {
83
+ result.options.long = true;
84
+ } else if (arg === '--json' || arg === '-j') {
85
+ result.options.json = true;
86
+ } else if (arg === '--strict') {
87
+ result.options.strict = true;
88
+ } else if (arg === '--max-size' && args[i + 1]) {
89
+ result.options.maxSize = parseInt(args[++i], 10) || 64;
90
+ } else if (commands.includes(arg)) {
91
+ result.command = arg;
92
+ } else if (!arg.startsWith('-') && !result.file) {
93
+ result.file = arg;
94
+ }
95
+ i++;
96
+ }
97
+
98
+ // 'long' command implies long format
99
+ if (result.command === 'long') {
100
+ result.options.long = true;
101
+ result.command = 'validate';
102
+ }
103
+
104
+ return result;
105
+ }
106
+
107
+ /**
108
+ * Check if file extension is supported
109
+ */
110
+ function isExtensionSupported(file) {
111
+ const ext = extname(file).toLowerCase();
112
+ // Also allow files without extension (assume AISP)
113
+ return ext === '' || SUPPORTED_EXTENSIONS.includes(ext);
114
+ }
115
+
116
+ /**
117
+ * Format long output
118
+ */
119
+ function formatLong(file, result, debug, fileSize) {
120
+ const lines = [];
121
+ lines.push(`\n${'═'.repeat(60)}`);
122
+ lines.push(`AISP Document Validation Report`);
123
+ lines.push(`${'═'.repeat(60)}`);
124
+ lines.push(`\nFile: ${basename(file)}`);
125
+ lines.push(`Size: ${(fileSize / 1024).toFixed(2)} KB`);
126
+ lines.push(`Mode: ${result.mode || 'wasm'}`);
127
+ lines.push(`\n${'─'.repeat(40)}`);
128
+ lines.push(`RESULT: ${result.valid ? '✓ VALID' : '✗ INVALID'}`);
129
+ lines.push(`${'─'.repeat(40)}`);
130
+ lines.push(`\nQuality Tier: ${result.tier} ${result.tierName}`);
131
+ lines.push(`\nMetrics:`);
132
+ lines.push(` Semantic Density (δ): ${result.delta.toFixed(4)}`);
133
+ lines.push(` Pure Density (ρ): ${result.pureDensity.toFixed(4)}`);
134
+ lines.push(` Ambiguity: ${result.ambiguity.toFixed(4)}`);
135
+
136
+ if (debug) {
137
+ lines.push(`\n${'─'.repeat(40)}`);
138
+ lines.push(`Semantic Score Breakdown:`);
139
+ lines.push(` Block Score: ${(debug.blockScore * 100).toFixed(1)}% (weight: 40%)`);
140
+ lines.push(` Binding Score: ${(debug.bindingScore * 100).toFixed(1)}% (weight: 60%)`);
141
+ lines.push(`\nBlocks Found: ${debug.breakdown.blocksFound}/${debug.breakdown.blocksRequired}`);
142
+ lines.push(` Required: ⟦Ω⟧, ⟦Σ⟧, ⟦Γ⟧, ⟦Λ⟧, ⟦Ε⟧`);
143
+ lines.push(`\nSemantic Operators: ${debug.breakdown.totalBindings}`);
144
+ lines.push(` ≜ definitions: ${debug.breakdown.definitions}`);
145
+ lines.push(` ≔ assignments: ${debug.breakdown.assignments}`);
146
+ lines.push(` ∀∃ quantifiers: ${debug.breakdown.quantifiers}`);
147
+ lines.push(` λ lambdas: ${debug.breakdown.lambdas}`);
148
+ lines.push(` ⇒⇔ implications: ${debug.breakdown.implications}`);
149
+ lines.push(` ∈⊆∩∪ set ops: ${debug.breakdown.setOps}`);
150
+ lines.push(`\nPure Density:`);
151
+ lines.push(` AISP Symbols: ${debug.breakdown.symbolCount}`);
152
+ lines.push(` Total Tokens: ${debug.breakdown.tokenCount}`);
153
+ }
154
+
155
+ lines.push(`\n${'═'.repeat(60)}`);
156
+ return lines.join('\n');
157
+ }
158
+
46
159
  async function main() {
47
160
  const args = process.argv.slice(2);
48
161
 
@@ -52,22 +165,15 @@ async function main() {
52
165
  }
53
166
 
54
167
  if (args[0] === '--version' || args[0] === '-v') {
55
- console.log('aisp-validator v0.2.1');
168
+ console.log(`aisp-validator v${VERSION}`);
56
169
  process.exit(0);
57
170
  }
58
171
 
59
- let command = args[0];
60
- let file = args[1];
61
-
62
- // If first arg is a file (no command), default to validate
63
- if (command && !['validate', 'tier', 'density', 'debug'].includes(command)) {
64
- file = command;
65
- command = 'validate';
66
- }
172
+ const { command, file, options } = parseArgs(args);
67
173
 
68
174
  if (!file) {
69
175
  console.error('Error: No file specified');
70
- console.log('Usage: aisp-validator <command> <file>');
176
+ console.log('Usage: aisp-validator <command> <file> [options]');
71
177
  process.exit(1);
72
178
  }
73
179
 
@@ -76,19 +182,51 @@ async function main() {
76
182
  process.exit(1);
77
183
  }
78
184
 
185
+ // Check file extension
186
+ if (!isExtensionSupported(file)) {
187
+ console.warn(`Warning: File extension not in supported list: ${SUPPORTED_EXTENSIONS.join(', ')}`);
188
+ console.warn('Continuing with validation...\n');
189
+ }
190
+
79
191
  try {
80
- await AISP.init();
192
+ // Initialize with max size option
193
+ await AISP.init({ maxDocSize: options.maxSize * 1024 });
194
+
81
195
  const content = await readFile(file, 'utf-8');
196
+ const fileStats = await stat(file);
197
+ const fileSize = fileStats.size;
82
198
 
83
199
  switch (command) {
84
200
  case 'validate': {
85
- const result = AISP.validate(content);
201
+ const result = AISP.validate(content, { strict: options.strict });
202
+ const debug = options.long ? AISP.debug(content) : null;
203
+
204
+ // JSON output
205
+ if (options.json) {
206
+ const output = {
207
+ file: basename(file),
208
+ fileSize,
209
+ ...result,
210
+ ...(debug ? { breakdown: debug.breakdown } : {})
211
+ };
212
+ console.log(JSON.stringify(output, null, 2));
213
+ process.exit(result.valid ? 0 : 1);
214
+ }
215
+
216
+ // Long format output
217
+ if (options.long) {
218
+ console.log(formatLong(file, result, debug, fileSize));
219
+ process.exit(result.valid ? 0 : 1);
220
+ }
221
+
222
+ // Standard output
86
223
  if (result.valid) {
87
224
  console.log(`✓ VALID`);
88
225
  console.log(` Tier: ${result.tier} ${result.tierName}`);
89
226
  console.log(` Semantic (δ): ${result.delta.toFixed(3)}`);
90
227
  console.log(` Pure (ρ): ${result.pureDensity.toFixed(3)}`);
91
228
  console.log(` Ambiguity: ${result.ambiguity.toFixed(3)}`);
229
+ if (result.mode) console.log(` Mode: ${result.mode}`);
92
230
  process.exit(0);
93
231
  } else {
94
232
  console.log(`✗ INVALID`);
@@ -105,20 +243,36 @@ async function main() {
105
243
 
106
244
  case 'tier': {
107
245
  const result = AISP.validate(content);
108
- console.log(`${result.tier} ${result.tierName}`);
246
+ if (options.json) {
247
+ console.log(JSON.stringify({ tier: result.tier, tierName: result.tierName, tierValue: result.tierValue }));
248
+ } else {
249
+ console.log(`${result.tier} ${result.tierName}`);
250
+ }
109
251
  break;
110
252
  }
111
253
 
112
254
  case 'density': {
113
255
  const result = AISP.validate(content);
114
- console.log(result.delta.toFixed(4));
256
+ if (options.json) {
257
+ console.log(JSON.stringify({ delta: result.delta, pureDensity: result.pureDensity }));
258
+ } else {
259
+ console.log(result.delta.toFixed(4));
260
+ }
115
261
  break;
116
262
  }
117
263
 
118
264
  case 'debug': {
119
265
  const debug = AISP.debug(content);
266
+
267
+ if (options.json) {
268
+ console.log(JSON.stringify(debug, null, 2));
269
+ break;
270
+ }
271
+
120
272
  console.log(`\nAISP Density Debug`);
121
273
  console.log(`==================`);
274
+ console.log(`\nFile: ${basename(file)}`);
275
+ console.log(`Size: ${(fileSize / 1024).toFixed(2)} KB`);
122
276
  console.log(`\nTier: ${debug.tier} ${debug.tierName}`);
123
277
  console.log(`Semantic (δ): ${debug.delta.toFixed(3)}`);
124
278
  console.log(`Pure (ρ): ${debug.pureDensity.toFixed(3)}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aisp-validator",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
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
@@ -131,20 +131,48 @@ function getTierFromDelta(delta) {
131
131
  return { tier: '⊘', tierValue: 0, tierName: 'Reject' };
132
132
  }
133
133
 
134
+ /**
135
+ * Supported file extensions for AISP documents
136
+ */
137
+ const SUPPORTED_EXTENSIONS = ['.aisp', '.md', '.txt', '.spec', '.aisp5'];
138
+
139
+ /**
140
+ * Default and max document size limits
141
+ */
142
+ const SIZE_LIMITS = {
143
+ DEFAULT_MAX: 64 * 1024, // 64KB default
144
+ ABSOLUTE_MAX: 1024 * 1024, // 1MB absolute max
145
+ WASM_MAX: 1024 // WASM kernel limit
146
+ };
147
+
134
148
  const AISP = {
135
149
  _instance: null,
136
150
  _memory: null,
137
151
  _allocPtr: 0x1000,
138
152
  _initialized: false,
153
+ _maxDocSize: SIZE_LIMITS.DEFAULT_MAX,
139
154
 
140
155
  /**
141
156
  * Initialize AISP kernel
142
- * @param {string} [wasmPath] - Optional path to aisp.wasm
157
+ * @param {string|object} [options] - Path to aisp.wasm or options object
158
+ * @param {string} [options.wasmPath] - Path to aisp.wasm
159
+ * @param {number} [options.maxDocSize] - Maximum document size in bytes (default: 64KB)
143
160
  * @returns {Promise<number>} 0 on success
144
161
  */
145
- async init(wasmPath) {
162
+ async init(options) {
146
163
  if (this._initialized) return 0;
147
164
 
165
+ // Handle both string (legacy) and object (new) options
166
+ let wasmPath;
167
+ if (typeof options === 'string') {
168
+ wasmPath = options;
169
+ } else if (options && typeof options === 'object') {
170
+ wasmPath = options.wasmPath;
171
+ if (options.maxDocSize) {
172
+ this._maxDocSize = Math.min(options.maxDocSize, SIZE_LIMITS.ABSOLUTE_MAX);
173
+ }
174
+ }
175
+
148
176
  const path = wasmPath || join(__dirname, '..', 'wasm', 'aisp.wasm');
149
177
  const bytes = await readFile(path);
150
178
 
@@ -165,12 +193,22 @@ const AISP = {
165
193
  return this._instance.aisp_init();
166
194
  },
167
195
 
196
+ /**
197
+ * Set maximum document size
198
+ * @param {number} size - Maximum size in bytes
199
+ */
200
+ setMaxDocSize(size) {
201
+ this._maxDocSize = Math.min(size, SIZE_LIMITS.ABSOLUTE_MAX);
202
+ },
203
+
168
204
  /**
169
205
  * Validate AISP document
170
206
  * @param {string} source - AISP source code
207
+ * @param {object} [options] - Validation options
208
+ * @param {boolean} [options.strict] - Use strict WASM validation (limited to 1KB)
171
209
  * @returns {object} Validation result
172
210
  */
173
- validate(source) {
211
+ validate(source, options = {}) {
174
212
  if (!this._instance) {
175
213
  throw new Error('AISP not initialized. Call init() first.');
176
214
  }
@@ -178,41 +216,100 @@ const AISP = {
178
216
  const encoder = new TextEncoder();
179
217
  const bytes = encoder.encode(source);
180
218
 
181
- const ptr = 0x1000;
182
- if (bytes.length > 1024) {
183
- return { valid: false, error: 'Document too large (max 1KB)' };
184
- }
185
-
186
- this._memory = new Uint8Array(this._instance.memory.buffer);
187
- this._memory.set(bytes, ptr);
188
-
189
- const docId = this._instance.aisp_parse(ptr, bytes.length);
190
- if (docId < 0) {
219
+ // Check size against configurable limit
220
+ if (bytes.length > this._maxDocSize) {
191
221
  return {
192
222
  valid: false,
193
- error: `Parse error at offset ${this._instance.aisp_error_offset()}`,
194
- errorCode: this._instance.aisp_error_code()
223
+ error: `Document too large (${bytes.length} bytes, max ${this._maxDocSize} bytes)`,
224
+ errorCode: -4
195
225
  };
196
226
  }
197
227
 
198
- const parseResult = this._instance.aisp_validate(docId);
199
-
200
- // Use semantic density calculation instead of WASM density
228
+ // Use semantic density calculation (works for all sizes)
201
229
  const densityResult = calculateSemanticDensity(source);
202
230
  const tierResult = getTierFromDelta(densityResult.delta);
203
231
 
232
+ // For documents within WASM limit, use WASM validation
233
+ if (bytes.length <= SIZE_LIMITS.WASM_MAX && options.strict !== false) {
234
+ const ptr = 0x1000;
235
+ this._memory = new Uint8Array(this._instance.memory.buffer);
236
+ this._memory.set(bytes, ptr);
237
+
238
+ const docId = this._instance.aisp_parse(ptr, bytes.length);
239
+ if (docId < 0) {
240
+ return {
241
+ valid: false,
242
+ error: `Parse error at offset ${this._instance.aisp_error_offset()}`,
243
+ errorCode: this._instance.aisp_error_code(),
244
+ tier: tierResult.tier,
245
+ tierValue: tierResult.tierValue,
246
+ tierName: tierResult.tierName,
247
+ delta: densityResult.delta,
248
+ pureDensity: densityResult.pureDensity
249
+ };
250
+ }
251
+
252
+ const parseResult = this._instance.aisp_validate(docId);
253
+
254
+ return {
255
+ valid: parseResult === 0,
256
+ tier: tierResult.tier,
257
+ tierValue: tierResult.tierValue,
258
+ tierName: tierResult.tierName,
259
+ delta: densityResult.delta,
260
+ pureDensity: densityResult.pureDensity,
261
+ ambiguity: this._instance.aisp_ambig(docId),
262
+ errorCode: parseResult,
263
+ mode: 'wasm'
264
+ };
265
+ }
266
+
267
+ // For larger documents, use pure JS validation
268
+ const jsValidation = this._validatePureJS(source, densityResult);
269
+
204
270
  return {
205
- valid: parseResult === 0,
271
+ valid: jsValidation.valid,
206
272
  tier: tierResult.tier,
207
273
  tierValue: tierResult.tierValue,
208
274
  tierName: tierResult.tierName,
209
275
  delta: densityResult.delta,
210
276
  pureDensity: densityResult.pureDensity,
211
- ambiguity: this._instance.aisp_ambig(docId),
212
- errorCode: parseResult
277
+ ambiguity: jsValidation.ambiguity,
278
+ errorCode: jsValidation.valid ? 0 : -3,
279
+ mode: 'js',
280
+ docSize: bytes.length
213
281
  };
214
282
  },
215
283
 
284
+ /**
285
+ * Pure JavaScript validation for larger documents
286
+ * @private
287
+ */
288
+ _validatePureJS(source, densityResult) {
289
+ // Check for AISP header
290
+ if (!source.trim().startsWith('𝔸')) {
291
+ return { valid: false, ambiguity: 1.0, error: 'Missing AISP header (𝔸)' };
292
+ }
293
+
294
+ // Check for required blocks
295
+ const requiredBlocks = ['⟦Ω', '⟦Σ', '⟦Γ', '⟦Λ', '⟦Ε'];
296
+ const missingBlocks = requiredBlocks.filter(b => !source.includes(b));
297
+
298
+ if (missingBlocks.length > 0) {
299
+ return {
300
+ valid: false,
301
+ ambiguity: 0.5,
302
+ error: `Missing required blocks: ${missingBlocks.join(', ')}`
303
+ };
304
+ }
305
+
306
+ // Valid if all required blocks present and density >= 0.20 (Bronze tier minimum)
307
+ const valid = densityResult.delta >= 0.20;
308
+ const ambiguity = valid ? 0.01 : 0.5;
309
+
310
+ return { valid, ambiguity };
311
+ },
312
+
216
313
  /**
217
314
  * Get detailed density breakdown for debugging
218
315
  * @param {string} source - AISP source
@@ -290,5 +387,5 @@ const AISP = {
290
387
  };
291
388
 
292
389
  export default AISP;
293
- export const { init, validate, isValid, getDensity, getTier, validateFile, debug, debugFile } = AISP;
294
- export { calculateSemanticDensity, calculatePureDensity, getTierFromDelta, AISP_SYMBOLS };
390
+ export const { init, validate, isValid, getDensity, getTier, validateFile, debug, debugFile, setMaxDocSize } = AISP;
391
+ export { calculateSemanticDensity, calculatePureDensity, getTierFromDelta, AISP_SYMBOLS, SUPPORTED_EXTENSIONS, SIZE_LIMITS };