Releases: brainfile/py
v0.4.0
Board config file I/O + agent identity
New features
identityfield onAgentInstructions— system prompt identity for agentsparse_board_config(content)— parse brainfile.md content into(BoardConfig, body)tupleserialize_board_config(config, body)— serialize board config to YAML frontmatter + markdownwrite_board_config(path, config, body)— write board config to disk
Why
External agents (Otto, Cursor, etc.) need to programmatically read and update the agent section in brainfile.md without rolling their own YAML frontmatter parser. This matches the existing task file I/O pattern (parse_task_content, serialize_task_content, etc.).
Extension fields (x-otto, x-cursor) round-trip through all config operations via _extras.
v0.3.2
Fix: nested model extras preservation
Bug: _serialize_value() called _dataclass_to_dict() on nested dataclasses, bypassing model_dump() and silently dropping _extras. This meant extension fields on nested models (e.g. Contract.outOfScope, Contract.feedback) were lost when serialized from a parent Task.
Fix: _serialize_value() now checks for model_dump() first, so nested model extras survive parent serialization.
Impact
| Field Location | 0.3.1 | 0.3.2 |
|---|---|---|
Task top-level extras (x-otto, blockedBy) |
Preserved | Preserved |
Nested Contract extras (outOfScope, feedback) |
Dropped | Preserved |
Reported by Otto agent during brainfile adoption inspection.
v0.3.1
Extension field preservation
Unknown keys passed to model_validate() are now preserved in _extras and merged back during model_dump(). This enables consumers to round-trip custom fields (e.g. x-otto, x-cursor) through brainfile without data loss.
What's new
_extrason_ModelMixin— unknown keys survivemodel_validate()→model_dump()→model_copy()x-prefix pass-through — extension keys bypasssnake_to_camel/camel_to_snakeconversion- Opaque extension values — internal keys within extension objects are never transformed
- Full YAML round-trip —
parse_task_content()→serialize_task_content()preserves extension fields - 6 new tests covering extension field behavior
v0.3.0
Breaking Changes
- Pydantic and ruamel.yaml are no longer required dependencies. The only hard dependency is now
PyYAML>=6.0. Installbrainfile[pydantic]if you need Pydantic model support.
What Changed
All Pydantic BaseModel classes replaced with plain @dataclass classes using a lightweight _ModelMixin that preserves the model_validate() / model_dump() / model_copy() API. All ruamel.yaml usage replaced with PyYAML (yaml.safe_load / yaml.dump).
New
_keys.py—snake_to_camel/camel_to_snakedict key transform helpers for JSONL interop_ModelMixin— compatibility shim providing Pydantic-like API on stdlib dataclasses
Changed
models.py— All models are now@dataclasswith_ModelMixintypes_ledger.py— Ledger types are now@dataclass_yaml.py— Thin PyYAML wrapper replacing ruamel.yamlpyproject.toml—dependencies = ["PyYAML>=6.0"], Pydantic moved to[pydantic]extra
Preserved
- JSONL output is byte-identical to
@brainfile/coreTypeScript output - All public API signatures remain backward compatible
- 185/185 tests pass
v0.2.1
What's New
Ledger Module
Append-only JSONL completion history, ported from the TypeScript core.
build_ledger_record()/append_ledger_record()— build and persist structured completion recordsread_ledger()/query_ledger()— read and filter by assignee, tags, date range, contract status, filesget_file_history()— query completions by file path intersectionget_task_context()— scoped recent history for a task's related files and deliverablescomplete_task_file()now writes tologs/ledger.jsonlby default (passlegacy_mode=Truefor old behavior)- Backward compatible: falls back to reading
.mdlog files if noledger.jsonlexists - JSONL output is byte-compatible with
@brainfile/coreTypeScript output
Improvements
- Shared
_time.pyutility for UTC timestamp generation - Generic
_normalize_model()helper replaces 4 copy-paste functions normalize_path_value()fix: whitespace stripped before./prefix checkLEDGER_CONTRACT_STATUSESderived fromLedgerContractStatusLiteral viaget_args()
v0.2.0
Breaking Changes
All public API identifiers renamed from camelCase to snake_case. This is a breaking change for all consumers.
Highlights
- snake_case everywhere: ~90 functions, parameters, TypedDict fields, dataclass fields, and dict keys renamed
- Trimmed package: v1 modules removed, formatters/schema_hints removed from top-level exports
- watchdog optional: moved to
pip install brainfile[watch]extra - Zero
ruff: noqasuppressions remaining - README and examples rewritten for the v2 API
See the commit for full details.
v0.1.1
fix: Rename TypeEntry.schema to schema_url to avoid pydantic UserWarning on every import
v0.1.0
Initial release of the Python engine for Brainfile — file-based task coordination for AI agents.
- Full v2 protocol support (directory-based, one task per file)
- Pydantic v2 models for all types (Board, Task, Contract, etc.)
- Contract system for multi-agent coordination
- Board operations (add, move, patch, complete, archive)
- Task file I/O with YAML frontmatter + markdown body
- Validation and linting
- File discovery and workspace detection