{"_id":"@alxmss/toon","_rev":"4-47504d90e7933bd8e1c08c3c500bbbc0","name":"@alxmss/toon","dist-tags":{"latest":"1.0.3"},"versions":{"1.0.0":{"name":"@alxmss/toon","version":"1.0.0","_id":"@alxmss/toon@1.0.0","maintainers":[{"name":"alxmss","email":"alexander.m.s.strandberg@gmail.com"}],"bin":{"toon":"dist/bin/toon-check.js"},"dist":{"shasum":"d1c9aef8e74c99e84239df9476146cff3a4aac65","tarball":"https://registry.npmjs.org/@alxmss/toon/-/toon-1.0.0.tgz","fileCount":27,"integrity":"sha512-TBdK+BLlZXfnPo299ieatM/xPwv3tRPrgHg13hKlJqrMEOoIE4/dHZZ+Qi9bD49/54J2BihxPvw1E+tfXvEUJw==","signatures":[{"sig":"MEYCIQD0ghgQtG4mIcW3Mk+lokITX7EzeCrLWpMx8hKmzFrnAgIhALWOm9Gev+8xCXCI/0bIzAfawCXmI+WhPaIyARt6UqK/","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":123939},"main":"./dist/src/index.js","type":"module","types":"./dist/src/index.d.ts","exports":{".":{"types":"./dist/src/index.d.ts","import":"./dist/src/index.js"},"./lint":{"types":"./dist/src/lint.d.ts","import":"./dist/src/lint.js"},"./parse":{"types":"./dist/src/parse.d.ts","import":"./dist/src/parse.js"},"./prompt":{"types":"./dist/src/prompt.d.ts","import":"./dist/src/prompt.js"},"./stringify":{"types":"./dist/src/stringify.d.ts","import":"./dist/src/stringify.js"}},"gitHead":"cc6b8056a0eb9027d41656968d7fd642984ef1f3","scripts":{"test":"vitest run","build":"tsc","prepare":"tsc","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"alxmss","email":"alexander.m.s.strandberg@gmail.com"},"_npmVersion":"11.12.1","description":"Token-Oriented Object Notation — high-density serialization for LLM context windows","directories":{},"_nodeVersion":"24.15.0","dependencies":{"commander":"^12.1.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.15.0","vitest":"^1.6.0","typescript":"^5.4.5","@types/node":"^25.6.0","gpt-tokenizer":"^2.5.0","@anthropic-ai/sdk":"^0.91.1"},"_npmOperationalInternal":{"tmp":"tmp/toon_1.0.0_1777477200167_0.5396561752008335","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@alxmss/toon","version":"1.0.1","_id":"@alxmss/toon@1.0.1","maintainers":[{"name":"alxmss","email":"alexander.m.s.strandberg@gmail.com"}],"bin":{"toon":"dist/bin/toon-check.js"},"dist":{"shasum":"e3e50585f0557c094b7e7e3acffa78ea7309c3e9","tarball":"https://registry.npmjs.org/@alxmss/toon/-/toon-1.0.1.tgz","fileCount":27,"integrity":"sha512-Zb6Hz0quFLGYjv5jbB5jbOL2+H7tKkuFSKv33ZbuPSOdVE1CXwRL4WivYZFnijeWFsckuNwQ2zXKJ71KqCi8MA==","signatures":[{"sig":"MEUCIQD0jE2bOnDi23gAIsOyUXcX8r8uYOsWPMWM4gW7jWTXngIgb3aO0zm+IZQV4lgmuedEFpGGSKWtSMv1rAvCczLhCKs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":124007},"main":"./dist/src/index.js","type":"module","types":"./dist/src/index.d.ts","exports":{".":{"types":"./dist/src/index.d.ts","import":"./dist/src/index.js"},"./lint":{"types":"./dist/src/lint.d.ts","import":"./dist/src/lint.js"},"./parse":{"types":"./dist/src/parse.d.ts","import":"./dist/src/parse.js"},"./prompt":{"types":"./dist/src/prompt.d.ts","import":"./dist/src/prompt.js"},"./stringify":{"types":"./dist/src/stringify.d.ts","import":"./dist/src/stringify.js"}},"gitHead":"531dc186c37b7c7963bc900b3c9ffcded283ec0c","scripts":{"test":"vitest run","build":"tsc","prepare":"tsc","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"alxmss","email":"alexander.m.s.strandberg@gmail.com"},"_npmVersion":"11.12.1","description":"Token-Oriented Object Notation — high-density serialization for LLM context windows","directories":{},"_nodeVersion":"24.15.0","dependencies":{"commander":"^12.1.0","gpt-tokenizer":"^2.5.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.15.0","vitest":"^1.6.0","typescript":"^5.4.5","@types/node":"^25.6.0","@anthropic-ai/sdk":"^0.91.1"},"_npmOperationalInternal":{"tmp":"tmp/toon_1.0.1_1777478713355_0.2954186985638312","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@alxmss/toon","version":"1.0.2","_id":"@alxmss/toon@1.0.2","maintainers":[{"name":"alxmss","email":"alexander.m.s.strandberg@gmail.com"}],"bin":{"toon":"dist/bin/toon-check.js"},"dist":{"shasum":"eb6a7406e5629b7769e78be66f42d4f531a87b13","tarball":"https://registry.npmjs.org/@alxmss/toon/-/toon-1.0.2.tgz","fileCount":27,"integrity":"sha512-DoMY/MadWZpD7/K2agBECQIQe4xDL/02TwoaGKuTBc7QU8ty0IO4O3JkkWbBbymkFsh72UlKj1+SXz0gvlpACw==","signatures":[{"sig":"MEUCIE4HViojP4RaBdSmdyyj7DE7/vqQk/PrNJbN2L4lhFh0AiEA8O5+4daoZb/exRR6Jand/dtg7SZimVhQ4Kzn6jZxHiY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":124042},"main":"./dist/src/index.js","type":"module","types":"./dist/src/index.d.ts","exports":{".":{"types":"./dist/src/index.d.ts","import":"./dist/src/index.js"},"./lint":{"types":"./dist/src/lint.d.ts","import":"./dist/src/lint.js"},"./parse":{"types":"./dist/src/parse.d.ts","import":"./dist/src/parse.js"},"./prompt":{"types":"./dist/src/prompt.d.ts","import":"./dist/src/prompt.js"},"./stringify":{"types":"./dist/src/stringify.d.ts","import":"./dist/src/stringify.js"}},"gitHead":"3bdbb0c6e9911e1b7526c5b9716e3df3cb700ca9","scripts":{"test":"vitest run","build":"tsc","prepare":"tsc","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"alxmss","email":"alexander.m.s.strandberg@gmail.com"},"_npmVersion":"11.12.1","description":"Token-Oriented Object Notation — high-density serialization for LLM context windows","directories":{},"_nodeVersion":"24.15.0","dependencies":{"commander":"^12.1.0","gpt-tokenizer":"^2.5.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.15.0","vitest":"^1.6.0","typescript":"^5.4.5","@types/node":"^25.6.0","@anthropic-ai/sdk":"^0.91.1"},"_npmOperationalInternal":{"tmp":"tmp/toon_1.0.2_1777479788839_0.4226155961449427","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"@alxmss/toon","version":"1.0.3","description":"Token-Oriented Object Notation — high-density serialization for LLM context windows","type":"module","main":"./dist/src/index.js","types":"./dist/src/index.d.ts","exports":{".":{"import":"./dist/src/index.js","types":"./dist/src/index.d.ts"},"./stringify":{"import":"./dist/src/stringify.js","types":"./dist/src/stringify.d.ts"},"./parse":{"import":"./dist/src/parse.js","types":"./dist/src/parse.d.ts"},"./lint":{"import":"./dist/src/lint.js","types":"./dist/src/lint.d.ts"},"./prompt":{"import":"./dist/src/prompt.js","types":"./dist/src/prompt.d.ts"}},"bin":{"toon":"dist/bin/toon-check.js"},"scripts":{"build":"tsc","prepare":"tsc","test":"vitest run","test:watch":"vitest","typecheck":"tsc --noEmit"},"dependencies":{"commander":"^12.1.0","gpt-tokenizer":"^2.5.0"},"devDependencies":{"@anthropic-ai/sdk":"^0.91.1","@types/node":"^25.6.0","tsx":"^4.15.0","typescript":"^5.4.5","vitest":"^1.6.0"},"gitHead":"8ea437298379f2df96a37880b230d5bd4adf2986","_id":"@alxmss/toon@1.0.3","_nodeVersion":"24.15.0","_npmVersion":"11.12.1","dist":{"integrity":"sha512-4gBTDoIoK+324cAL3TBLG3IbIDl0dCw7hErRl5h7zTqoT/ZfQvwF4PCqP0iWlsBsLg38JVtt0G74D2KFAJLpnQ==","shasum":"9f1445a005b26d5fe171d673d237661866c96a3c","tarball":"https://registry.npmjs.org/@alxmss/toon/-/toon-1.0.3.tgz","fileCount":27,"unpackedSize":129996,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQChhUH1wla8ibZaIVdkCN6PYDKvsNO/iEyW9WkhXu9CKgIgUxN0f7HrkkdXr5/B4H7JMVuPsOBwhCUztUTWAfKgqqg="}]},"_npmUser":{"name":"alxmss","email":"alexander.m.s.strandberg@gmail.com"},"directories":{},"maintainers":[{"name":"alxmss","email":"alexander.m.s.strandberg@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/toon_1.0.3_1777494218556_0.056266252807082306"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-29T15:40:00.087Z","modified":"2026-04-29T20:23:38.812Z","1.0.0":"2026-04-29T15:40:00.298Z","1.0.1":"2026-04-29T16:05:13.523Z","1.0.2":"2026-04-29T16:23:08.998Z","1.0.3":"2026-04-29T20:23:38.707Z"},"description":"Token-Oriented Object Notation — high-density serialization for LLM context windows","maintainers":[{"name":"alxmss","email":"alexander.m.s.strandberg@gmail.com"}],"readme":"# TOON — Token-Oriented Object Notation\r\n\r\n![v1.0.2](https://img.shields.io/badge/version-1.0.2-brightgreen)\r\n![Tests](https://img.shields.io/badge/tests-80%2F80-brightgreen)\r\n![License](https://img.shields.io/badge/license-MIT-blue)\r\n\r\n**TOON is a serialization format for LLM context windows.** It replaces JSON with a compact, indentation-aware notation that cuts 30–57% of tokens from structured data — no information lost, no fine-tuning required.\r\n\r\n---\r\n\r\n## The Problem\r\n\r\nYou're building an LLM-powered feature. You serialize some data and stuff it into a prompt:\r\n\r\n```typescript\r\nconst context = JSON.stringify(records)  // 18,471 tokens\r\n```\r\n\r\nThat's expensive. JSON was designed for machines to parse, not for transformer attention. Every `\"key\":` is repeated on every row. Every `{`, `}`, `[`, `]` is a token that carries no information density. At scale — 200 log events, 50 API responses, a deep config object — this bloats your context window and your bill.\r\n\r\nTOON fixes this at the serialization layer:\r\n\r\n```typescript\r\nimport { stringify } from '@alxmss/toon'\r\nconst context = stringify(records)  // 9,985 tokens — 45.9% less\r\n```\r\n\r\nSame data. Same LLM. No prompt engineering. Just fewer tokens.\r\n\r\n---\r\n\r\n## How It Works\r\n\r\nTOON uses three core compression mechanisms:\r\n\r\n**1. HRV (Header-Row-Value)** — for arrays of uniform objects, keys are declared once in a header row instead of repeated on every item:\r\n\r\n```\r\n// JSON: 627 tokens\r\n[{\"method\":\"GET\",\"path\":\"/users\",\"auth\":true},{\"method\":\"POST\",\"path\":\"/users\",\"auth\":true},...]\r\n\r\n// TOON: 334 tokens (-46.7%)\r\nendpoints[len:3]:\r\n  # method | path    | auth\r\n  > GET    | /users  | true\r\n  > POST   | /users  | true\r\n  > GET    | /health | false\r\n```\r\n\r\n**2. Dot-path compression** — single-child object chains collapse to a flat path:\r\n\r\n```\r\n// JSON: 88 tokens\r\n{\"db\":{\"primary\":{\"host\":{\"address\":\"10.0.0.1\"}}}}\r\n\r\n// TOON: 38 tokens (-56.8%)\r\ndb.primary.host.address: 10.0.0.1\r\n```\r\n\r\n**3. Quote elision** — strings that can't be ambiguous (IPs, semver, URL paths, bare words) are never quoted. `3.2.1`, `10.0.0.1`, `/users/{id}` stay as-is.\r\n\r\n---\r\n\r\n## TOON + RTK: Two Layers, Zero Overlap\r\n\r\nIf you use [RTK](https://github.com/alxmss/rtk) (the token-saving command wrapper for Claude Code), these tools work at different layers — one does not replace the other.\r\n\r\n| Layer | Tool | What it compresses | When |\r\n|-------|------|-------------------|------|\r\n| **Development** | RTK | Shell command output entering Claude Code's context | `rtk vitest`, `rtk git diff`, `rtk tsc` |\r\n| **Runtime** | TOON | Structured data sent to your LLM in production | `stringify(data)` in your app |\r\n\r\nRTK keeps your dev loop lean. TOON keeps your users' API calls cheap. Stack both for a two-layer token budget.\r\n\r\n```\r\nDevelopment                        Runtime\r\n───────────────────────────────    ──────────────────────────────────────\r\nrtk vitest      → Claude Code      stringify(payload) → your LLM API call\r\nrtk git diff    → Claude Code      parse(llmOutput)   ← LLM response\r\nrtk tsc         → Claude Code\r\n```\r\n\r\n---\r\n\r\n## Installation\r\n\r\n```bash\r\nnpm i @alxmss/toon\r\n```\r\n\r\n**One-time Claude Code setup** (teaches Claude to use TOON automatically in this project):\r\n\r\n```bash\r\nnpx @alxmss/toon init\r\n```\r\n\r\nThis writes a TOON conventions block into your project's `CLAUDE.md`. From that point on, Claude Code uses `stringify()` and `TOON_SYSTEM_PROMPT` whenever it writes a feature that sends data to an LLM.\r\n\r\n---\r\n\r\n## Quick Start\r\n\r\n### Serialize data for an LLM\r\n\r\n```typescript\r\nimport { stringify, TOON_SYSTEM_PROMPT } from '@alxmss/toon'\r\n\r\nconst response = await anthropic.messages.create({\r\n  system: myInstructions + '\\n\\n' + TOON_SYSTEM_PROMPT,\r\n  messages: [{\r\n    role: 'user',\r\n    content: stringify(data),   // not JSON.stringify\r\n  }],\r\n})\r\n```\r\n\r\n`TOON_SYSTEM_PROMPT` (~280 tokens) teaches the model to read and emit TOON. Use `TOON_SYSTEM_PROMPT_COMPACT` (~90 tokens) for follow-up calls once the model is context-trained.\r\n\r\n### Parse LLM output back to an object\r\n\r\n```typescript\r\nimport { parse } from '@alxmss/toon'\r\n\r\nconst result = parse(llmOutput)\r\n// → plain JS object, round-trip exact\r\n```\r\n\r\n### Validate before parsing\r\n\r\n```typescript\r\nimport { lint } from '@alxmss/toon'\r\n\r\nconst issues = lint(toonString)\r\n// [{ severity: 'error', line: 4, column: 1, message: '...' }]\r\n// Empty array = structurally valid\r\n```\r\n\r\n### Measure savings on your own data\r\n\r\n```bash\r\nnpx @alxmss/toon check data.json\r\n```\r\n\r\n```\r\n  TOON Density Report — data.json\r\n  ────────────────────────────────────────────────────────────\r\n  Metric                              JSON      TOON     Delta\r\n  ────────────────────────────────────────────────────────────\r\n  Bytes                              56792     27334    -51.9%\r\n  Tokens (cl100k_base)               18471      9985    -45.9%\r\n  ────────────────────────────────────────────────────────────\r\n  Fits in window (128k)                10×       20×      ×2.00\r\n  ────────────────────────────────────────────────────────────\r\n\r\n  Density Score  45.9% reduction\r\n  [█████████░░░░░░░░░░░] 45.9%\r\n\r\n  Context Expansion Factor: 2.00× — TOON fits 2.00× more data in the same window\r\n```\r\n\r\n---\r\n\r\n## When to Use TOON\r\n\r\nTOON's compression is structural — it eliminates repeated key names and punctuation, not values. The gain scales with schema uniformity.\r\n\r\n### Maximum benefit (40–57%)\r\n\r\n| Use Case | Typical Saving | Why |\r\n|----------|---------------|-----|\r\n| Observability pipelines (CloudWatch, Datadog, Loki) | **~46%** | Log events are the most uniform data in existence → HRV |\r\n| GitHub / REST API responses (repos, issues, PRs) | **~46%** | Repeated field names across paginated records → HRV |\r\n| Infrastructure config (k8s, Terraform) | **~57%** | Long single-child chains → dot-path compression |\r\n| RAG pipelines with structured records | **35–47%** | DB rows, product catalogs, CRM contacts → HRV |\r\n| Agentic tool schemas / endpoint inventories | **35–45%** | Repeated schema fields across tool definitions → HRV |\r\n\r\n### Good benefit (30–40%)\r\n\r\n| Use Case | Typical Saving | Why |\r\n|----------|---------------|-----|\r\n| CI bots and PR review agents (mixed payloads) | **~35%** | Flat KV metadata + tabular arrays → dot-path + HRV |\r\n| LLM data transformation (validate / enrich / classify) | **30–45%** | Uniform input records → savings on both request and response |\r\n\r\n### Diminishing returns\r\n\r\n- **Prose documents** (articles, emails, legal text) — no structural repetition to eliminate\r\n- **Tiny payloads** (< 50 tokens) — `[len:N]` anchor overhead isn't amortized\r\n- **Highly irregular arrays** — falls back to block format, still ~20–30% savings\r\n\r\n### Not a fit\r\n\r\n- Human-edited config files — YAML/TOML are more ergonomic to write\r\n- Binary or streaming data\r\n- Top-level arrays — wrap in `{ items: [...] }` first\r\n\r\n---\r\n\r\n## Why the Savings Compound\r\n\r\n- **Lower API cost** — input tokens are priced per token; 46% fewer tokens = 46% less on that payload\r\n- **More data per window** — a 200k Claude window holds **1.85× more complete records** in TOON than JSON\r\n- **Faster time-to-first-token** — smaller prompts start streaming sooner\r\n- **Fewer RAG round-trips** — fitting more records per call reduces retrieval calls per session\r\n\r\nFor a pipeline processing 1M CloudWatch events/day, the measured 45.9% reduction translates to **~42M tokens saved** — before latency improvements.\r\n\r\n---\r\n\r\n## Measured Results\r\n\r\n### Synthetic fixtures (validated on every `npm test`)\r\n\r\n| Shape | JSON Tokens | TOON Tokens | Savings |\r\n|-------|-------------|-------------|---------|\r\n| 12-row uniform table | 627 | 334 | **46.7%** |\r\n| 6-row sparse table (1 optional col) | 294 | 196 | **33.3%** |\r\n| Mixed document (KV + HRV + dot-path) | 415 | 271 | **34.7%** |\r\n| Deeply nested config (3 levels) | 88 | 38 | **56.8%** |\r\n| Non-uniform block array | 111 | 77 | **30.6%** |\r\n\r\n### Real-world stress test (`scripts/stress-test.ts`)\r\n\r\n| Fixture | JSON Tokens | TOON Tokens | Reduction | 200k window CEF |\r\n|---------|-------------|-------------|-----------|-----------------|\r\n| CloudWatch logs — 200 events × 9 fields | 18,471 | 9,985 | **45.9%** | **2.00×** |\r\n| GitHub repos — 50 repos × 12 fields | 5,457 | 2,919 | **46.5%** | **1.89×** |\r\n\r\n*CEF = Context Expansion Factor: how many more complete documents fit in the same window.*  \r\n*Tokenizer: cl100k_base (same encoder as GPT-4). Run `node_modules/.bin/tsx scripts/stress-test.ts` to reproduce.*\r\n\r\n### LLM handshake verification\r\n\r\n`TOON_SYSTEM_PROMPT` was verified against `claude-sonnet-4-6` on a 12-row HRV CloudWatch log with a three-part reasoning task. Score: **5/5** — correct on highest latency value, timestamp, most-errored user, error count, and root-cause pattern. The TOON payload used ~180 tokens vs ~420 for equivalent JSON — **57% less on the reasoning task itself**.\r\n\r\n```bash\r\nANTHROPIC_API_KEY=sk-... node_modules/.bin/tsx scripts/handshake-test.ts\r\n```\r\n\r\n---\r\n\r\n## API Reference\r\n\r\n### `stringify(value, options?)`\r\n\r\n```typescript\r\nstringify(value: Record<string, unknown>, options?: {\r\n  indent?: 2 | 4       // default: 2\r\n  dotPath?: boolean    // default: true  — compress single-child chains\r\n  sizeHints?: boolean  // default: true  — emit [len:N] anchors\r\n  hrvThreshold?: number // default: 0.5  — max extra/base key ratio for sparse HRV\r\n}): string\r\n```\r\n\r\nThrows `TypeError` if top-level value is not a plain object.  \r\nThrows `ToonSerializationError` on circular references.\r\n\r\n### `parse(input, options?)`\r\n\r\n```typescript\r\nparse(input: string, options?: {\r\n  validateHints?: boolean  // default: true — throw on [len:N] length mismatch\r\n}): Record<string, unknown>\r\n```\r\n\r\nThrows `ToonParseError` (with `.line`, `.column`, `.suggestion`) on violations.\r\n\r\n### `lint(input)`\r\n\r\n```typescript\r\nlint(input: string): Issue[]\r\n// Issue: { severity: 'error' | 'warning', line: number, column: number, message: string }\r\n```\r\n\r\nNever throws. Returns all structural issues in one pass — use before `parse()` in CI or editor integrations.\r\n\r\n### `TOON_SYSTEM_PROMPT` / `TOON_SYSTEM_PROMPT_COMPACT`\r\n\r\nPre-written system prompt snippets. Full (~280 tokens) for first-time integration; compact (~90 tokens) for follow-up calls.\r\n\r\n---\r\n\r\n## CLI\r\n\r\n```bash\r\n# One-time project setup\r\nnpx @alxmss/toon init           # writes TOON block to ./CLAUDE.md\r\nnpx @alxmss/toon init --global  # writes to ~/.claude/CLAUDE.md\r\n\r\n# Measure token savings on any JSON file\r\ntoon check data.json\r\ntoon check data.json --window 32000   # custom context window\r\ntoon check data.json --toon           # also print the TOON output\r\n```\r\n\r\n---\r\n\r\n## Format Reference\r\n\r\n### Sigils\r\n\r\n| Sigil | Role | Example |\r\n|-------|------|---------|\r\n| `key: value` | Key-value pair | `name: Alice` |\r\n| `a.b.c: value` | Dot-path (single-child chain) | `db.host: localhost` |\r\n| `[len:N]` | Size hint / structural anchor | `users[len:3]:` |\r\n| `# col1 \\| col2` | HRV header | `# id \\| name \\| role?` |\r\n| `> v1 \\| v2` | HRV data row | `> 1 \\| Alice \\| admin` |\r\n| `- key: value` | Block array item | `- method: GET` |\r\n| `~` | Null / absent | `latency: ~` |\r\n| `col?` | Optional HRV column | `# id \\| note?` |\r\n| `//` | Line comment | `// deprecated` |\r\n\r\n### Type inference (first match wins)\r\n\r\n```\r\n~ or null      → null\r\ntrue / false   → boolean\r\nbare integer   → int\r\nbare float     → float\r\n\"…\"            → string\r\n[…]            → inline array\r\n{…}            → inline object\r\nanything else  → bare string   (IPs, semver, URL paths never need quotes)\r\n```\r\n\r\n### Array tier selection\r\n\r\n```\r\nAll scalars                        → key[len:N]: a, b, c\r\nAll objects, no optional keys      → HRV-uniform  (# / > rows)\r\nObjects with ≤50% optional keys    → HRV-sparse   (col? columns, ~ for absent)\r\nOtherwise                          → Block array  (- items)\r\n```\r\n\r\n---\r\n\r\n## Spec\r\n\r\nFormal EBNF grammar: [`spec/GRAMMAR.md`](spec/GRAMMAR.md)\r\n\r\nKnown limitations:\r\n- Block string `|` is parse-only (stringify uses quoted strings instead)\r\n- `NaN` / `Infinity` serialize as quoted strings\r\n- Top-level arrays are not supported — wrap in `{ items: [...] }`\r\n","readmeFilename":"README.md"}