contextweigh documentation

The versioned JSON contract, the exit-code contract, the supported adapters, and exactly what the measurement claims.

Home

Input contract

The native input is a versioned JSON envelope carrying an ordered list of content blocks. Each block is an object with a UTF-8 text string. The envelope is capped at 1 MiB, 1000 blocks, and JSON nesting depth 32.

{
  "suite": "v1",
  "blocks": [
    { "text": "you are a helpful assistant" },
    { "text": "you are a helpful assistant" },
    { "text": "what is the capital of France?" }
  ]
}

No block text is ever echoed back in the report. Output carries each block's index, counts, and a content hash only. Hashes are pseudonyms — they can be dictionary-guessed and are not anonymization.

Output contract

The report measures UTF-8 bytes and exact whole-block duplicates, and totals the bytes and whitespace tokens the duplicates cost. Two views ship:

The result is tri-state: unknown is kept distinct from pass and fail. A run with no measurable blocks is unknown, not a pass.

Exit-code contract

The exit code is part of the contract, so the CLI drops into CI without parsing output:

CodeMeaning
0pass — no duplicate context found
1fail — duplicate context found
2unknown or unsupported input

Adapters

Adapters are one-way imports: they translate a recorded run into the block contract. They do not reconstruct, replay, or store the run, and make no provider-token claim.

conereplay-v1

Accepts adapter=conereplay-v1 with trace.events from a recorded ConeReplay EventRecord. UTF-8 input/output strings are split into blocks. It does not assert the blocks were all transmitted to a provider.

openai-chat-v1

Accepts adapter=openai-chat-v1 with a chat-completions messages[] array — the resent-history case. Each message's text becomes a block, so repeated system/tool context across the array is detected. A string content becomes one block; null/absent content (for example an assistant turn carrying only tool_calls) contributes no block; an array of content parts contributes one block per type=text part, while non-text parts (image/audio) are out of measurement scope and ignored. Any other content shape is refused. Caps: the shared 1 MiB / depth-32 envelope limit plus 1000 messages and 1000 content parts per message.

What the measurement does and does not claim

The tokenizer is unicode-whitespace v1.0, labeled explicitly and not a provider-model tokenizer. Counting is deterministic. The tool does not claim model tokens, a billing estimate, substring repetition, semantic duplication, or context truncation. Evaluation never executes payload code, fetches URLs, or contacts a provider. A report needs owner review before disclosure.

Status

Hosted history, teams, and billing are not yet available: by design they stay off until authentication, isolation, retention, and deletion tests pass. See the implementation notes for the exact caps and the acceptance fixtures.