Skip to content

Clarify parser tolerance rules in CACP wire spec — implementers diverge, causing interop bugs #4

@zenprocess

Description

@zenprocess

Problem

The CACP spec shows examples in the canonical compact form (STATUS:ok, no whitespace after the colon) but does not specify whether parsers MUST tolerate human-readable variants like STATUS: ok, STATUS:\tok, or STATUS: ok.

This ambiguity has caused real interop bugs. A production implementation hit a multi-release cascade caused by the parser rejecting whitespace variants while the system prompt taught the agent to emit STATUS: ok (with whitespace). Several agent-side fixes (drift detection, two-phase closure, JSON-schema enforcement) were shipped before the root cause was identified as a parser tolerance bug — a single missing \s* in the regex.

Recommended ratification

Add a new section to the CACP wire format spec:

Parser Tolerance Rules

The canonical wire format is FIELD:value with no whitespace between the colon and the value, for token compactness (the "C" in CACP). This is what emitters SHOULD produce.

Parsers MUST tolerate whitespace variants:

  • FIELD:value (canonical compact)
  • FIELD: value (single space — common in human-edited examples)
  • FIELD: value (multiple spaces)
  • FIELD:\tvalue (tab separator)

Parsers MUST tolerate field-name case variants (treat field names as case-insensitive):

  • STATUS:, status:, Status:, STATus:

Parsers MUST accept the following STATUS values:

  • ok, fail, partial, needs_decision, no_changes, decomposed, rejected, retry, fixture_gap

Parsers MUST accept the following TESTS and BUILD values:

  • pass, fail, skip (with optional :N count for TESTS)

Implementations SHOULD test their parser against a system-prompt example block to ensure round-trip compatibility — what the prompt teaches the agent to emit, the parser must accept.

Why this matters

The CACP standard's whole value proposition is interop. Multiple agents and dispatchers should agree on the wire format. Without ratifying tolerance rules, every implementer makes their own choice and the standard fragments. The cascade described above was a direct consequence of that fragmentation — the system prompt taught one form, the parser enforced another, the standard didn't say which was right.

Test contract

A reference test vector for parser implementations:

STATUS:ok
status: ok
Status:  ok
STATUS:	ok

All four lines MUST parse to the same (field='STATUS', value='ok') tuple. Any conformant parser passing this vector is interop-safe with any conformant emitter.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions