Skip to content

feat: make TokenUsage.total_tokens a computed field#118

Merged
Aureliolo merged 3 commits intomainfrom
feat/computed-total-tokens
Mar 6, 2026
Merged

feat: make TokenUsage.total_tokens a computed field#118
Aureliolo merged 3 commits intomainfrom
feat/computed-total-tokens

Conversation

@Aureliolo
Copy link
Copy Markdown
Owner

@Aureliolo Aureliolo commented Mar 6, 2026

Summary

  • Migrate TokenUsage.total_tokens from a stored Field + @model_validator to a @computed_field property — eliminates redundant storage and impossible-to-fail validator
  • Remove total_tokens= kwarg from all constructor call sites (compute_cost, add_token_usage, ZERO_TOKEN_USAGE, all test fixtures/factories)
  • Simplify add_token_usage by inlining expressions (no intermediate variables needed)
  • Update DESIGN_SPEC.md §10.2 and §15.5 to reflect the migration (Planned → Adopted)
  • Update CLAUDE.md to mark @computed_field as an adopted convention

Review coverage

Pre-reviewed by 9 agents (code-reviewer, python-reviewer, pr-test-analyzer, silent-failure-hunter, comment-analyzer, type-design-analyzer, logging-audit, resilience-audit, docs-consistency). 5 findings addressed:

  1. CLAUDE.md: mark @computed_field as Adopted (was stale "Planned")
  2. Add serialization roundtrip + computed-always-wins tests
  3. Add explanatory comment for type: ignore[prop-decorator]
  4. Rename test_maintains_total_invarianttest_total_tokens_is_sum_of_parts
  5. Clarify add_token_usage docstring re: computed total_tokens

Test plan

  • uv run ruff check src/ tests/ — all checks passed
  • uv run mypy src/ tests/ — no issues in 199 source files
  • uv run pytest tests/ -n auto --cov=ai_company --cov-fail-under=80 — 1788 passed, 95.35% coverage
  • New tests: test_total_tokens_is_always_computed, test_total_tokens_in_serialization, test_total_tokens_roundtrip
  • Pre-commit hooks pass (ruff, format, gitleaks, commitizen)

Closes #109

Aureliolo and others added 2 commits March 6, 2026 08:52
Convert `total_tokens` from a stored `Field` with `@model_validator` to
a `@computed_field` property. This eliminates redundant storage and the
impossible-to-fail validator, and removes `total_tokens=...` from all
22 call sites.

Closes #109

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pre-reviewed by 9 agents, 5 findings addressed:
- CLAUDE.md: mark @computed_field as Adopted (was stale Planned)
- Add serialization roundtrip + computed-always-wins tests
- Add explanatory comment for type: ignore[prop-decorator]
- Rename test_maintains_total_invariant → test_total_tokens_is_sum_of_parts
- Clarify add_token_usage docstring re: computed total_tokens

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings March 6, 2026 08:03
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 6, 2026

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 6, 2026

Caution

Review failed

Pull request was closed or merged during review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 237dd9f7-5973-4e95-8200-acd9cc5863a6

📥 Commits

Reviewing files that changed from the base of the PR and between 5de4fce and 2faff4d.

📒 Files selected for processing (3)
  • DESIGN_SPEC.md
  • src/ai_company/providers/models.py
  • tests/unit/providers/test_models.py
📜 Recent review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Greptile Review
🧰 Additional context used
📓 Path-based instructions (3)
DESIGN_SPEC.md

📄 CodeRabbit inference engine (CLAUDE.md)

Update DESIGN_SPEC.md to reflect approved deviations from the original design

Files:

  • DESIGN_SPEC.md
tests/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

tests/**/*.py: Mark test functions with @pytest.mark.unit, @pytest.mark.integration, @pytest.mark.e2e, or @pytest.mark.slow
Maintain minimum 80% code coverage (enforced in CI)
Use asyncio_mode = 'auto' in pytest configuration — no manual @pytest.mark.asyncio needed on async tests
Set 30-second timeout per test
Use fake/test model IDs and provider names in tests (e.g. test-haiku-001, test-provider), never real vendor model IDs — tests must not be coupled to external providers

Files:

  • tests/unit/providers/test_models.py
src/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

