Skip to content

Addressing PR comments#7

Merged
tafreeman merged 4 commits into
mainfrom
af
Apr 7, 2026
Merged

Addressing PR comments#7
tafreeman merged 4 commits into
mainfrom
af

Conversation

@tafreeman
Copy link
Copy Markdown
Owner

No description provided.

- Introduced a comprehensive C4 context level documentation for ExecutionKit, detailing system overview, personas, features, user journeys, external systems, and a context diagram.
- Highlighted key patterns such as Consensus, Refine Loop, and React Loop, along with their use cases and API references.

refactor: Improve budget management in TokenUsage

- Updated the `_subtract` function to handle budget fields with a sentinel value of -1 for exhausted budgets, preventing misinterpretation of unlimited fields.
- Enhanced `CostTracker` with methods to reserve and release call slots, addressing TOCTOU race conditions during concurrent LLM dispatches.

fix: Update error handling and messaging in provider

- Changed error handling in the `Provider` class to raise more specific exceptions for transport failures.
- Adjusted the `Kit` class to raise `TypeError` instead of `PatternError` when the provider does not meet the required interface.

feat: Introduce message construction helpers

- Added `user_message` and `assistant_message` functions for constructing OpenAI-compatible message dictionaries, improving code readability and maintainability.

test: Enhance test coverage for budget management and tool parameters

- Added tests to ensure proper handling of budget exhaustion and the correct behavior of the `_trim_messages` function.
- Verified that tool parameters are wrapped in a read-only `MappingProxyType` to enforce immutability.

chore: Update project metadata and dependencies

- Updated project URLs in `pyproject.toml` to reflect the correct repository location.
- Ensured all tests pass with the latest changes and maintained high coverage across the codebase.
# Conflicts:
#	.github/workflows/publish.yml
#	SECURITY.md
#	executionkit/patterns/consensus.py
#	executionkit/patterns/react_loop.py
Copilot AI review requested due to automatic review settings April 7, 2026 18:37
@tafreeman
Copy link
Copy Markdown
Owner Author

@codex[agent] fix the liniting issues identified by the ci checks

@chatgpt-codex-connector
Copy link
Copy Markdown

To use Codex here, create an environment for this repo.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

except Exception:
tracker.release_call() # release reserved slot on failure

P1 Badge Release reserved call slot on cancellation

checked_complete reserves a call before awaiting with_retry, but the cleanup only catches Exception. In Python, asyncio.CancelledError is a BaseException, so cancellation skips this handler and leaves the reservation counted forever. After any cancelled request, the shared CostTracker can report phantom llm_calls, causing later budget checks to fail early in long-running or concurrent workflows.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

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 introduces several improvements to the ExecutionKit library, including enhanced budget management in the pipe composition pattern, the addition of reserve_call and release_call methods to CostTracker to prevent race conditions, and new message construction helpers. It also updates documentation and adds unit tests for the new functionality. My feedback highlights that the reserve_call and release_call methods are currently duplicated in cost.py and suggests removing the redundant implementation. Additionally, I have raised a concern regarding the use of -1 as a sentinel value for exhausted budgets, as it may compromise the mathematical integrity of the TokenUsage class.

Comment thread executionkit/cost.py Outdated
Comment on lines +56 to +68
def reserve_call(self) -> None:
"""Reserve one call slot before an async LLM dispatch.

Pre-increments the call counter to prevent TOCTOU races when
concurrent coroutines check the budget. If the dispatch fails,
call :meth:`release_call` to restore the slot.
"""
self._calls += 1

def release_call(self) -> None:
"""Release a previously reserved call slot on dispatch failure."""
self._calls -= 1

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

The methods reserve_call and release_call are duplicated in this file. They are already defined with more comprehensive docstrings at lines 31 and 39. This redundant definition should be removed to keep the class clean and avoid maintenance confusion.

Comment thread executionkit/compose.py
if budget == 0: # unlimited field — preserve it
return 0
remaining = budget - spent
return remaining if remaining > 0 else -1 # -1 = exhausted
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

