Canonical Definition: SCL is a protocol for deterministic, cryptographic identity of AI run declarations. This definition is normative and MUST be used when defining the protocol.

SCL:V1 Specification

Final · Frozen · Immutable

This document defines the only valid grammar for SCL:V1. All engines and SDKs MUST match this exactly: bytes in → AST out → canonical JSON out → hash out.

Canonical source: SCL:V1 Specification (this document)
Reference implementation: C (scl-core)
Conformance tools: Python, C++, Rust
This specification is immutable. Any change constitutes a new protocol version.
No changes will ever be made to SCL:V1 after launch. Future revisions belong to SCL:V2.
This spec is normative. Any behavior not explicitly allowed here is forbidden.

0. Normative Definitions #

0.1 Byte Model #

SCL:V1 documents are sequences of bytes.

0.2 Encoding (UTF-8 Only) #

0.3 Line Endings (LF Only) #

0.4 Forbidden Bytes (Global) #

0.5 Forbidden Control Characters Inside Quoted Strings #

Inside any quoted string (handle tags or SCL quoted content):

Control-character checks apply to decoded Unicode code points after UTF-8 validation (not raw bytes).

0.6 Deterministic Error Rule ("First Failure") #

Recommendation: engines SHOULD expose (code, byte_offset) internally even if the public API only returns code.

0.7 Token Bytes and Comparisons #

Unless explicitly stated otherwise:

1. Document Structure #

A valid SCL:V1 document MUST be exactly:

  1. Header line: SCL:V1
  2. One blank line (exactly \n\n)
  3. Handles block
  4. Immediately followed by SCL block with no blank line between
  5. End of document exactly at the final } of the SCL block (no extra bytes)

No other blank lines are permitted anywhere else in the document.

A "blank line" is a physical line consisting of exactly LF with no preceding bytes.

Top-level order is fixed: Header → Handles → SCL.

Any violation MUST raise a deterministic error per §0.6 and the error codes table.

2. Header #

Valid header line is exactly:

SCL:V1

Rules:

Invalid header → E101 (byte offset is the first byte where the header cannot match, per §0.6).

3. Handles Block #

3.1 Exact Block Delimiters

The handles block MUST be:

Missing handles block → E102

EOF before handles closes → E103

3.2 Handles Block Contents

3.3 Handle Definition Line Grammar #

A handle definition is one physical line ending with LF:

<indent><handle_id>(<tag_list>)\n

<handle_id>

Regex (ASCII only):

^[A-Za-z_][A-Za-z0-9_]*$

Invalid → E201

Exact Punctuation / Spacing Rules

Deterministic Handle-line Parsing (MANDATORY)

Engines MUST parse each non-empty handles-block line using this fixed procedure:

  1. Parse <indent> as zero or more bytes 0x20.
  2. Parse <handle_id> bytes matching [A-Za-z_][A-Za-z0-9_]*. Otherwise raise E201.
  3. Next byte MUST be ( with no intervening spaces. If LF or space, raise E201.
  4. Parse <tag_list> inside parentheses using §3.4. Any failure raises E202 (unless E001 applies).
  5. After closing ), next byte MUST be LF. If any byte other than LF occurs, raise E201.

3.4 Tag List Grammar #

Tags appear inside parentheses:

id("tag1","tag2")

Rules:

Invalid tag syntax → E202. Invalid UTF-8/control/CR/tab → E001

4. SCL Block #

4.1 Exact Block Delimiters

Missing SCL block → E104

EOF before SCL block closes → E105

4.2 Content Modes #

Immediately after scl {\n, content MUST be in exactly one of two modes. Once selected by the first content line, all subsequent lines MUST conform to that mode.

Mode A — Quoted Mode

A quoted-mode body is one or more physical lines, each of the form:

<indent>"<bytes>"\n

Termination: ends when next line is exactly } followed by EOF (no trailing LF).

AST content: strip outer quotes, join inner contents with \n between lines.

Mode B — Raw Mode

Raw mode begins when the first content line after scl {\n does NOT begin (after optional spaces) with ".

  1. Raw content begins on the line after scl {\n.
  2. Ends when final bytes match: optional spaces, then }, then EOF.
  3. If candidate terminator matches ^[ ]*}[ ]+$, raise E104 at first trailing space.
  4. Empty physical lines within raw content are allowed.
  5. Raw content must be valid UTF-8 → E001.

AST content: concatenate all raw lines before terminator, joined with \n.

5. AST Canonical Form #

Every engine MUST emit exactly this AST object model:

{
  "type":"Document",
  "version":"SCL:V1",
  "handles":[
    {
      "type":"Handle",
      "id":"<id>",
      "tags":["<tag1>","<tag2>"]
    }
  ],
  "scl":{
    "type":"SclBlock",
    "content":"<content-bytes-as-utf8-string>",
    "refs":[],
    "hints":[]
  }
}

Invariants:

6. Canonical JSON & Document Hash #

The canonical JSON bytes are the sole hash input for SCL:V1.

Engines MUST canonicalize the parsed document (AST canonical form; §5) to canonical JSON bytes. The Document Hash is:

doc_hash = SHA256(canonical_json_bytes)
SCL:V1 Document canonical JSON uses only JSON objects, arrays, and strings. Numbers, booleans, and null do not appear.

6.1 Canonical JSON Rules #

6.2 Document Hash Invariance #

The hash input is the canonical JSON byte sequence exactly as emitted (no Unicode normalization, newline translation, or whitespace modification).

Any two SCL inputs that parse to the same AST MUST produce identical canonical JSON bytes and therefore identical doc_hash.

The Document Hash is not SHA256(raw_input_bytes). If an implementation exposes a raw-input checksum, it MUST be named distinctly and MUST NOT be described as the Document Hash.

7. Error Codes #

CodeMeaning
E001Invalid UTF-8, CR, tab, or forbidden control character
E101Missing or invalid SCL:V1 header
E102Handles block missing, empty, or contains an invalid line
E103Unclosed handles block (EOF before closing })
E104Missing SCL block, or invalid token where SCL content/terminator expected
E105Unclosed SCL block (EOF before valid SCL termination)
E201Invalid handle ID
E202Invalid tag list or tag token
E900Internal parser error

8. Forbidden Syntax #

Everything not explicitly allowed by this spec is forbidden, including:

9. Change Control #

SCL:V1 is frozen after launch. Any change requires SCL:V2.