# Chisel M64 Artifact Workbench

## Inspect, compress, compare, publish (read-only first)

The Dark Star workbench now exposes both Polygon contract addresses together. **Inspect dictionary terms** verifies the selected M64Dictionary, reports its total term count and loads term IDs/text in pages of 64. **Inspect and compress** reads only existing on-chain terms, leaves missing words as literal ASCII, reconstructs the canonical JavaScript and verifies SHA-256. It does **not** write to either contract or request wallet approval. There is a separate wallet-authorized **Add missing terms** action if the publisher chooses to grow the immutable vocabulary.

The compression report displays original/canonical source bytes, decoded internal stream bytes, exact 64-symbol M64 text bytes, v3 JSON bytes, and the **complete Chisel envelope** projected using fixed-length placeholder template transaction and template SHA-256 fields. Projected envelope size is the same as the final envelope size because the locator/hash widths are fixed. Savings may be negative. At unsigned transaction preview it additionally compares ABI calldata size and, when RPC supports it, estimated gas for the full M64 record versus uncompressed source written through the same `logRecord(bytes32,bytes)` method. That marginal comparison **does not include** one-time dictionary additions, renderer-template log, any IPFS overhead, or on-chain historical data duplication from calldata and emitted log.

Publishing remains an explicit wallet action. The program record names the exact dictionary contract and the template transaction hash. Read-only reconstruction verifies both Chisel events and on-chain dictionary entries. Independent deterministic CID reproduction still requires a fixed IPFS DAG/CAR import profile.


## Polygon deployment used for Dark Star Z (reported 2026-11-07)

The M64 dictionary **has already been deployed and populated**. This is not a proposed or empty contract. The reported Dark Star Z deployment extracted and published **51 symbols**. Those existing dictionary entries are the source of truth when encoding and reconstructing this artifact. The live count may grow; use the Workbench's `Inspect M64Dictionary` control to query the chain.

- Polygon mainnet chain ID: `137`.
- M64Dictionary (symbol IDs / term lookup): `0x522afe4f086da1df80531dea1e8793b05cace9cf`.
- Full immutable dictionary reference: `eip155:137:0x522afe4f086da1df80531dea1e8793b05cace9cf`.
- Chisel (record publisher): `0x683cfA103FE5DbD0a47402d78Fbf818D4160B1d3`.

**Binding requirement:** A Chisel M64 **program** record must carry the exact dictionary reference in its `artifact.dictionary.ref`, not merely use a local dictionary or assume that Chisel contains symbol values. The packed `CM64` v2 envelope includes `artifact.dictionary.ref`, the Chisel carrier reference, the exact M64 text, and a reference plus SHA-256 for the earlier renderer-template log. During preparation, Chisel must reject any disagreement between the selected dictionary contract and the artifact's embedded reference, hydrate against that deployed contract, and check the canonical SHA-256/byte count. This is how the two separate contracts become one reproducible program record.

The `Preview renderer transaction` operation itself references only Chisel, because the HTML template is dictionary-independent. The **subsequent program transaction** references both Chisel and M64Dictionary (and the renderer transaction). A deployed/populated dictionary is not evidence that a Chisel program record has been published. The addresses and 51-symbol baseline above are user-reported; the current session could not independently query the live Polygon state.

## Dual-contract M64 ledger reconstruction (development branch)

The Dark Star workbench can publish a self-contained renderer template (including landscape controls) and a versioned M64 program record as `Chisel.logRecord()` events, then retrieve both from Chisel and resolve the JavaScript source using the exact on-chain dictionary address embedded in the program record. This requires a deployed Chisel contract, a usable dictionary contract, a wallet for writes, and public RPC for reads. A full ledger-to-IPFS CID reproduction test remains outstanding.

**Transport precision:** M64 text uses a complete 64-character Base64url alphabet. There is **not** a special 64th printable escape character. The extension escape is byte `0xC0` in the decoded abstract stream. Dictionary IDs 0–63 are direct single-byte references; 64+ use `0xC0 + varuint`. On Polygon, M64 text is sent as UTF-8 bytes via `bytes` and displayed as hexadecimal by RPC/explorers. The text is not replaced with the decoded abstract byte stream.

See [M64 wire format and compression metrics](M64_WIRE_FORMAT.md) for exact layouts, the two contract references, recovery steps, and accounting for published text versus source, metadata, gas, and reusable dictionary/template setup.

## Active M64 v3 workbench (2026-11-06)