Using -1 as a sentinel value for an exhausted budget in TokenUsage is a fragile design choice. Since TokenUsage is a public data class that implements __add__, any mathematical operations involving an exhausted budget object will yield incorrect results (e.g., adding an exhausted budget to a usage object). While this works for internal logic in checked_complete, it breaks the mathematical properties of the type. A more robust approach would be to use None for unlimited fields and 0 for exhausted fields, although this would require a larger refactor of the budget convention.

Co-authored-by: tafreeman <72930272+tafreeman@users.noreply.github.com>
@Codex
Copy link
Copy Markdown
Contributor

Codex AI commented Apr 7, 2026

@codex[agent] fix the liniting issues identified by the ci checks

Fixed the lint/format errors and ensured ruff + pytest are clean in commit 352c057.

@Codex Codex AI changed the title Af Addressing PR comments Apr 7, 2026
Copy link
Copy Markdown
Contributor

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 tightens immutability guarantees across core value types (tools, responses, results), refines budget propagation semantics in pipe() (using an explicit exhausted sentinel), and adds/updates extensive documentation and tests to reflect the evolving public API.

Changes:

  • Enforce read-only mappings (via MappingProxyType) and immutable sequences (tuples) in core dataclasses (Tool, LLMResponse, PatternResult) and adapt tests accordingly.
  • Change pipe() budget propagation to use -1 as an “exhausted” sentinel instead of clamping to 0 (which means “unlimited”), and teach budget enforcement to recognize the sentinel.
  • Add engine message helpers and large C4/API documentation set; update repository URLs in docs/metadata.

Reviewed changes

Copilot reviewed 38 out of 42 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tests/test_types.py Adds coverage for Tool.parameters immutability and JSON-serializable schema output.
tests/test_sync_and_parse.py Updates expectations for immutable LLMResponse fields (tool_calls tuple, usage proxy).
tests/test_provider.py Updates provider tests for immutable defaults and tuple tool_calls.
tests/test_patterns.py Adds/updates tests for consensus edge cases, budget exhaustion, and _trim_messages.
tests/test_kit.py Updates helper response construction to use MappingProxyType for usage.
tests/test_compose.py Extends compose tests for -1 exhausted-budget sentinel and _subtract behavior.
tests/conftest.py Updates test response factory to return tuple tool calls and proxy usage.
SECURITY.md Updates security reporting link and clarifies API key masking behavior.
README.md Updates CI badge link to the correct repository.
pyproject.toml Updates project URLs to the correct repository.
executionkit/types.py Makes Tool.parameters an immutable mapping (proxy-wrapped) and ensures to_schema() returns a plain dict.
executionkit/provider.py Makes LLMResponse.tool_calls a tuple and usage a MappingProxyType; improves transport error mapping.
executionkit/patterns/react_loop.py Updates typing/docs around message trimming and tool schema validation inputs.
executionkit/patterns/consensus.py Uses shared message constructors and wraps metadata as MappingProxyType; adds clearer docs.
executionkit/patterns/base.py Recognizes -1 exhausted-budget sentinel when enforcing budgets.
executionkit/engine/messages.py Adds user_message / assistant_message helpers for OpenAI-style chat messages.
executionkit/engine/init.py Re-exports the new message helper functions.
executionkit/cost.py Adds call reservation helpers (but currently duplicates method definitions).
executionkit/compose.py Changes budget subtraction to use -1 exhausted sentinel instead of clamping to 0.
docs/c4/c4-context.md Adds C4 context-level documentation for the project.
docs/c4/c4-container.md Adds C4 container-level documentation for the project.
docs/c4/c4-component.md Adds C4 component index and dependency graph.
docs/c4/c4-component-test-dev-utilities.md Adds C4 docs for test/dev utilities (MockProvider + examples).
docs/c4/c4-component-reasoning-patterns.md Adds C4 docs for reasoning patterns (consensus/refine/react/base).
docs/c4/c4-component-provider-layer.md Adds C4 docs for provider layer (protocols/types/errors) (currently out-of-sync with new immutable types).
docs/c4/c4-component-execution-engine.md Adds C4 docs for engine utilities (retry/parallel/json/messages).
docs/c4/c4-component-composition-session.md Adds C4 docs for composition/session layer (pipe/Kit/CostTracker).
docs/c4/c4-code-src-executionkit.md Adds code-level doc for root package (some type details need syncing).
docs/c4/c4-code-src-executionkit-patterns.md Adds code-level doc for patterns package.
docs/c4/c4-code-src-executionkit-engine.md Adds code-level doc for engine package.
docs/c4/c4-code-examples.md Adds code-level doc for examples directory.
docs/c4/c4-code-examples.html Adds HTML export of examples code-level doc.
docs/c4/apis/executionkit-api.yaml Adds an API specification file (currently out-of-sync with implemented immutable types).
CONTRIBUTING.md Updates clone URL to the correct repository.
CHANGELOG.md Cleans up changelog entries and records immutability-related changes.
.gitignore Ignores .full-review/ going forward (but tracked files remain committed).
.github/workflows/publish.yml Simplifies/repairs publish workflow steps and reinstates bandit with toml support.
.full-review/state.json Updates stored review state text to remove local absolute paths.
.full-review/00-scope.md Updates scope doc to remove local absolute paths.
.claude/settings.local.json Expands allowed commands; includes machine-specific absolute paths.

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