src/**/*.py: Always read DESIGN_SPEC.md before implementing any feature or planning any issue — it is the starting point for architecture, data models, and behavior
If implementation deviates from DESIGN_SPEC.md, alert the user and explain why — user decides whether to proceed or update the spec. Do NOT silently diverge.
When a spec section is referenced (e.g. 'Section 10.2'), read that section verbatim before coding
Every implementation plan must be presented to the user for accept/deny before coding starts
At every phase of planning and implementation, be critical and actively look for ways to improve the design in the spirit of what we're building (robustness, correctness, simplicity, future-proofing where it's free). Surface improvements as suggestions, not silent changes.
Do NOT use from __future__ import annotations — Python 3.14 has PEP 649 native lazy annotations
Use except A, B: syntax without parentheses for multiple exception handling (PEP 758) — ruff enforces this on Python 3.14
All public functions must have type hints and pass mypy strict mode
All public classes and functions must have Google-style docstrings, enforced by ruff D rules
Never mutate existing objects — create new objects instead. For non-Pydantic internal collections (registries, BaseTool), use copy.deepcopy() at construction + MappingProxyType wrapping for read-only enforcement.
For dict/list fields in frozen Pydantic models, rely on frozen=True for field reassignment prevention and use copy.deepcopy() at system boundaries (tool execution, LLM provider serialization, inter-agent delegation, serializing for persistence)
Use frozen Pydantic models for config/identity; use separate mutable-via-copy models (using model_copy(update=...)) for runtime state that evolves (e.g. agent execution state, task progress). Never mix static config fields with mutable runtime fields in one model.
Use Pydantic v2 with BaseModel, model_validator, and ConfigDict
Use `@computed...

Files:

  • src/ai_company/providers/models.py
🧠 Learnings (10)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-06T07:08:12.974Z
Learning: Applies to src/**/*.py : Use `computed_field` for derived values instead of storing + validating redundant fields in Pydantic models
📚 Learning: 2026-03-06T07:08:12.974Z
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-06T07:08:12.974Z
Learning: Applies to DESIGN_SPEC.md : Update `DESIGN_SPEC.md` to reflect approved deviations from the original design

Applied to files:

  • DESIGN_SPEC.md
📚 Learning: 2026-03-06T07:08:12.974Z
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-06T07:08:12.974Z
Learning: Applies to src/**/*.py : All provider calls must go through `BaseCompletionProvider` which applies retry + rate limiting automatically

Applied to files:

  • DESIGN_SPEC.md
📚 Learning: 2026-03-06T07:08:12.974Z
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-06T07:08:12.974Z
Learning: Applies to src/**/*.py : Use frozen Pydantic models for config/identity; use separate mutable-via-copy models (using `model_copy(update=...)`) for runtime state that evolves (e.g. agent execution state, task progress). Never mix static config fields with mutable runtime fields in one model.

Applied to files:

  • DESIGN_SPEC.md
📚 Learning: 2026-03-06T07:08:12.974Z
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-06T07:08:12.974Z
Learning: Applies to src/**/*.py : For `dict`/`list` fields in frozen Pydantic models, rely on `frozen=True` for field reassignment prevention and use `copy.deepcopy()` at system boundaries (tool execution, LLM provider serialization, inter-agent delegation, serializing for persistence)

Applied to files:

  • DESIGN_SPEC.md
📚 Learning: 2026-03-06T07:08:12.974Z
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-06T07:08:12.974Z
Learning: Applies to src/**/*.py : Never mutate existing objects — create new objects instead. For non-Pydantic internal collections (registries, `BaseTool`), use `copy.deepcopy()` at construction + `MappingProxyType` wrapping for read-only enforcement.

Applied to files:

  • DESIGN_SPEC.md
📚 Learning: 2026-01-26T08:59:32.818Z
Learnt from: CR
Repo: Aureliolo/story-factory PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-01-26T08:59:32.818Z
Learning: Applies to **/*.py : Use type hints where appropriate. Use Pydantic models for data validation in `src/memory/story_state.py`, dataclasses in `src/settings.py`.

Applied to files:

  • DESIGN_SPEC.md
📚 Learning: 2026-03-06T07:08:12.974Z
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-06T07:08:12.974Z
Learning: Applies to src/**/*.py : Use `computed_field` for derived values instead of storing + validating redundant fields in Pydantic models

Applied to files:

  • DESIGN_SPEC.md
  • src/ai_company/providers/models.py
📚 Learning: 2026-03-06T07:08:12.974Z
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-06T07:08:12.974Z
Learning: Applies to src/**/*.py : At every phase of planning and implementation, be critical and actively look for ways to improve the design in the spirit of what we're building (robustness, correctness, simplicity, future-proofing where it's free). Surface improvements as suggestions, not silent changes.

Applied to files:

  • DESIGN_SPEC.md
📚 Learning: 2026-03-06T07:08:12.974Z
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-06T07:08:12.974Z
Learning: Applies to src/**/*.py : Use Pydantic v2 with `BaseModel`, `model_validator`, and `ConfigDict`

Applied to files:

  • src/ai_company/providers/models.py
🪛 LanguageTool
DESIGN_SPEC.md

[style] ~860-~860: This word has been used in one of the immediately preceding sentences. Using a synonym could make your text more interesting to read, unless the repetition is intentional.
Context: ..._tokens — no stored field or validator needed. Spending summary models (AgentSpendin...

(EN_REPEATEDWORDS_NEED)

🔇 Additional comments (5)
tests/unit/providers/test_models.py (1)

73-111: LGTM! Well-structured tests for the computed field behavior.

The new tests comprehensively cover:

  • Automatic computation of total_tokens
  • Presence in serialized output via model_dump()
  • Round-trip behavior for both dict and JSON serialization (stale values correctly ignored)
  • Immutability via property rejection of direct assignment

The previous review concern about using hand-written dicts in test_total_tokens_roundtrip has been addressed — the test now correctly uses model_dump() to create the payload before mutating total_tokens.

src/ai_company/providers/models.py (2)

31-35: LGTM! Clean implementation of the computed field.

The @computed_field decorator with description parameter is correctly used, and the # type: ignore[prop-decorator] comment appropriately handles the mypy limitation with stacked decorators on properties. This aligns with the coding guideline to "use computed_field for derived values instead of storing + validating redundant fields."


46-61: LGTM! Function correctly updated to rely on computed property.

The implementation and docstring are properly updated. The function no longer manually computes or passes total_tokens, correctly delegating to the @computed_field property.

DESIGN_SPEC.md (2)

860-860: LGTM! Implementation note accurately documents the change.

The note clearly explains that total_tokens is now a @computed_field property and appropriately references the planned _SpendingTotals base extraction for spending summary models in §15.5.


1441-1441: LGTM! Convention status correctly updated to "Adopted".

The status change from "Planned" to "Adopted" with the specific reference to TokenUsage.total_tokens migration accurately reflects the implementation in this PR.


📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • TokenUsage.total_tokens is now automatically calculated from input and output tokens, eliminating manual specification requirements.
  • Documentation

    • Updated code conventions documentation to reflect the computed token calculation approach.
  • Refactor

    • Renamed CompletionRequest/Response to CompletionConfig/Response in provider models for improved naming clarity.

Walkthrough

This PR replaces the stored total_tokens field on TokenUsage with a Pydantic @computed_field property (sum of input_tokens and output_tokens), and updates models, provider code, docs, and tests to stop constructing or validating a stored total_tokens.

Changes

Cohort / File(s) Summary
Documentation
CLAUDE.md, DESIGN_SPEC.md
Added computed_field to Pydantic v2 exports and updated conventions/design notes to state TokenUsage.total_tokens is implemented with @computed_field (removed stored-field + validator references).
Model Definition
src/ai_company/providers/models.py
Removed stored total_tokens field and _validate_total validator; added @computed_field property total_tokens; updated ZERO_TOKEN_USAGE, add_token_usage, imports, and docstrings to rely on computed property.
Provider Logic
src/ai_company/providers/base.py
Stopped including total_tokens when constructing TokenUsage in BaseCompletionProvider.compute_cost (now supplies input_tokens, output_tokens, cost_usd only).
Unit Tests — Fixtures
tests/unit/providers/conftest.py, tests/unit/engine/conftest.py
Removed total_tokens from TokenUsage test factories and sample fixtures.
Unit Tests — Behavioral
tests/unit/engine/test_context.py, tests/unit/engine/test_task_execution.py, tests/unit/providers/test_base_provider.py
Updated tests to stop providing total_tokens; adjusted/renamed assertions to treat total_tokens as derived (sum of input+output).
Unit Tests — Model Tests
tests/unit/providers/test_models.py
Removed tests expecting explicit total_tokens input and validation; added tests verifying total_tokens is computed, appears in serialized output, is recomputed on load, and cannot be directly assigned.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 26.67% which is insufficient. The required threshold is 100.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: converting TokenUsage.total_tokens from a stored field to a computed field.
Description check ✅ Passed The description thoroughly explains the change and includes test coverage, review findings, and addresses the objective of issue #109.
Linked Issues check ✅ Passed All acceptance criteria from issue #109 are met: total_tokens is a computed_field property, validator removed, all call sites updated, serialization preserves total_tokens, and tests pass.
Out of Scope Changes check ✅ Passed All changes are directly related to migrating total_tokens to a computed field and updating documentation accordingly. The CompletionRequest → CompletionConfig reference update mentioned in commit messages aligns with DESIGN_SPEC.md consistency goals.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/computed-total-tokens

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request refactors the TokenUsage.total_tokens field to leverage Pydantic's @computed_field decorator. This change streamlines the TokenUsage model by automatically deriving total_tokens from input_tokens and output_tokens, thereby eliminating redundant data storage and simplifying model initialization. The update enhances data consistency, reduces boilerplate code, and aligns the codebase with adopted Pydantic conventions for handling derived values, improving overall maintainability and robustness.

Highlights

  • Migration to Pydantic @computed_field: The TokenUsage.total_tokens field was migrated from a stored Pydantic Field with a @model_validator to a @computed_field property. This change eliminates redundant storage and simplifies validation logic.
  • Codebase Simplification: The total_tokens keyword argument was removed from all TokenUsage constructor calls across the codebase, including compute_cost, add_token_usage, ZERO_TOKEN_USAGE, and various test fixtures/factories. The add_token_usage utility function was also simplified by inlining token summation expressions.
  • Documentation Updates: Documentation in DESIGN_SPEC.md (sections 10.2 and 15.5) and CLAUDE.md was updated to reflect the adoption of @computed_field as a standard convention for derived values.
  • Enhanced Test Coverage: New tests were added to specifically verify the correct behavior of total_tokens as a computed field, including its handling during serialization and deserialization roundtrips. Existing tests were adjusted to remove total_tokens from TokenUsage instantiations and one test was renamed for clarity.
Changelog
  • CLAUDE.md
    • Updated the 'Models' section to mark @computed_field as an adopted convention for derived values.
  • DESIGN_SPEC.md
    • Updated Section 10.2 to reflect total_tokens as a @computed_field property, removing the mention of it being a stored Field with a model_validator.
    • Updated Section 15.5 to change the status of 'Derived fields' from 'Planned' to 'Adopted' and noted the migration of TokenUsage.total_tokens.
  • src/ai_company/providers/base.py
    • Removed the total_tokens argument from the TokenUsage constructor within the compute_cost function.
  • src/ai_company/providers/models.py
    • Imported computed_field from pydantic.
    • Removed total_tokens as a direct Field attribute from the TokenUsage model.
    • Replaced the _validate_total model_validator with a @computed_field property named total_tokens that calculates the sum of input_tokens and output_tokens.
    • Removed the total_tokens argument from the ZERO_TOKEN_USAGE instantiation.
    • Simplified the add_token_usage function by directly passing summed input_tokens and output_tokens to the TokenUsage constructor and updating its docstring.
  • tests/unit/engine/conftest.py
    • Removed total_tokens from the TokenUsage instantiation in sample_token_usage.
  • tests/unit/engine/test_context.py
    • Removed total_tokens from TokenUsage instantiations in various test cases.
  • tests/unit/engine/test_task_execution.py
    • Removed total_tokens from TokenUsage instantiations in test_sums_correctly, test_total_tokens_is_sum_of_parts, and test_with_zero_usage.
    • Renamed test_maintains_total_invariant to test_total_tokens_is_sum_of_parts.
  • tests/unit/providers/conftest.py
    • Removed total_tokens from TokenUsageFactory and sample_token_usage definitions.
  • tests/unit/providers/test_base_provider.py
    • Removed total_tokens from the TokenUsage instantiation within _do_complete.
  • tests/unit/providers/test_models.py
    • Removed the test_total_must_equal_sum test case, as the total_tokens field is no longer directly validated.
    • Removed total_tokens from TokenUsage instantiations in test_negative_input_rejected and test_negative_cost_rejected.
    • Added new tests: test_total_tokens_is_always_computed, test_total_tokens_in_serialization, and test_total_tokens_roundtrip to verify the behavior of the computed field.
Activity
  • The pull request underwent pre-review by 9 agents (code-reviewer, python-reviewer, pr-test-analyzer, silent-failure-hunter, comment-analyzer, type-design-analyzer, logging-audit, resilience-audit, docs-consistency).
  • Five findings were addressed during the review process, including updating CLAUDE.md to mark @computed_field as Adopted, adding serialization roundtrip tests, including an explanatory comment for type: ignore[prop-decorator], renaming test_maintains_total_invariant to test_total_tokens_is_sum_of_parts, and clarifying the add_token_usage docstring.
  • All automated checks passed, including uv run ruff check src/ tests/, uv run mypy src/ tests/ (no issues in 199 source files), and uv run pytest tests/ -n auto --cov=ai_company --cov-fail-under=80 (1788 passed, 95.35% coverage).
  • New tests test_total_tokens_is_always_computed, test_total_tokens_in_serialization, and test_total_tokens_roundtrip were introduced to cover the changes.
  • Pre-commit hooks (ruff, format, gitleaks, commitizen) passed successfully.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Mar 6, 2026

Greptile Summary

This PR completes the migration of TokenUsage.total_tokens from a redundant stored Field combined with an impossible-to-fail @model_validator to a Pydantic v2 @computed_field property, marking the "Derived fields" design convention as Adopted. All ten changed files are internally consistent, static analysis passes cleanly, and the new test suite provides explicit roundtrip and serialization coverage.

Key changes:

  • models.py: total_tokens is now a @computed_field property; _validate_total validator removed; ZERO_TOKEN_USAGE and add_token_usage updated accordingly.
  • base.py: Removes the now-unnecessary total_tokens kwarg from compute_cost.
  • All test fixtures, factories, and inline TokenUsage constructors across tests/unit/ have been cleaned up.
  • CLAUDE.md and DESIGN_SPEC.md updated to accurately reflect the adopted convention, including a minor documentation correction (CompletionRequestCompletionConfig in the file-tree comment).
  • tests/integration/providers/conftest.py retains total_tokens intentionally — it belongs to litellm.types.utils.Usage, a third-party type, not ai_company.providers.models.TokenUsage.

Confidence Score: 5/5

  • This PR is safe to merge — it is a clean, well-tested structural refactor with no changes to token counting logic.
  • The change is purely structural: the arithmetic that was previously validated in a @model_validator is now the computed property body itself. Serialization behaviour is preserved (model_dump() still emits total_tokens). Deserialization from old payloads containing a stored total_tokens key is explicitly tested and handled correctly via Pydantic v2 default semantics for computed fields. All call sites in the repo have been updated, lint, type-check, and tests all pass at high coverage.
  • No files require special attention.

Last reviewed commit: 2faff4d

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR migrates TokenUsage.total_tokens from a stored/validated Pydantic field to a @computed_field, removing redundant state and simplifying construction/aggregation across the provider and engine layers.

Changes:

  • Convert TokenUsage.total_tokens to a @computed_field and drop the (now unnecessary) validator and stored field.
  • Remove total_tokens= from all TokenUsage(...) call sites and fixtures; simplify add_token_usage.
  • Update unit tests and documentation (DESIGN_SPEC.md, CLAUDE.md) to reflect the adopted derived-field convention.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/ai_company/providers/models.py Implements total_tokens as a computed field; updates ZERO_TOKEN_USAGE and add_token_usage.
src/ai_company/providers/base.py Removes redundant total_tokens construction in compute_cost.
tests/unit/providers/test_models.py Replaces invariant-validator test with computed-field, serialization, and roundtrip tests.
tests/unit/providers/test_base_provider.py Updates provider test helper to construct TokenUsage without total_tokens.
tests/unit/providers/conftest.py Updates TokenUsageFactory and sample_token_usage fixture to omit total_tokens.
tests/unit/engine/test_task_execution.py Updates engine aggregation tests and renames invariant test to reflect computed behavior.
tests/unit/engine/test_context.py Updates context tests to construct TokenUsage without total_tokens.
tests/unit/engine/conftest.py Updates engine fixture to omit total_tokens.
DESIGN_SPEC.md Updates design notes/conventions to mark computed derived fields as adopted.
CLAUDE.md Updates modeling conventions to include computed_field as adopted practice.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors TokenUsage.total_tokens to be a @computed_field, improving data integrity and code simplicity by ensuring the total token count is always consistent with the sum of input and output tokens, eliminating the need for manual validation and reducing redundant storage. No security vulnerabilities were identified during the audit. The changes are applied consistently, and the new tests are thorough. I suggest implementing the __add__ operator in the TokenUsage model for more idiomatic summation, which would allow for removing the add_token_usage helper function.

Comment on lines 46 to 61
def add_token_usage(a: TokenUsage, b: TokenUsage) -> TokenUsage:
"""Create a new ``TokenUsage`` with summed token counts and cost.

Computes ``total_tokens`` from the summed parts to maintain the
``total_tokens == input_tokens + output_tokens`` invariant.

Args:
a: First usage record.
b: Second usage record.

Returns:
New ``TokenUsage`` with summed token counts and cost.
New ``TokenUsage`` with summed token counts and cost
(``total_tokens`` is computed automatically).
"""
input_tokens = a.input_tokens + b.input_tokens
output_tokens = a.output_tokens + b.output_tokens
return TokenUsage(
input_tokens=input_tokens,
output_tokens=output_tokens,
total_tokens=input_tokens + output_tokens,
input_tokens=a.input_tokens + b.input_tokens,
output_tokens=a.output_tokens + b.output_tokens,
cost_usd=a.cost_usd + b.cost_usd,
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

While this function works correctly, consider implementing operator overloading by adding an __add__ method to the TokenUsage class. This would allow for more idiomatic and readable code, like usage_a + usage_b, instead of add_token_usage(usage_a, usage_b). This would make TokenUsage behave more like a numeric type where addition is a natural operation.

Example implementation inside TokenUsage class:

from typing import Self

# ...

    def __add__(self, other: Self) -> Self:
        if not isinstance(other, TokenUsage):
            return NotImplemented
        return TokenUsage(
            input_tokens=self.input_tokens + other.input_tokens,
            output_tokens=self.output_tokens + other.output_tokens,
            cost_usd=self.cost_usd + other.cost_usd,
        )

With this change, this add_token_usage function would no longer be necessary and could be removed, and call sites could be updated to use the + operator.

total_tokens=30,
cost_usd=0.02,
)
result = add_token_usage(a, b)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If you implement __add__ on TokenUsage as suggested in src/ai_company/providers/models.py, this call can be simplified.

Suggested change
result = add_token_usage(a, b)
result = a + b

total_tokens=20,
cost_usd=0.0,
)
result = add_token_usage(a, b)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If you implement __add__ on TokenUsage as suggested in src/ai_company/providers/models.py, this call can be simplified.

Suggested change
result = add_token_usage(a, b)
result = a + b

total_tokens=75,
cost_usd=0.05,
)
result = add_token_usage(ZERO_TOKEN_USAGE, usage)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If you implement __add__ on TokenUsage as suggested in src/ai_company/providers/models.py, this call can be simplified.

Suggested change
result = add_token_usage(ZERO_TOKEN_USAGE, usage)
result = ZERO_TOKEN_USAGE + usage

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/unit/providers/test_models.py`:
- Around line 82-92: Replace the hand-written dict with a real serialized
payload from TokenUsage.model_dump to perform a true round-trip: create a
TokenUsage instance with input_tokens and output_tokens, call model_dump() to
get the serialized dict, mutate the serialized dict's "total_tokens" to 999,
then pass that dict into TokenUsage.model_validate(...) and assert that
usage.total_tokens == 15; reference the test function
test_total_tokens_roundtrip and methods TokenUsage.model_dump and
TokenUsage.model_validate when locating the change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: a7ab4640-be95-4f24-bc27-dc5fbd4fed2f