**M64 v3 is the only current user-facing artifact format.** `index.html` is now a thin host for `dark-star-z.html`, the standalone interactive Dark Star Z viewer. Chisel's Examples page can also embed the viewer as an iframe.

- Without a CID, the viewer loads `examples/darkstar-core.js` and renders locally. Changing line, slope and color controls reruns the code without any transaction.
- With `?cid=<artifact-cid>`, it fetches a v3 artifact JSON through a configured IPFS gateway, resolves its declared EVM dictionary through read-only JSON-RPC, checks canonical byte length and SHA-256, and **waits for the user's Render action** before running CID-supplied code.
- To make a v3 artifact, set the address of an actual `M64Dictionary` contract and RPC chain. The builder checks missing terms, asks before any wallet-funded `addTerms` transaction, and generates a downloadable external-dictionary v3 artifact.
- The same page can save the rendered PNG, save a parameter preset, or upload the v3 artifact JSON, PNG, or a **self-contained interactive HTML page** to public IPFS through Pinata v3 with a user-provided session-only JWT. HTML export inlines the page's same-origin JavaScript dependencies and embeds its Dark Star source and current parameters. The Pinata credential is cleared from the exported document; it is not saved to localStorage, embedded into artifacts, or committed. The exported standalone page is intended to run from a single IPFS CID without a separate directory upload.
- The page can draft the 72-byte `CT1|+|H|<sha256>` / `CT1|-|H|<sha256>` UTXO ASCII trust-warning convention, but no signatures or attestations are broadcast automatically. See [cross-chain thunder attestations](../../docs/CROSS_CHAIN_THUNDER_ATTESTATIONS.md).

Historical `hydrate.html` and the older v2 artifact validator still exist as internal/archived code until their remaining dependencies and tests are retired. They are no longer the linked Workbench or recommended artifact format. Do not emit new v2 artifacts.

**Note:** This browser UI is a prototype; it has passed static inline-JavaScript syntax checking, not a live wallet/IPFS/Pinata end-to-end test in this environment.

M64 is a compact transport for an abstract byte stream. It is not an image format and it is not inherently JavaScript-specific.

The current pipeline is:

```text
source/data
   |
canonical form
   |
dictionary collection / lookup
   |
dictionary-index byte stream
   |
M64 transport
   |
dictionary hydration
   |
runtime
```

## Active direction

The durable development order is in [`../../docs/NEXT_DEVELOPMENT.md`](../../docs/NEXT_DEVELOPMENT.md).

The immediate objective is **not** to invent another compression scheme. It is to stabilize M64 as a protocol:

1. keep a small executable regression floor;
2. freeze an M64 v3 external-dictionary artifact schema;
3. separate the JavaScript source adapter from the language-neutral M64 transport/dictionary core;
4. implement a simple append-only shared ledger dictionary;
5. measure marginal artifact cost after vocabulary already exists on-ledger;
6. use the result for the staged recursive Chisel rebuild experiment.

The regression floor is active. `m64.artifact.js` provides the executable v3 schema boundary, `m64.javascript.js` provides the explicit JavaScript canonicalizer boundary, `m64.dictionary.js` provides a transport-neutral resolver, and `m64.v3.js` now proves the v3 canonicalize/publish/hydrate/integrity loop against an in-memory dictionary provider.

The JavaScript language/version and canonicalizer assumptions belong to artifact metadata. The dictionary can declare its language, but JavaScript language-version details should not be baked into the dictionary contract itself. M64 transport should remain usable for JavaScript, Python, MIDI/binary generators, or other deterministic payload families.

## Design notes

The broader ledger/dictionary/IPFS direction is recorded in:

- [`LEDGER_IPFS_ARCHITECTURE.md`](LEDGER_IPFS_ARCHITECTURE.md) - EVM as durable data/reference substrate, plural append-only dictionaries, contract/transaction references, cross-ledger graphs, deterministic IPFS/CAR reconstruction, and recovery from zero hosted IPFS copies.

That document intentionally separates implemented M64 mechanics from architectural ideas that are not yet a frozen live protocol.

## Historical M64 v2 dictionary encoding (legacy codec background)

The original staging format had a hard ceiling of 64 profile tokens. That ceiling is removed.

Dictionary references now have two forms:

```text
0x80..0xBF       dictionary indexes 0..63
0xC0 <varuint>   dictionary indexes 64 and above
0x00..0x7F       literal canonical ASCII
```

The first 64 terms therefore retain the cheapest possible one-byte references. Larger dictionaries use a compact variable-length integer only when the index exceeds 63.