Comment thread executionkit/provider.py
Comment on lines 381 to 389
usage = data.get("usage")
if not isinstance(usage, dict):
usage = {}
return LLMResponse(
content=_extract_content(message.get("content")),
tool_calls=_parse_tool_calls(message.get("tool_calls")),
tool_calls=tuple(_parse_tool_calls(message.get("tool_calls"))),
finish_reason=str(choice.get("finish_reason", "stop")),
usage=usage,
usage=MappingProxyType(usage),
raw=data,
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

LLMResponse.usage is wrapped with MappingProxyType(usage) but usage is the same dict object stored inside raw (data). Because raw is exposed on the response, external mutation of response.raw["usage"] would mutate the supposedly-immutable response.usage view. Consider wrapping a shallow copy instead (e.g., MappingProxyType(dict(usage))) to avoid shared mutable state.

Copilot uses AI. Check for mistakes.
Comment thread docs/c4/apis/executionkit-api.yaml Outdated
Comment on lines +54 to +93
PatternResult:
description: >
Immutable generic result returned by every pattern function. T is
str for all three built-in patterns.
type: frozen_dataclass
x-module: executionkit.types
x-generic: "PatternResult[T]"
properties:
value:
type: T
description: The final output produced by the pattern
score:
type: "float | None"
description: Quality score (0.0–1.0) if computed by the pattern, else None
cost:
$ref: "#/components/schemas/TokenUsage"
description: Total token consumption across all LLM calls in this pattern run
metadata:
type: "dict[str, Any]"
description: Pattern-specific extra data (e.g. agreement_ratio, iterations, rounds)

LLMResponse:
description: >
Immutable structured view of a single LLM completion, normalised
from the raw provider response.
type: frozen_dataclass
x-module: executionkit.provider
properties:
content:
type: str
description: Text content of the completion
tool_calls:
type: "list[ToolCall]"
description: Parsed tool/function call invocations (empty list if none)
finish_reason:
type: str
description: Provider finish reason (e.g. stop, tool_calls, length)
usage:
type: "dict[str, Any]"
description: Raw usage dict from the provider response
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

The public API spec is out of sync with the implemented immutable types: PatternResult.metadata is now a MappingProxyType, and LLMResponse.tool_calls / LLMResponse.usage are now tuple/MappingProxyType (not list/dict). Update this spec to match the current dataclass field types so downstream readers don’t implement against outdated contracts.

Copilot uses AI. Check for mistakes.
Comment on lines +85 to +112
# Core response type
@dataclass(frozen=True)
class LLMResponse:
content: str
tool_calls: list[ToolCall]
finish_reason: str
usage: dict[str, Any]
raw: Any

@property
def input_tokens(self) -> int: ...
@property
def output_tokens(self) -> int: ...
@property
def total_tokens(self) -> int: ...
@property
def has_tool_calls(self) -> bool: ...
@property
def was_truncated(self) -> bool: ...

# Shared result container
@dataclass(frozen=True)
class PatternResult(Generic[T]):
value: T
score: float | None
cost: TokenUsage
metadata: dict[str, Any]

Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

This documentation block shows outdated type signatures for the immutable value types: LLMResponse.tool_calls is now a tuple (not list), LLMResponse.usage is a MappingProxyType (not dict), PatternResult.metadata is a MappingProxyType, and Tool.parameters is now treated as an immutable mapping. Please update the interface examples to reflect the current code so the docs don’t contradict the library behavior.

Copilot uses AI. Check for mistakes.
Comment thread .claude/settings.local.json Outdated
"Bash(python -m mypy executionkit/ tests/ --strict)",
"Bash(python -m mypy executionkit/ --strict)",
"Bash(python -m pytest tests/test_patterns.py::TestConsensus::test_max_cost_budget_exhausted_after_first_sample -v --tb=long)",
"Bash(git -C \"C:/Users/tandf/source/executionkit\" remote get-url origin)",
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

This settings file includes hard-coded absolute local paths (e.g. C:/Users/...) in allowed Bash command patterns. Committing machine-specific paths makes the config non-portable and may leak local environment details; consider removing these entries or replacing them with relative paths/patterns.

Suggested change
"Bash(git -C \"C:/Users/tandf/source/executionkit\" remote get-url origin)",
"Bash(git -C . remote get-url origin)",

Copilot uses AI. Check for mistakes.
@tafreeman
Copy link
Copy Markdown
Owner Author

@copilot apply changes based on the comments in this thread

…docs, local path

Agent-Logs-Url: https://github.com/tafreeman/executionkit/sessions/7a1e5cd7-12c9-46db-abf9-01289591d33d

Co-authored-by: tafreeman <72930272+tafreeman@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 7, 2026

@copilot apply changes based on the comments in this thread

Applied all four changes from the review thread in commit 91857d3:

  1. provider.py: Changed MappingProxyType(usage)MappingProxyType(dict(usage)) so LLMResponse.usage holds an independent copy rather than sharing the mutable dict inside raw.
  2. executionkit-api.yaml: Updated PatternResult.metadata to MappingProxyType[str, Any], LLMResponse.tool_calls to tuple[ToolCall, ...], and LLMResponse.usage to MappingProxyType[str, Any].
  3. c4-component-provider-layer.md: Updated the interface examples to match the current immutable types.
  4. .claude/settings.local.json: Replaced the hard-coded C:/Users/tandf/source/executionkit path with the portable git -C . remote get-url origin.

@tafreeman
Copy link
Copy Markdown
Owner Author

@claude[agent] any items in the converstation that has not been addressed?

@Claude
Copy link
Copy Markdown
Contributor

Claude AI commented Apr 7, 2026

@claude[agent] any items in the converstation that has not been addressed?

All review comments from the thread have been addressed in commit 91857d3:

  1. Fixed shared mutable state in LLMResponse.usage (provider.py:388)
  2. Updated API spec to reflect immutable types (executionkit-api.yaml)
  3. Updated component documentation with correct type signatures (c4-component-provider-layer.md)
  4. Removed hard-coded local path from settings (settings.local.json:80)

CI checks are passing.

@tafreeman tafreeman merged commit 855cd8e into main Apr 7, 2026
8 checks passed
@tafreeman tafreeman deleted the af branch April 10, 2026 14:35
tafreeman added a commit that referenced this pull request May 18, 2026
Addressing PR comments
tafreeman added a commit that referenced this pull request May 18, 2026
Addressing PR comments
tafreeman added a commit that referenced this pull request May 22, 2026
Addressing PR comments
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.

6 participants