Implement LiveMaterializationStrategy as the third materialization
strategy type (alongside sequential_buffer and accumulate) per spec
§26456-26492. The live strategy renders element updates in-place at
~15 fps by tracking a dirty-element set and coalescing updates into
frame redraws.
RichMaterializer now extends LiveMaterializationStrategy instead of
_BaseBufferStrategy, enabling supports_incremental_updates=True.
Element rendering still delegates to the colour renderer for visual
formatting, maintaining backward compatibility.
Changes:
- Add _LiveMaterializationStrategy class with frame-rate throttling,
dirty-element tracking, and per-frame composition in declaration
order
- Update RichMaterializer to extend _LiveMaterializationStrategy
- Export LiveMaterializationStrategy from materializers.py and
__init__.py
- Update SD-2 and SD-7 documentation in __init__.py
- Add vulture whitelist entry for LiveMaterializationStrategy
- Add 5 Behave scenarios covering live strategy rendering, incremental
update support, dirty-element coalescing, all-element-type rendering,
and frame rate validation
- Add step definitions for the new scenarios
ISSUES CLOSED: #903
Align the structured output envelope (JSON/YAML modes) with the specification:
add `status` field, rename `elements` to `data`, rename `metadata` to
`messages`, and fix the fallback chain to include the table step
(rich→table→color→plain).
ISSUES CLOSED: #884
The format_output() function returned a string that callers passed to
Rich console.print(), which wraps long lines at terminal width. This
injected literal newline characters into JSON string values (e.g. in
definition_of_done fields), producing invalid JSON that downstream
parsers could not decode (JSONDecodeError: Invalid control character).
For machine-readable formats (json, yaml, plain), format_output() now
writes the rendered output directly to sys.stdout and returns an empty
string. This preserves the exact serialization from json.dumps/
yaml.dump without Rich text processing artifacts.
Refs: #746