📥 Commits

Reviewing files that changed from the base of the PR and between 7e5e861 and 5de4fce.

📒 Files selected for processing (10)
  • CLAUDE.md
  • DESIGN_SPEC.md
  • src/ai_company/providers/base.py
  • src/ai_company/providers/models.py
  • tests/unit/engine/conftest.py
  • tests/unit/engine/test_context.py
  • tests/unit/engine/test_task_execution.py
  • tests/unit/providers/conftest.py
  • tests/unit/providers/test_base_provider.py
  • tests/unit/providers/test_models.py
💤 Files with no reviewable changes (5)
  • src/ai_company/providers/base.py
  • tests/unit/engine/test_context.py
  • tests/unit/providers/conftest.py
  • tests/unit/engine/conftest.py
  • tests/unit/providers/test_base_provider.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Agent
  • GitHub Check: Greptile Review
🧰 Additional context used
📓 Path-based instructions (3)
tests/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

tests/**/*.py: Mark test functions with @pytest.mark.unit, @pytest.mark.integration, @pytest.mark.e2e, or @pytest.mark.slow
Maintain minimum 80% code coverage (enforced in CI)
Use asyncio_mode = 'auto' in pytest configuration — no manual @pytest.mark.asyncio needed on async tests
Set 30-second timeout per test
Use fake/test model IDs and provider names in tests (e.g. test-haiku-001, test-provider), never real vendor model IDs — tests must not be coupled to external providers