A dictionary can now grow monotonically without changing the M64 transport. Thousands or millions of terms are possible in principle. The practical limit is the dictionary implementation, not M64.

## Automatic collection

The workbench starts with a small seed dictionary and scans canonical source for lexical terms. Newly encountered terms are appended to the dictionary and immediately become reusable references.

That means terms such as:

```text
function
return
Uint8Array
width
height
drawLine
```

need not be emitted repeatedly into the abstract stream once they have dictionary indexes.

The current collector is intentionally simple. It collects identifier/word-like terms of two or more characters. Manual dictionary entries can still represent punctuation, operators, method fragments, common phrases, or other repeated byte sequences.

## External dictionary lookup

The core codec no longer assumes that the dictionary must be an embedded array. `m64.js` exposes chain-neutral lookup hooks:

```text
collectDictionaryTerms(source, knownTerms)
resolveTerms(terms, termToIndexLookup)
tokenizeResolved(source, termToIndexMap)
dictionaryIndexes(bytes)
hydrateLookup(payload, alphabet, indexToTermLookup)
```

This is the intended bridge to a shared ledger dictionary.

For a JavaScript dictionary contract, the flow can be:

```text
canonical source
   |
collect terms
   |
contract lookup(term) -> numeric id
   |
add missing term to contract
   |
contract returns stable numeric id
   |
M64 stores only ids + unavoidable literals
```

Hydration performs the inverse operation:

```text
M64 payload
   |
extract dictionary ids
   |
contract/cache lookup(id) -> term
   |
reconstruct canonical source
```

M64 itself does not care whether those lookups come from an EVM contract, a locally cached mirror, IPFS, DigiByte/Litecoin metadata, or another registry.

## Retired v2 artifact package (historical)

The former Workbench exported a self-contained version 2 artifact with an embedded dictionary snapshot. This historical format is no longer exposed by the active v3 Workbench:

```json
{
  "kind": "chisel-m64-artifact",
  "version": 2,
  "type": "javascript",
  "runtime": "CHISEL-PURE1",
  "entry": "a",
  "profile": {
    "kind": "m64-profile",
    "version": 2,
    "alphabet": "...64 characters...",
    "tokens": ["function", "return", "..."]
  },
  "input": {},
  "payload": "...M64..."
}
```

That embedded snapshot is staging scaffolding, not the desired final ledger format.

The legacy `validateArtifact()` path intentionally remains v2-only so the existing workbench and `hydrate.html` cannot accidentally accept a v3 artifact that they do not yet know how to resolve.

## Executable M64 v3 draft

`m64.artifact.js` adds a separate `validateArtifactV3()` boundary. The current executable draft is:

```json
{
  "kind": "chisel-m64-artifact",
  "version": 3,
  "language": "javascript",
  "languageVersion": "es2026",
  "codec": "m64-dict-v1",
  "canonicalizer": "js-canonical-v1",
  "dictionary": {
    "kind": "ledger-dictionary",
    "ref": "eip155:137:0x...",
    "version": 1,
    "language": "javascript"
  },
  "runtime": "CHISEL-PURE1",
  "entry": "a",
  "payload": "...M64...",
  "canonicalBytes": 0,
  "sha256": "<64 lowercase hex characters>"
}
```

For `m64-dict-v1`, the transport alphabet is fixed rather than repeated in every artifact:

```text
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_
```

The validator checks package kind/version, language/runtime metadata, codec/canonicalizer IDs, dictionary descriptor shape, M64 payload structure, canonical byte-count shape, and lowercase SHA-256 field shape.

With a resolver, `hydrateArtifactV3()` goes further: it requires the resolver descriptor to match the artifact dictionary reference, resolves every dictionary ID, reconstructs canonical source, checks `canonicalBytes`, and recomputes/verifies SHA-256.

The missing production piece is now a durable ledger-backed resolver provider and publish path, not the basic client protocol loop.

## JavaScript adapter boundary

`m64.javascript.js` defines `js-canonical-v1` as an explicit conservative source adapter around the legacy canonicalizer. It exports:

```text
inspectJavascriptV1(source)
canonicalizeJavascriptV1(source, identifierMap)
JS_CANONICAL_V1.id
```

The important rule is rejection rather than guesswork. `js-canonical-v1` currently:

- accepts the ordinary syntax used by the existing Dark Star M64 example;
- accepts normal division such as `x / 2`;
- skips ordinary line and block comments during preflight;
- rejects template literals because the legacy canonicalizer does not understand interpolation safely;
- rejects regular-expression literals and ambiguous slash positions rather than allowing identifier renaming inside regex source;
- rejects unterminated quoted strings, block comments, and unbalanced parentheses found by the preflight scanner.

