Skip to content

Releases: brainfile/py

v0.4.0

02 Mar 19:29

Choose a tag to compare

Board config file I/O + agent identity

New features

  • identity field on AgentInstructions — system prompt identity for agents
  • parse_board_config(content) — parse brainfile.md content into (BoardConfig, body) tuple
  • serialize_board_config(config, body) — serialize board config to YAML frontmatter + markdown
  • write_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

02 Mar 16:35

Choose a tag to compare

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

02 Mar 16:23

Choose a tag to compare

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

  • _extras on _ModelMixin — unknown keys survive model_validate()model_dump()model_copy()
  • x- prefix pass-through — extension keys bypass snake_to_camel/camel_to_snake conversion
  • Opaque extension values — internal keys within extension objects are never transformed
  • Full YAML round-tripparse_task_content()serialize_task_content() preserves extension fields
  • 6 new tests covering extension field behavior

v0.3.0

02 Mar 16:05

Choose a tag to compare

Breaking Changes

  • Pydantic and ruamel.yaml are no longer required dependencies. The only hard dependency is now PyYAML>=6.0. Install brainfile[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.pysnake_to_camel / camel_to_snake dict key transform helpers for JSONL interop
  • _ModelMixin — compatibility shim providing Pydantic-like API on stdlib dataclasses

Changed

  • models.py — All models are now @dataclass with _ModelMixin
  • types_ledger.py — Ledger types are now @dataclass
  • _yaml.py — Thin PyYAML wrapper replacing ruamel.yaml
  • pyproject.tomldependencies = ["PyYAML>=6.0"], Pydantic moved to [pydantic] extra

Preserved

  • JSONL output is byte-identical to @brainfile/core TypeScript output
  • All public API signatures remain backward compatible
  • 185/185 tests pass

v0.2.1

02 Mar 05:20

Choose a tag to compare

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 records
  • read_ledger() / query_ledger() — read and filter by assignee, tags, date range, contract status, files
  • get_file_history() — query completions by file path intersection
  • get_task_context() — scoped recent history for a task's related files and deliverables
  • complete_task_file() now writes to logs/ledger.jsonl by default (pass legacy_mode=True for old behavior)
  • Backward compatible: falls back to reading .md log files if no ledger.jsonl exists
  • JSONL output is byte-compatible with @brainfile/core TypeScript output

Improvements

  • Shared _time.py utility for UTC timestamp generation
  • Generic _normalize_model() helper replaces 4 copy-paste functions
  • normalize_path_value() fix: whitespace stripped before ./ prefix check
  • LEDGER_CONTRACT_STATUSES derived from LedgerContractStatus Literal via get_args()

v0.2.0

01 Mar 02:39

Choose a tag to compare

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: noqa suppressions remaining
  • README and examples rewritten for the v2 API

See the commit for full details.

v0.1.1

01 Mar 00:00

Choose a tag to compare

fix: Rename TypeEntry.schema to schema_url to avoid pydantic UserWarning on every import

v0.1.0

28 Feb 22:49

Choose a tag to compare

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