Files:

  • tests/unit/providers/test_models.py
  • tests/unit/engine/test_task_execution.py
DESIGN_SPEC.md

📄 CodeRabbit inference engine (CLAUDE.md)

Update DESIGN_SPEC.md to reflect approved deviations from the original design

Files:

  • DESIGN_SPEC.md
src/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

src/**/*.py: Always read DESIGN_SPEC.md before implementing any feature or planning any issue — it is the starting point for architecture, data models, and behavior
If implementation deviates from DESIGN_SPEC.md, alert the user and explain why — user decides whether to proceed or update the spec. Do NOT silently diverge.
When a spec section is referenced (e.g. 'Section 10.2'), read that section verbatim before coding
Every implementation plan must be presented to the user for accept/deny before coding starts
At every phase of planning and implementation, be critical and actively look for ways to improve the design in the spirit of what we're building (robustness, correctness, simplicity, future-proofing where it's free). Surface improvements as suggestions, not silent changes.
Do NOT use from __future__ import annotations — Python 3.14 has PEP 649 native lazy annotations
Use except A, B: syntax without parentheses for multiple exception handling (PEP 758) — ruff enforces this on Python 3.14
All public functions must have type hints and pass mypy strict mode
All public classes and functions must have Google-style docstrings, enforced by ruff D rules
Never mutate existing objects — create new objects instead. For non-Pydantic internal collections (registries, BaseTool), use copy.deepcopy() at construction + MappingProxyType wrapping for read-only enforcement.
For dict/list fields in frozen Pydantic models, rely on frozen=True for field reassignment prevention and use copy.deepcopy() at system boundaries (tool execution, LLM provider serialization, inter-agent delegation, serializing for persistence)
Use frozen Pydantic models for config/identity; use separate mutable-via-copy models (using model_copy(update=...)) for runtime state that evolves (e.g. agent execution state, task progress). Never mix static config fields with mutable runtime fields in one model.
Use Pydantic v2 with BaseModel, model_validator, and ConfigDict
Use `@computed...

Files:

  • src/ai_company/providers/models.py
🧠 Learnings (15)
📓 Common learnings
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-06T07:08:12.933Z
Learning: Applies to src/**/*.py : Use `computed_field` for derived values instead of storing + validating redundant fields in Pydantic models
📚 Learning: 2026-03-06T07:08:12.933Z
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-06T07:08:12.933Z
Learning: Applies to src/**/*.py : Use `computed_field` for derived values instead of storing + validating redundant fields in Pydantic models

Applied to files:

  • CLAUDE.md
  • DESIGN_SPEC.md
  • src/ai_company/providers/models.py
📚 Learning: 2026-02-26T17:43:50.902Z
Learnt from: CR
Repo: Aureliolo/story-factory PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-02-26T17:43:50.902Z
Learning: When making changes that affect architecture, services, key files, settings, or workflows, update the relevant sections of existing documentation (CLAUDE.md, README.md, etc.) to reflect those changes.

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-01-26T08:59:32.818Z
Learnt from: CR
Repo: Aureliolo/story-factory PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-01-26T08:59:32.818Z
Learning: Applies to docs/MODELS.md : Update docs/MODELS.md when adding model recommendations

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-06T07:08:12.933Z
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-06T07:08:12.933Z
Learning: Applies to src/**/*.py : Use frozen Pydantic models for config/identity; use separate mutable-via-copy models (using `model_copy(update=...)`) for runtime state that evolves (e.g. agent execution state, task progress). Never mix static config fields with mutable runtime fields in one model.

Applied to files:

  • CLAUDE.md
  • DESIGN_SPEC.md
📚 Learning: 2026-03-06T07:08:12.933Z
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-06T07:08:12.933Z
Learning: Applies to src/**/*.py : All public classes and functions must have Google-style docstrings, enforced by ruff D rules

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-06T07:08:12.933Z
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-06T07:08:12.933Z
Learning: Applies to src/**/*.py : For `dict`/`list` fields in frozen Pydantic models, rely on `frozen=True` for field reassignment prevention and use `copy.deepcopy()` at system boundaries (tool execution, LLM provider serialization, inter-agent delegation, serializing for persistence)

Applied to files:

  • CLAUDE.md
  • DESIGN_SPEC.md
📚 Learning: 2026-03-06T07:08:12.933Z
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-06T07:08:12.933Z
Learning: Applies to src/**/*.py : Never mutate existing objects — create new objects instead. For non-Pydantic internal collections (registries, `BaseTool`), use `copy.deepcopy()` at construction + `MappingProxyType` wrapping for read-only enforcement.

Applied to files:

  • CLAUDE.md
  • DESIGN_SPEC.md
📚 Learning: 2026-01-26T08:59:32.818Z
Learnt from: CR
Repo: Aureliolo/story-factory PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-01-26T08:59:32.818Z
Learning: Applies to **/*.py : Line length: 100 characters (enforced by Ruff)

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-01-26T08:59:32.818Z
Learnt from: CR
Repo: Aureliolo/story-factory PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-01-26T08:59:32.818Z
Learning: Applies to **/*.py : Use type hints where appropriate. Use Pydantic models for data validation in `src/memory/story_state.py`, dataclasses in `src/settings.py`.

Applied to files:

  • CLAUDE.md
  • DESIGN_SPEC.md
📚 Learning: 2026-03-06T07:08:12.933Z
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-06T07:08:12.933Z
Learning: Applies to src/**/*.py : At every phase of planning and implementation, be critical and actively look for ways to improve the design in the spirit of what we're building (robustness, correctness, simplicity, future-proofing where it's free). Surface improvements as suggestions, not silent changes.

Applied to files:

  • CLAUDE.md
  • DESIGN_SPEC.md
📚 Learning: 2026-03-06T07:08:12.933Z
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-06T07:08:12.933Z
Learning: Applies to src/**/*.py : Maximum line length is 88 characters (enforced by ruff)

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-06T07:08:12.933Z
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-06T07:08:12.933Z
Learning: Applies to src/**/*.py : Use Pydantic v2 with `BaseModel`, `model_validator`, and `ConfigDict`

Applied to files:

  • CLAUDE.md
  • src/ai_company/providers/models.py
📚 Learning: 2026-03-06T07:08:12.933Z
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-06T07:08:12.933Z
Learning: Applies to src/**/*.py : Always read `DESIGN_SPEC.md` before implementing any feature or planning any issue — it is the starting point for architecture, data models, and behavior

Applied to files:

  • CLAUDE.md
📚 Learning: 2026-03-06T07:08:12.933Z
Learnt from: CR
Repo: Aureliolo/ai-company PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-06T07:08:12.933Z
Learning: Applies to DESIGN_SPEC.md : Update `DESIGN_SPEC.md` to reflect approved deviations from the original design

Applied to files:

  • DESIGN_SPEC.md
🪛 LanguageTool
DESIGN_SPEC.md

[style] ~860-~860: This word has been used in one of the immediately preceding sentences. Using a synonym could make your text more interesting to read, unless the repetition is intentional.
Context: ..._tokens — no stored field or validator needed. Spending summary models (AgentSpendin...

(EN_REPEATEDWORDS_NEED)

- Add description="Total token count" to @computed_field for consistency
- Improve test_total_tokens_roundtrip to use model_dump() + mutate pattern
- Add JSON roundtrip assertion (model_dump_json/model_validate_json)
- Add test_total_tokens_not_assignable for computed property immutability
- Fix DESIGN_SPEC.md §15.3: CompletionRequest → CompletionConfig

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@Aureliolo Aureliolo merged commit c0bab18 into main Mar 6, 2026
10 of 11 checks passed
@Aureliolo Aureliolo deleted the feat/computed-total-tokens branch March 6, 2026 08:45
Aureliolo added a commit that referenced this pull request Mar 10, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.1.1](ai-company-v0.1.0...ai-company-v0.1.1)
(2026-03-10)


### Features

* add autonomy levels and approval timeout policies
([#42](#42),
[#126](#126))
([#197](#197))
([eecc25a](eecc25a))
* add CFO cost optimization service with anomaly detection, reports, and
approval decisions
([#186](#186))
([a7fa00b](a7fa00b))
* add code quality toolchain (ruff, mypy, pre-commit, dependabot)
([#63](#63))
([36681a8](36681a8))
* add configurable cost tiers and subscription/quota-aware tracking
([#67](#67))
([#185](#185))
([9baedfa](9baedfa))
* add container packaging, Docker Compose, and CI pipeline
([#269](#269))
([435bdfe](435bdfe)),
closes [#267](#267)
* add coordination error taxonomy classification pipeline
([#146](#146))
([#181](#181))
([70c7480](70c7480))
* add cost-optimized, hierarchical, and auction assignment strategies
([#175](#175))
([ce924fa](ce924fa)),
closes [#173](#173)
* add design specification, license, and project setup
([8669a09](8669a09))
* add env var substitution and config file auto-discovery
([#77](#77))
([7f53832](7f53832))
* add FastestStrategy routing + vendor-agnostic cleanup
([#140](#140))
([09619cb](09619cb)),
closes [#139](#139)
* add HR engine and performance tracking
([#45](#45),
[#47](#47))
([#193](#193))
([2d091ea](2d091ea))
* add issue auto-search and resolution verification to PR review skill
([#119](#119))
([deecc39](deecc39))
* add memory retrieval, ranking, and context injection pipeline
([#41](#41))
([873b0aa](873b0aa))
* add pluggable MemoryBackend protocol with models, config, and events
([#180](#180))
([46cfdd4](46cfdd4))
* add pluggable MemoryBackend protocol with models, config, and events
([#32](#32))
([46cfdd4](46cfdd4))
* add pluggable PersistenceBackend protocol with SQLite implementation
([#36](#36))
([f753779](f753779))
* add progressive trust and promotion/demotion subsystems
([#43](#43),
[#49](#49))
([3a87c08](3a87c08))
* add retry handler, rate limiter, and provider resilience
([#100](#100))
([b890545](b890545))
* add SecOps security agent with rule engine, audit log, and ToolInvoker
integration ([#40](#40))
([83b7b6c](83b7b6c))
* add shared org memory and memory consolidation/archival
([#125](#125),
[#48](#48))
([4a0832b](4a0832b))
* design unified provider interface
([#86](#86))
([3e23d64](3e23d64))
* expand template presets, rosters, and add inheritance
([#80](#80),
[#81](#81),
[#84](#84))
([15a9134](15a9134))
* implement agent runtime state vs immutable config split
([#115](#115))
([4cb1ca5](4cb1ca5))
* implement AgentEngine core orchestrator
([#11](#11))
([#143](#143))
([f2eb73a](f2eb73a))
* implement basic tool system (registry, invocation, results)
([#15](#15))
([c51068b](c51068b))
* implement built-in file system tools
([#18](#18))
([325ef98](325ef98))
* implement communication foundation — message bus, dispatcher, and
messenger ([#157](#157))
([8e71bfd](8e71bfd))
* implement company template system with 7 built-in presets
([#85](#85))
([cbf1496](cbf1496))
* implement conflict resolution protocol
([#122](#122))
([#166](#166))
([e03f9f2](e03f9f2))
* implement core entity and role system models
([#69](#69))
([acf9801](acf9801))
* implement crash recovery with fail-and-reassign strategy
([#149](#149))
([e6e91ed](e6e91ed))
* implement engine extensions — Plan-and-Execute loop and call
categorization
([#134](#134),
[#135](#135))
([#159](#159))
([9b2699f](9b2699f))
* implement enterprise logging system with structlog
([#73](#73))
([2f787e5](2f787e5))
* implement graceful shutdown with cooperative timeout strategy
([#130](#130))
([6592515](6592515))
* implement hierarchical delegation and loop prevention
([#12](#12),
[#17](#17))
([6be60b6](6be60b6))
* implement LiteLLM driver and provider registry
([#88](#88))
([ae3f18b](ae3f18b)),
closes [#4](#4)
* implement LLM decomposition strategy and workspace isolation
([#174](#174))
([aa0eefe](aa0eefe))
* implement meeting protocol system
([#123](#123))
([ee7caca](ee7caca))
* implement message and communication domain models
([#74](#74))
([560a5d2](560a5d2))
* implement model routing engine
([#99](#99))
([d3c250b](d3c250b))
* implement parallel agent execution
([#22](#22))
([#161](#161))
([65940b3](65940b3))
* implement per-call cost tracking service
([#7](#7))
([#102](#102))
([c4f1f1c](c4f1f1c))
* implement personality injection and system prompt construction
([#105](#105))
([934dd85](934dd85))
* implement single-task execution lifecycle
([#21](#21))
([#144](#144))
([c7e64e4](c7e64e4))
* implement subprocess sandbox for tool execution isolation
([#131](#131))
([#153](#153))
([3c8394e](3c8394e))
* implement task assignment subsystem with pluggable strategies
([#172](#172))
([c7f1b26](c7f1b26)),
closes [#26](#26)
[#30](#30)
* implement task decomposition and routing engine
([#14](#14))
([9c7fb52](9c7fb52))
* implement Task, Project, Artifact, Budget, and Cost domain models
([#71](#71))
([81eabf1](81eabf1))
* implement tool permission checking
([#16](#16))
([833c190](833c190))
* implement YAML config loader with Pydantic validation
([#59](#59))
([ff3a2ba](ff3a2ba))
* implement YAML config loader with Pydantic validation
([#75](#75))
([ff3a2ba](ff3a2ba))
* initialize project with uv, hatchling, and src layout
([39005f9](39005f9))
* initialize project with uv, hatchling, and src layout
([#62](#62))
([39005f9](39005f9))
* Litestar REST API, WebSocket feed, and approval queue (M6)
([#189](#189))
([29fcd08](29fcd08))
* make TokenUsage.total_tokens a computed field
([#118](#118))
([c0bab18](c0bab18)),
closes [#109](#109)
* parallel tool execution in ToolInvoker.invoke_all
([#137](#137))
([58517ee](58517ee))
* testing framework, CI pipeline, and M0 gap fixes
([#64](#64))
([f581749](f581749))
* wire all modules into observability system
([#97](#97))
([f7a0617](f7a0617))


### Bug Fixes

* address Greptile post-merge review findings from PRs
[#170](https://github.com/Aureliolo/ai-company/issues/170)-[#175](https://github.com/Aureliolo/ai-company/issues/175)
([#176](#176))
([c5ca929](c5ca929))
* address post-merge review feedback from PRs
[#164](https://github.com/Aureliolo/ai-company/issues/164)-[#167](https://github.com/Aureliolo/ai-company/issues/167)
([#170](#170))
([3bf897a](3bf897a)),
closes [#169](#169)
* enforce strict mypy on test files
([#89](#89))
([aeeff8c](aeeff8c))
* harden Docker sandbox, MCP bridge, and code runner
([#50](#50),
[#53](#53))
([d5e1b6e](d5e1b6e))
* harden git tools security + code quality improvements
([#150](#150))
([000a325](000a325))
* harden subprocess cleanup, env filtering, and shutdown resilience
([#155](#155))
([d1fe1fb](d1fe1fb))
* incorporate post-merge feedback + pre-PR review fixes
([#164](#164))
([c02832a](c02832a))
* pre-PR review fixes for post-merge findings
([#183](#183))
([26b3108](26b3108))
* strengthen immutability for BaseTool schema and ToolInvoker boundaries
([#117](#117))
([7e5e861](7e5e861))


### Performance

* harden non-inferable principle implementation
([#195](#195))
([02b5f4e](02b5f4e)),
closes [#188](#188)


### Refactoring

* adopt NotBlankStr across all models
([#108](#108))
([#120](#120))
([ef89b90](ef89b90))
* extract _SpendingTotals base class from spending summary models
([#111](#111))
([2f39c1b](2f39c1b))
* harden BudgetEnforcer with error handling, validation extraction, and
review fixes
([#182](#182))
([c107bf9](c107bf9))
* harden personality profiles, department validation, and template
rendering ([#158](#158))
([10b2299](10b2299))
* pre-PR review improvements for ExecutionLoop + ReAct loop
([#124](#124))
([8dfb3c0](8dfb3c0))
* split events.py into per-domain event modules
([#136](#136))
([e9cba89](e9cba89))


### Documentation

* add ADR-001 memory layer evaluation and selection
([#178](#178))
([db3026f](db3026f)),
closes [#39](#39)
* add agent scaling research findings to DESIGN_SPEC
([#145](#145))
([57e487b](57e487b))
* add CLAUDE.md, contributing guide, and dev documentation
([#65](#65))
([55c1025](55c1025)),
closes [#54](#54)
* add crash recovery, sandboxing, analytics, and testing decisions
([#127](#127))
([5c11595](5c11595))
* address external review feedback with MVP scope and new protocols
([#128](#128))
([3b30b9a](3b30b9a))
* expand design spec with pluggable strategy protocols
([#121](#121))
([6832db6](6832db6))
* finalize 23 design decisions (ADR-002)
([#190](#190))
([8c39742](8c39742))
* update project docs for M2.5 conventions and add docs-consistency
review agent
([#114](#114))
([99766ee](99766ee))


### Tests

* add e2e single agent integration tests
([#24](#24))
([#156](#156))
([f566fb4](f566fb4))
* add provider adapter integration tests
([#90](#90))
([40a61f4](40a61f4))


### CI/CD

* add Release Please for automated versioning and GitHub Releases
([#278](#278))
([a488758](a488758))
* bump actions/checkout from 4 to 6
([#95](#95))
([1897247](1897247))
* bump actions/upload-artifact from 4 to 7
([#94](#94))
([27b1517](27b1517))
* harden CI/CD pipeline
([#92](#92))
([ce4693c](ce4693c))
* split vulnerability scans into critical-fail and high-warn tiers
([#277](#277))
([aba48af](aba48af))


### Maintenance

* add /worktree skill for parallel worktree management
([#171](#171))
([951e337](951e337))
* add design spec context loading to research-link skill
([8ef9685](8ef9685))
* add post-merge-cleanup skill
([#70](#70))
([f913705](f913705))
* add pre-pr-review skill and update CLAUDE.md
([#103](#103))
([92e9023](92e9023))
* add research-link skill and rename skill files to SKILL.md
([#101](#101))
([651c577](651c577))
* bump aiosqlite from 0.21.0 to 0.22.1
([#191](#191))
([3274a86](3274a86))
* bump pyyaml from 6.0.2 to 6.0.3 in the minor-and-patch group
([#96](#96))
([0338d0c](0338d0c))
* bump ruff from 0.15.4 to 0.15.5
([a49ee46](a49ee46))
* fix M0 audit items
([#66](#66))
([c7724b5](c7724b5))
* pin setup-uv action to full SHA
([#281](#281))
([4448002](4448002))
* post-audit cleanup — PEP 758, loggers, bug fixes, refactoring, tests,
hookify rules
([#148](#148))
([c57a6a9](c57a6a9))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
Aureliolo added a commit that referenced this pull request Mar 11, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.1.0](v0.0.0...v0.1.0)
(2026-03-11)


### Features

* add autonomy levels and approval timeout policies
([#42](#42),
[#126](#126))
([#197](#197))
([eecc25a](eecc25a))
* add CFO cost optimization service with anomaly detection, reports, and
approval decisions
([#186](#186))
([a7fa00b](a7fa00b))
* add code quality toolchain (ruff, mypy, pre-commit, dependabot)
([#63](#63))
([36681a8](36681a8))
* add configurable cost tiers and subscription/quota-aware tracking
([#67](#67))
([#185](#185))
([9baedfa](9baedfa))
* add container packaging, Docker Compose, and CI pipeline
([#269](#269))
([435bdfe](435bdfe)),
closes [#267](#267)
* add coordination error taxonomy classification pipeline
([#146](#146))
([#181](#181))
([70c7480](70c7480))
* add cost-optimized, hierarchical, and auction assignment strategies
([#175](#175))
([ce924fa](ce924fa)),
closes [#173](#173)
* add design specification, license, and project setup
([8669a09](8669a09))
* add env var substitution and config file auto-discovery
([#77](#77))
([7f53832](7f53832))
* add FastestStrategy routing + vendor-agnostic cleanup
([#140](#140))
([09619cb](09619cb)),
closes [#139](#139)
* add HR engine and performance tracking
([#45](#45),
[#47](#47))
([#193](#193))
([2d091ea](2d091ea))
* add issue auto-search and resolution verification to PR review skill
([#119](#119))
([deecc39](deecc39))
* add mandatory JWT + API key authentication
([#256](#256))
([c279cfe](c279cfe))
* add memory retrieval, ranking, and context injection pipeline
([#41](#41))
([873b0aa](873b0aa))
* add pluggable MemoryBackend protocol with models, config, and events
([#180](#180))
([46cfdd4](46cfdd4))
* add pluggable MemoryBackend protocol with models, config, and events
([#32](#32))
([46cfdd4](46cfdd4))
* add pluggable output scan response policies
([#263](#263))
([b9907e8](b9907e8))
* add pluggable PersistenceBackend protocol with SQLite implementation
([#36](#36))
([f753779](f753779))
* add progressive trust and promotion/demotion subsystems
([#43](#43),
[#49](#49))
([3a87c08](3a87c08))
* add retry handler, rate limiter, and provider resilience
([#100](#100))
([b890545](b890545))
* add SecOps security agent with rule engine, audit log, and ToolInvoker
integration ([#40](#40))
([83b7b6c](83b7b6c))
* add shared org memory and memory consolidation/archival
([#125](#125),
[#48](#48))
([4a0832b](4a0832b))
* design unified provider interface
([#86](#86))
([3e23d64](3e23d64))
* expand template presets, rosters, and add inheritance
([#80](#80),
[#81](#81),
[#84](#84))
([15a9134](15a9134))
* implement agent runtime state vs immutable config split
([#115](#115))
([4cb1ca5](4cb1ca5))
* implement AgentEngine core orchestrator
([#11](#11))
([#143](#143))
([f2eb73a](f2eb73a))
* implement AuditRepository for security audit log persistence
([#279](#279))
([94bc29f](94bc29f))
* implement basic tool system (registry, invocation, results)
([#15](#15))
([c51068b](c51068b))
* implement built-in file system tools
([#18](#18))
([325ef98](325ef98))
* implement communication foundation — message bus, dispatcher, and
messenger ([#157](#157))
([8e71bfd](8e71bfd))
* implement company template system with 7 built-in presets
([#85](#85))
([cbf1496](cbf1496))
* implement conflict resolution protocol
([#122](#122))
([#166](#166))
([e03f9f2](e03f9f2))
* implement core entity and role system models
([#69](#69))
([acf9801](acf9801))
* implement crash recovery with fail-and-reassign strategy
([#149](#149))
([e6e91ed](e6e91ed))
* implement engine extensions — Plan-and-Execute loop and call
categorization
([#134](#134),
[#135](#135))
([#159](#159))
([9b2699f](9b2699f))
* implement enterprise logging system with structlog
([#73](#73))
([2f787e5](2f787e5))
* implement graceful shutdown with cooperative timeout strategy
([#130](#130))
([6592515](6592515))
* implement hierarchical delegation and loop prevention
([#12](#12),
[#17](#17))
([6be60b6](6be60b6))
* implement LiteLLM driver and provider registry
([#88](#88))
([ae3f18b](ae3f18b)),
closes [#4](#4)
* implement LLM decomposition strategy and workspace isolation
([#174](#174))
([aa0eefe](aa0eefe))
* implement meeting protocol system
([#123](#123))
([ee7caca](ee7caca))
* implement message and communication domain models
([#74](#74))
([560a5d2](560a5d2))
* implement model routing engine
([#99](#99))
([d3c250b](d3c250b))
* implement parallel agent execution
([#22](#22))
([#161](#161))
([65940b3](65940b3))
* implement per-call cost tracking service
([#7](#7))
([#102](#102))
([c4f1f1c](c4f1f1c))
* implement personality injection and system prompt construction
([#105](#105))
([934dd85](934dd85))
* implement single-task execution lifecycle
([#21](#21))
([#144](#144))
([c7e64e4](c7e64e4))
* implement subprocess sandbox for tool execution isolation
([#131](#131))
([#153](#153))
([3c8394e](3c8394e))
* implement task assignment subsystem with pluggable strategies
([#172](#172))
([c7f1b26](c7f1b26)),
closes [#26](#26)
[#30](#30)
* implement task decomposition and routing engine
([#14](#14))
([9c7fb52](9c7fb52))
* implement Task, Project, Artifact, Budget, and Cost domain models
([#71](#71))
([81eabf1](81eabf1))
* implement tool permission checking
([#16](#16))
([833c190](833c190))
* implement YAML config loader with Pydantic validation
([#59](#59))
([ff3a2ba](ff3a2ba))
* implement YAML config loader with Pydantic validation
([#75](#75))
([ff3a2ba](ff3a2ba))
* initialize project with uv, hatchling, and src layout
([39005f9](39005f9))
* initialize project with uv, hatchling, and src layout
([#62](#62))
([39005f9](39005f9))
* Litestar REST API, WebSocket feed, and approval queue (M6)
([#189](#189))
([29fcd08](29fcd08))
* make TokenUsage.total_tokens a computed field
([#118](#118))
([c0bab18](c0bab18)),
closes [#109](#109)
* parallel tool execution in ToolInvoker.invoke_all
([#137](#137))
([58517ee](58517ee))
* testing framework, CI pipeline, and M0 gap fixes
([#64](#64))
([f581749](f581749))
* wire all modules into observability system
([#97](#97))
([f7a0617](f7a0617))


### Bug Fixes

* address Greptile post-merge review findings from PRs
[#170](https://github.com/Aureliolo/ai-company/issues/170)-[#175](https://github.com/Aureliolo/ai-company/issues/175)
([#176](#176))
([c5ca929](c5ca929))
* address post-merge review feedback from PRs
[#164](https://github.com/Aureliolo/ai-company/issues/164)-[#167](https://github.com/Aureliolo/ai-company/issues/167)
([#170](#170))
([3bf897a](3bf897a)),
closes [#169](#169)
* enforce strict mypy on test files
([#89](#89))
([aeeff8c](aeeff8c))
* harden Docker sandbox, MCP bridge, and code runner
([#50](#50),
[#53](#53))
([d5e1b6e](d5e1b6e))
* harden git tools security + code quality improvements
([#150](#150))
([000a325](000a325))
* harden subprocess cleanup, env filtering, and shutdown resilience
([#155](#155))
([d1fe1fb](d1fe1fb))
* incorporate post-merge feedback + pre-PR review fixes
([#164](#164))
([c02832a](c02832a))
* pre-PR review fixes for post-merge findings
([#183](#183))
([26b3108](26b3108))
* resolve circular imports, bump litellm, fix release tag format
([#286](#286))
([a6659b5](a6659b5))
* strengthen immutability for BaseTool schema and ToolInvoker boundaries
([#117](#117))
([7e5e861](7e5e861))


### Performance

* harden non-inferable principle implementation
([#195](#195))
([02b5f4e](02b5f4e)),
closes [#188](#188)


### Refactoring

* adopt NotBlankStr across all models
([#108](#108))
([#120](#120))
([ef89b90](ef89b90))
* extract _SpendingTotals base class from spending summary models
([#111](#111))
([2f39c1b](2f39c1b))
* harden BudgetEnforcer with error handling, validation extraction, and
review fixes
([#182](#182))
([c107bf9](c107bf9))
* harden personality profiles, department validation, and template
rendering ([#158](#158))
([10b2299](10b2299))
* pre-PR review improvements for ExecutionLoop + ReAct loop
([#124](#124))
([8dfb3c0](8dfb3c0))
* split events.py into per-domain event modules
([#136](#136))
([e9cba89](e9cba89))


### Documentation

* add ADR-001 memory layer evaluation and selection
([#178](#178))
([db3026f](db3026f)),
closes [#39](#39)
* add agent scaling research findings to DESIGN_SPEC
([#145](#145))
([57e487b](57e487b))
* add CLAUDE.md, contributing guide, and dev documentation
([#65](#65))
([55c1025](55c1025)),
closes [#54](#54)
* add crash recovery, sandboxing, analytics, and testing decisions
([#127](#127))
([5c11595](5c11595))
* address external review feedback with MVP scope and new protocols
([#128](#128))
([3b30b9a](3b30b9a))
* expand design spec with pluggable strategy protocols
([#121](#121))
([6832db6](6832db6))
* finalize 23 design decisions (ADR-002)
([#190](#190))
([8c39742](8c39742))
* update project docs for M2.5 conventions and add docs-consistency
review agent
([#114](#114))
([99766ee](99766ee))


### Tests

* add e2e single agent integration tests
([#24](#24))
([#156](#156))
([f566fb4](f566fb4))
* add provider adapter integration tests
([#90](#90))
([40a61f4](40a61f4))


### CI/CD

* add Release Please for automated versioning and GitHub Releases
([#278](#278))
([a488758](a488758))
* bump actions/checkout from 4 to 6
([#95](#95))
([1897247](1897247))
* bump actions/upload-artifact from 4 to 7
([#94](#94))
([27b1517](27b1517))
* bump anchore/scan-action from 6.5.1 to 7.3.2
([#271](#271))
([80a1c15](80a1c15))
* bump docker/build-push-action from 6.19.2 to 7.0.0
([#273](#273))
([dd0219e](dd0219e))
* bump docker/login-action from 3.7.0 to 4.0.0
([#272](#272))
([33d6238](33d6238))
* bump docker/metadata-action from 5.10.0 to 6.0.0
([#270](#270))
([baee04e](baee04e))
* bump docker/setup-buildx-action from 3.12.0 to 4.0.0
([#274](#274))
([5fc06f7](5fc06f7))
* bump sigstore/cosign-installer from 3.9.1 to 4.1.0
([#275](#275))
([29dd16c](29dd16c))
* harden CI/CD pipeline
([#92](#92))
([ce4693c](ce4693c))
* split vulnerability scans into critical-fail and high-warn tiers
([#277](#277))
([aba48af](aba48af))


### Maintenance

* add /worktree skill for parallel worktree management
([#171](#171))
([951e337](951e337))
* add design spec context loading to research-link skill
([8ef9685](8ef9685))
* add post-merge-cleanup skill
([#70](#70))
([f913705](f913705))
* add pre-pr-review skill and update CLAUDE.md
([#103](#103))
([92e9023](92e9023))
* add research-link skill and rename skill files to SKILL.md
([#101](#101))
([651c577](651c577))
* bump aiosqlite from 0.21.0 to 0.22.1
([#191](#191))
([3274a86](3274a86))
* bump pyyaml from 6.0.2 to 6.0.3 in the minor-and-patch group
([#96](#96))
([0338d0c](0338d0c))
* bump ruff from 0.15.4 to 0.15.5
([a49ee46](a49ee46))
* fix M0 audit items
([#66](#66))
([c7724b5](c7724b5))
* **main:** release ai-company 0.1.1
([#282](#282))
([2f4703d](2f4703d))
* pin setup-uv action to full SHA
([#281](#281))
([4448002](4448002))
* post-audit cleanup — PEP 758, loggers, bug fixes, refactoring, tests,
hookify rules
([#148](#148))
([c57a6a9](c57a6a9))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

---------

Signed-off-by: Aurelio <19254254+Aureliolo@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make TokenUsage.total_tokens a computed field

2 participants