This is deliberately a safe subset, not a complete JavaScript parser. Existing v2 workbench behavior remains unchanged. New v3 JavaScript publishing should go through `canonicalizeJavascriptV1()` until a later canonicalizer version expands the accepted syntax with equivalent regression coverage.

## Dictionary resolver boundary

`m64.dictionary.js` separates dictionary semantics from transport. A resolver exposes:

```text
describe()
idForTerm(term)
termForId(id)
ensureTerm(term)
ensureTerms(terms[])
```

The descriptor is the same structure stored in a v3 artifact:

```json
{
  "kind": "ledger-dictionary",
  "ref": "<stable provider-specific identity>",
  "version": 1,
  "language": "javascript"
}
```

The resolver wrapper accepts provider functions corresponding to `lookupId(term)`, `lookupTerm(id)`, `addTerm(term)`, and optional batched `addTerms(terms[])`. `createMemoryDictionary()` supplies an append-only in-memory reference implementation with stable numeric IDs and a `snapshotTerms()` helper for tests.

This is deliberate inversion of control. Polygon should implement this interface. Polygon should not define it.

## End-to-end v3 client loop

`m64.v3.js` adds:

```text
buildJavascriptArtifactV3(source, options)
hydrateArtifactV3(artifact, resolver)
sha256HexUtf8(text)
```

`buildJavascriptArtifactV3()` performs:

```text
JavaScript source
  -> js-canonical-v1
  -> collect lexical terms
  -> resolver.ensureTerms()
  -> dictionary IDs
  -> M64 payload
  -> v3 artifact + canonical byte count + SHA-256
```

`hydrateArtifactV3()` performs the inverse and verifies integrity:

```text
v3 artifact
  -> validate schema
  -> verify resolver identity
  -> resolve dictionary IDs
  -> canonical source
  -> verify byte count
  -> verify SHA-256
```

The artifact does not embed the dictionary term array. Tests now exercise this loop with both a small JavaScript function and the Dark Star renderer.

## CHISEL-PURE1

A hydrated JavaScript artifact defines a plain entry function and the host invokes:

```js
entry(input)
```

The result should be structured-cloneable data such as a string, number, object, array, `ArrayBuffer`, or typed array.

This is deliberately not image-specific. A PURE1 artifact can implement raster generation, MIDI generation, text transformation, encoding/decoding, transaction serialization, parsers, or other deterministic protocol logic.

## Regression tests

The protocol-floor tests live in `../../tests/m64.test.mjs` and run in GitHub Actions:

```bash
node --test tests/m64.test.mjs
```

They cover byte transport round trips, stage/hydrate equality, dictionary IDs above 63, external dictionary hydration, malformed/reserved encoding rejection, the v2 workbench validation boundary, the v3 schema validator, JavaScript adapter safety, append-only resolver behavior, resolver mismatch rejection, integrity tamper rejection, and complete v3 round trips for ordinary JavaScript and Dark Star.

## Files

- `m64.js` - current compatibility facade plus canonicalization, growing dictionary codec, external lookup hooks, and M64 transport
- `m64.artifact.js` - M64 v3 artifact/dictionary-reference validation boundary
- `m64.javascript.js` - conservative `js-canonical-v1` source adapter/preflight boundary
- `m64.dictionary.js` - transport-neutral dictionary resolver plus in-memory reference provider
- `m64.v3.js` - v3 JavaScript publish/hydrate/integrity orchestration
- `index.html` - current v3 Workbench host embedding the standalone Dark Star Z viewer
- `hydrate.html` - retired standalone v2 hydrator kept in tree for historical reference
- `polygon.html` - browser EIP-1193 carrier for writing artifact text into Polygon transaction calldata
- `LEDGER_IPFS_ARCHITECTURE.md` - design notes for ledger references, shared dictionaries, cross-ledger objects, and deterministic IPFS recovery
- `SELF_REBUILD.md` - staged recursive Chisel recovery direction
- `dark-star-z.html` - standalone interactive v3 viewer, self-contained HTML export, public IPFS publication, and thunder trust/warning drafts
- `examples/` - Dark Star renderer source and earlier examples

## Polygon carrier

`polygon.html` remains intentionally separate from the compression layer. It carries arbitrary UTF-8 artifact text in transaction calldata. M64 and the dictionary model therefore remain independent of Polygon and can later be referenced from multiple ledgers.
