claw-code/tests
YeonGyu-Kim f012cadd64 test: cycle #27 — cross-channel consistency audit suite
Cycle #27 ships a new test class systematizing the three-layer protocol
invariant framework.

## Context

After cycles #20–#26, the protocol has three distinct invariant classes:

1. **Structural compliance** (#178): Does the envelope exist?
2. **Quality compliance** (#179): Is stderr silent + error message truthful?
3. **Cross-channel consistency** (#181 + NEW): Do multiple channels agree?

#181 revealed a critical gap: the second test class was incomplete.
Envelopes could be structurally valid, quality-compliant, but still
lie about their own state (envelope.exit_code != actual exit).

## New Test Class

TestCrossChannelConsistency in test_cross_channel_consistency.py captures
the third invariant layer with 5 dedicated tests:

1. envelope.command ↔ dispatched subcommand
2. envelope.output_format ↔ --output-format flag
3. envelope.timestamp ↔ actual wall clock (recent, <5s)
4. envelope.exit_code ↔ process exit code (cycle #26/#181 regression guard)
5. envelope boolean fields (found/handled/deleted) ↔ error block presence

Each test specifically targets cross-channel truth, not structure or quality.

## Why Separate Test Classes Matter

A command can fail all three ways independently:

| Failure mode | Exit/Crash | Test class | Example |
|---|---|---|---|
| Structural | stderr noise | TestParseErrorEnvelope | argparse leaks to stderr |
| Quality | correct shape, wrong message | TestParseErrorStderrHygiene | error instead of real message |
| Cross-channel | truthy field, lie about state | TestCrossChannelConsistency | exit_code: 0 but exit 1 |

#181 was invisible to the first two classes. A claw passing all structure/
quality tests could still be misled. The third class catches that.

## Audit Results (Cycle #27)

All 5 tests pass — no drift detected in any channel pair:

-  Envelope command always matches dispatch
-  Envelope output_format always matches flag
-  Envelope timestamp always recent (<5s)
-  Envelope exit_code always matches process exit (post-#181 guard)
-  Boolean fields consistent with error block presence

The systematic audit proved the fix from #181 holds, and identified
no new cross-channel gaps.

## Test Impact

- 209 → 214 tests passing (+5)
- Zero regressions
- New invariant class now has dedicated test suite
- Future cross-channel bugs will be caught by this class

## Related

- #178 (#20): Parser-front-door structural contract
- #179 (#20): Stderr hygiene + real error message quality
- #181 (#26): Envelope exit_code must match process exit
- #182-N: Future cross-channel contract violations will be caught
  by TestCrossChannelConsistency

This test class is evergreen — as new fields/channels are added to the
protocol, invariants for those channels should be added here, not mixed
with other test classes. Keeping invariant classes separate makes
regression attribution instant (e.g., 'TestCrossChannelConsistency failed'
= 'some truth channel disagreed').

Classification (per cycle #24 calibration):
- Red-state bug: ✗ (audit is green)
- Real friction: ✓ (structured audit of documented invariants)
- Proof of equilibrium: ✓ (systematic verification, no gaps found)

Source: Jobdori cycle #27 proactive invariant audit — following gaebal
guidance to probe documented invariants, not speculative gaps.
2026-04-30 11:03:06 +09:00
..
test_cancel_observed_field.py feat: #164 Stage B CLOSURE — turn-loop JSON + cancel_observed coverage + CLAWABLE promotion 2026-04-30 11:03:06 +09:00
test_cli_parity_audit.py feat: #164 Stage B CLOSURE — turn-loop JSON + cancel_observed coverage + CLAWABLE promotion 2026-04-30 11:03:06 +09:00
test_command_graph_tool_pool_output_format.py fix: #169 — command-graph and tool-pool now accept --output-format; diagnostic inventory JSON parity 2026-04-30 11:03:06 +09:00
test_cross_channel_consistency.py test: cycle #27 — cross-channel consistency audit suite 2026-04-30 11:03:06 +09:00
test_exec_route_bootstrap_output_format.py fix: #181 — envelope exit_code must match process exit code (exec-command/exec-tool) 2026-04-30 11:03:06 +09:00
test_flush_transcript_cli.py fix: #166 — flush-transcript now accepts --directory / --output-format / --session-id; session-creation command parity with #160/#165 lifecycle triplet 2026-04-30 11:03:06 +09:00
test_json_envelope_field_consistency.py feat: #173 — wrap_json_envelope() applied to all 13 clawable commands (LOOP CLOSED) 2026-04-30 11:03:06 +09:00
test_load_session_cli.py feat: #173 — wrap_json_envelope() applied to all 13 clawable commands (LOOP CLOSED) 2026-04-30 11:03:06 +09:00
test_parse_error_envelope.py fix: #179 — JSON mode now fully suppresses argparse stderr + preserves real error message 2026-04-30 11:03:06 +09:00
test_porting_workspace.py feat: #173 — wrap_json_envelope() applied to all 13 clawable commands (LOOP CLOSED) 2026-04-30 11:03:06 +09:00
test_run_turn_loop_cancellation.py fix: #164 Stage A — cooperative cancellation via cancel_event in submit_message 2026-04-30 11:03:06 +09:00
test_run_turn_loop_continuation.py fix: #163 — remove [turn N] suffix pollution from run_turn_loop; file #164 timeout-cancellation followup 2026-04-30 11:03:06 +09:00
test_run_turn_loop_permissions.py fix: #159 — run_turn_loop no longer hardcodes empty denied_tools; permission denials now parity-match bootstrap_session 2026-04-30 11:03:06 +09:00
test_run_turn_loop_timeout.py fix: #164 Stage A — cooperative cancellation via cancel_event in submit_message 2026-04-30 11:03:06 +09:00
test_session_store.py fix(#160): harden delete_session contract — idempotency, race-safety, typed partial-failure 2026-04-30 11:03:06 +09:00
test_show_command_tool_output_format.py fix: #167 — show-command and show-tool now accept --output-format flag; CLI parity with session-lifecycle family 2026-04-30 11:03:06 +09:00
test_submit_message_budget.py fix: #162 — budget-overflow no longer corrupts session state in submit_message 2026-04-30 11:03:06 +09:00
test_submit_message_cancellation.py fix: #164 Stage A — cooperative cancellation via cancel_event in submit_message 2026-04-30 11:03:06 +09:00