Skip to content

0.12.0 dev - #341

Merged
marlon-costa-dc merged 43 commits into
mainfrom
0.12.0-dev
Aug 3, 2026
Merged

0.12.0 dev#341
marlon-costa-dc merged 43 commits into
mainfrom
0.12.0-dev

Conversation

@marlon-costa-dc

@marlon-costa-dc marlon-costa-dc commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Summary by cubic

Unified the result system on a covariant p.Result with a concrete r[T] facade, removed ResultLike, allowed None as a success payload, and tightened protocols, handlers, DI, and utilities. Regenerated CI/tooling (incl. multi-distro matrix) and excluded a standalone uv cycle.

  • Refactors

    • Made p.Result covariant; removed ResultLike; updated handlers/protocols/utilities/tests to use p.Result; factories return concrete r[T].
    • Consolidated result protocols into src/flext_core/_protocols/result.py; moved internals to src/flext_core/_result/ (base/behavior/construction/transforms/composition/unwrap); widened lash/recover/flow_through; simplified map_or; clarified value/unwrap errors; allowed None payloads.
    • Fixed DI wiring via dependency_injector.wiring.wire; serialized middleware with mp.PlainSerializer; service registration accepts class refs; FlextService validates by field name and alias.
    • Corrected @computed_field usage and exposed as staticmethod facades; normalized Settings.log_level; hardened project metadata parsing and homepage resolution.
  • CI and Tooling

    • Added multi-distro ci-matrix and Dockerfiles; expanded blocking CI push branches to dev, develop, and 0.12.0-dev.
    • Regenerated Makefile and pyproject.toml; standardized Python 3.13; added ast-grep, gitleaks, tokei, taplo, pyright; added sgconfig.yml; excluded standalone uv cycle.
    • Removed local .beads/; refreshed .envrc, .gitignore, .vscode; simplified .github/dependabot.yml; scoped AGENTS.md to project rules.

Written for commit 9236a21. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features

    • Expanded result handling with fluent transformations, error recovery, model conversion, safe unwrapping, and success/failure construction helpers.
    • Result values now provide clearer success, failure, payload, and error behavior.
    • Service registration now supports class-based service references.
  • Bug Fixes

    • Improved project metadata parsing and homepage URL handling.
    • Improved middleware configuration serialization.
  • Chores

    • Added multi-platform CI coverage and refreshed development environment setup.

Marlon Costa added 21 commits July 27, 2026 22:07
The construction mixin factories were typed as returning the mixin
itself instead of the concrete FlextResult facade. Rebind all return
types and cls casts to FlextResult[V] so consumers see the public
result type.
…/OO structure

- Merge p.Result auxiliary protocols into single structural protocol
- Move result internals to _result/ package with clean inheritance chain
- Remove mixin aliases and compatibility layers
- Align value access error message with RuntimeError convention
- Restore successful_result and failed_result static helpers
- Allow None payload in map operations (returns convention)
- Fix dependency-injector wiring type resolution
- Update project metadata error handling for missing project table
- p.Result now uses an explicit covariant TypeVar (Protocol[T_co]) with a
  covariant-safe member set: higher-order callbacks use Callable[..., X],
  lash/recover/flow_through return honest Result[T_co | U], and __or__/map_or
  keep single general signatures. Result[str] now flows into
  Result[JsonPayload] at handler boundaries (structural assignment was
  impossible while the protocol was invariant).
- FlextResultConstruction.ok returns the declared protocol type p.Result[V]
  (constructing the concrete FlextResult internally) so generic consumers
  solve the payload type nominally instead of through structural matching.
- FlextResultTransforms: lash/recover/flow_through widened to [U] forms,
  map_or overloads collapsed to the general form (same precision), redundant
  casts removed.
- Remove stale pyrefly ignore in _dependency_bindings and fix the
  Result[None] annotation in test_result_recent_behaviors.

Validated: pyrefly check 0 errors (src+tests+examples), ruff check/format
clean, pytest result suites green.
The overload set could not cover the protocol's general map_or signature
for static checkers (mypy reported FlextResult[Never] not assignable to
p.Result[V] at FlextResultConstruction.ok); the single general form keeps
identical precision and satisfies p.Result on mypy, pyrefly and pyright.
Also removes the now-unused type: ignore in _result/base.py and the stale
overload import.

Validated: mypy clean on the result chain, pyrefly 0 errors project-wide,
ruff clean.
…o basedpyright consumers

- Add explicit __init__ to FlextResult so basedpyright sees the value/error
  keyword parameters on the concrete generic class.
- Return FlextResult[V] from FlextResultConstruction.ok() so callers typed
  as r[T] accept the result without a cast.
- Normalize log_level declaration to plain Field(default=...) so type
  checkers infer the default and DcBackupSettings(workspace_root=...) calls
  type-check cleanly.
- Rename validate_error_data helper (dropping the leading underscore) so it
  can be reused from the concrete result facade.
…ssions for 0.12.0-dev alignment

- Rename covariant TypeVar to ResultT_co and restore covariant=True in
  protocols.result to satisfy Ruff PLC0105 and preserve p.Result variance.
- Resolve merge conflict in root .mise.toml beads tool pin.
- Replace unsafe model_dump override in DecoratorConfig with mp.PlainSerializer
  for middleware so JSON dumps remain JsonValue-compatible without manual
  mutation of immutable mappings.
- Tighten result construction/transform/composition typing and update tests
  for mypy var-annotated and structural subtyping checks.
- Bump internal version metadata and regenerate examples/typings artifacts.

make check and make test pass (2625 tests) in flext-core.
Only the principal workspace root owns a Beads ledger (issue-prefix
'mro'); a member must not carry .beads/ state. The tracked ledger here
was an empty accidental init (0 issues) and made workspace conform fail
closed with 'standalone project must not own Beads state'.

Untrack .beads/ and ignore it; the directory is archived on disk as
.beads.bak rather than deleted.
Apply canonical conform output plus the 5 E202 whitespace-before-close-
bracket defects in examples/ex_04_flext_dispatcher.py that the newly
generated per-file-ignores policy correctly stopped masking. Examples
are first-class code, so the defect is fixed at the source rather than
exempted.
@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The change restructures the result implementation and protocols, updates workspace orchestration and CI, tightens service and dispatcher typing, revises project metadata utilities, and adjusts tests, environment configuration, and development tooling.

Changes

Workspace and result architecture

Layer / File(s) Summary
Workspace orchestration and CI
Makefile, .github/workflows/*, ci/docker/*, .mise.toml, .envrc, pyproject.toml, .gitignore, .vscode/settings.json
Standalone setup, managed gitlink reconciliation, external uv resolution, multi-platform CI, Docker bootstrap images, tool pins, environment activation, ignore rules, and project configuration are updated.
Result contracts and type migration
src/flext_core/_protocols/result.py, src/flext_core/_protocols/handler.py, src/flext_core/_typings/services.py, src/flext_core/_exceptions/_factories_parts/*, examples/*
Result protocols are defined directly, ResultLike contracts are narrowed to Result, service and handler aliases are updated, and examples use the r result alias and boolean activation values.
Result implementation layers
src/flext_core/_result/*, src/flext_core/result.py
Result construction, behavior, transformations, composition, unwrapping, and public class wiring are split into dedicated implementation modules.
Runtime and utility integration
src/flext_core/_utilities/*, src/flext_core/_runtime/*, src/flext_core/_settings.py, src/flext_core/__version__.py
Project metadata parsing, enforcement discovery, dispatcher normalization, dependency wiring, settings declarations, and internal result imports are updated.
Validation and supporting updates
tests/*
Tests add explicit result and scan annotations, update middleware serialization and result behavior expectations, revise service test doubles, and remove obsolete metadata and exception-hierarchy checks.

Estimated code review effort: 5 (Critical) | ~120 minutes

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 27.88% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title identifies the 0.12.0 development target but does not describe the primary result-system refactor or CI and tooling changes. Use a concise descriptive title, such as "Refactor result system and update 0.12.0 development tooling".
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 0.12.0-dev

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.

pass

@overload
def __or__(self, default: T) -> T: ...
@overload
def __or__(self, default: T) -> T: ...
@overload
def __or__[D](self, default: D) -> T | D: ...
def dispatch_message(
self, message: p.Routable, operation: str = ...
) -> pr.ResultLike[t.JsonPayload] | t.JsonPayload | None: ...
) -> pr.Result[t.JsonPayload] | t.JsonPayload | None: ...
def handle(
self, message: p.Routable
) -> pr.ResultLike[t.JsonPayload] | t.JsonPayload | None: ...
) -> pr.Result[t.JsonPayload] | t.JsonPayload | None: ...
def execute(
self, message: p.Routable
) -> pr.ResultLike[t.JsonPayload] | t.JsonPayload | None: ...
) -> pr.Result[t.JsonPayload] | t.JsonPayload | None: ...
@runtime_checkable
class FailureLike(Protocol):
@property
def error(self) -> str | None: ...
@property
def error(self) -> str | None: ...
@property
def error_code(self) -> str | None: ...
@property
def error_code(self) -> str | None: ...
@property
def error_data(self) -> t.JsonMapping | None: ...
@property
def error_data(self) -> t.JsonMapping | None: ...
@property
def exception(self) -> BaseException | None: ...
@property
def exception(self) -> BaseException | None: ...
@property
def failure(self) -> bool: ...

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 15

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/flext_core/_runtime/_dependency_bindings.py (1)

166-180: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Forward configured packages to the wiring call.

packages is accepted but discarded, while src/flext_core/_utilities/model_runtime.py passes wire_packages here. Package-only wiring therefore does nothing.

Proposed fix
-        _ = packages
-        wiring.wire(container, modules=modules_to_wire or None, packages=None)
+        wiring.wire(
+            container,
+            modules=modules_to_wire or None,
+            packages=packages,
+        )
#!/bin/bash
set -euo pipefail

rg -n -C3 'wiring\.wire\(' src/flext_core/_runtime/_dependency_bindings.py
rg -n -C3 'wire_packages|packages=' src/flext_core/_utilities/model_runtime.py tests
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/flext_core/_runtime/_dependency_bindings.py` around lines 166 - 180,
Update the dependency-wiring function containing modules_to_wire to forward the
configured packages argument to wiring.wire instead of discarding it. Preserve
the existing module and class-derived module handling, and ensure package-only
configuration from model_runtime.py’s wire_packages reaches the wiring call.
🧹 Nitpick comments (9)
Makefile (1)

409-421: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Bootstrap downloads and executes a release binary with no integrity check.

curl -fsSL "$$url"chmod +xmv trusts TLS alone; the post-install --version compare only reads what the downloaded binary reports about itself, so a substituted/corrupted asset still passes. mise publishes per-asset checksums alongside releases; verifying one before mv closes this bootstrap supply-chain gap. Also, the curl failure branch at Line 413 exits silently — add a message with the URL to make CI failures diagnosable.

Note: this file is a generated projection (@flext-managed), so the fix belongs in the flext-infra Makefile.j2 SSOT.

#!/bin/bash
# Confirm mise publishes checksum assets for the pinned release
ver=$(grep -E '^MISE_VERSION *:=' Makefile | awk -F':= *' '{print $2}' | tr -d ' ')
echo "pinned mise version: $ver"
curl -fsSL "https://api.github.com/repos/jdx/mise/releases/tags/v$ver" \
  | jq -r '.assets[].name' | grep -iE 'sha|sig|checksum' | head -20
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Makefile` around lines 409 - 421, Update the flext-infra Makefile.j2 source
template, not the generated Makefile, to verify the downloaded mise asset
against the release-published checksum before chmod/mv or execution. Preserve
the existing temporary-file flow and version validation, and add an error
message including $$url in the curl failure branch before exiting.
src/flext_core/_models/handler.py (1)

170-177: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

when_used="always" breaks python-mode round-tripping of middleware.

With always, model_dump() (python mode) also yields ["pkg.mod.MyMiddleware", ...], so DecoratorConfig.model_validate(config.model_dump()) can no longer reconstruct the field (str is not type[p.Middleware]), and any consumer that inspected the actual classes from a python dump now gets strings. If the intent is only human/JSON-readable output, when_used="json" preserves python-mode fidelity while giving the same JSON shape.

♻️ Restrict stringification to JSON serialization
             mp.PlainSerializer(
                 lambda value: [
                     f"{middleware_type.__module__}.{middleware_type.__qualname__}"
                     for middleware_type in value
                 ],
                 return_type=list[str],
-                when_used="always",
+                when_used="json",
             ),

Worth confirming no code path re-validates a python-mode dump of DecoratorConfig.

#!/bin/bash
# Look for round-trip usage of DecoratorConfig dumps and middleware consumption
rg -nP -C3 'DecoratorConfig' --type=py | head -60
rg -nP -C3 '\bmiddleware\b' --type=py -g '!**/.venv/**' | head -60
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/flext_core/_models/handler.py` around lines 170 - 177, Update the
PlainSerializer in the middleware field configuration to use JSON-only
serialization instead of applying stringification in all modes. Preserve JSON
output as fully qualified middleware class-name strings while keeping
python-mode dumps as the original middleware classes for validation and
consumers.
src/flext_core/_protocols/result.py (1)

11-11: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

mp is only needed for a lazily-evaluated bound — consider moving it under TYPE_CHECKING.

FlextModelsPydantic is used solely in to_model[U: mp.BaseModel] (Line 124); PEP 695 type-parameter bounds are evaluated lazily, so this eager import of the models layer from the protocols layer buys nothing at runtime while adding a protocols→models dependency edge (and cycle exposure) plus import cost. m and t are already handled that way.

♻️ Move the models import into the type-checking block
-from flext_core._models.pydantic import FlextModelsPydantic as mp
-
 ResultT_co = TypeVar("ResultT_co", covariant=True)

 if TYPE_CHECKING:
     from collections.abc import Callable
     from types import TracebackType

+    from flext_core._models.pydantic import FlextModelsPydantic as mp
     from flext_core._typings.base import FlextTypingBase as t
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/flext_core/_protocols/result.py` at line 11, Move the FlextModelsPydantic
import for alias mp from the module-level runtime imports into the existing
TYPE_CHECKING block, while preserving its use as the bound in to_model[U:
mp.BaseModel]. Keep the runtime protocol behavior and the existing m and t
type-only import handling unchanged.
.mise.toml (1)

6-15: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Python pin loosened from 3.13.11 to 3.13 in both pin files. Same root cause: the interpreter is now resolved to an arbitrary latest 3.13.x while every other tool in .mise.toml remains patch-pinned, so bootstrapped environments can differ between developers and CI runs.

  • .mise.toml#L6-L15: restore a patch-level python pin (or document why the minor-only pin is intentional given the exact pins for uv, taplo, ast-grep, gitleaks, tokei).
  • .python-version#L1-L1: keep this file in lockstep with the .mise.toml pin granularity so uv and mise resolve the identical interpreter.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.mise.toml around lines 6 - 15, Restore a patch-level Python pin in
.mise.toml, matching the repository’s pinned interpreter version, and update
.python-version to the identical patch-level value; keep both files in lockstep
so mise and uv resolve the same deterministic interpreter.
pyproject.toml (1)

57-65: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Consolidate duplicate dependency constraints.

pyrefly and pytest are each declared twice, and yamlfix adds another constraint alongside an existing bounded declaration. Keep one intentional specification per tool in the SSOT; otherwise resolution and regeneration can drift.

Also applies to: 106-106

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pyproject.toml` around lines 57 - 65, Consolidate the duplicate dependency
entries in the project’s tool dependency list: keep exactly one intentional
constraint for pyrefly and pytest, and merge yamlfix’s duplicate constraints
into its existing bounded declaration. Preserve the intended version bounds
while removing redundant specifications from the SSOT.
ci/docker/alpine.Dockerfile (1)

4-4: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Run the CI image as a non-root user.

No USER is declared, so bootstrap and smoke commands run as root. Create a dedicated user, chown /workspace, and switch to it before the default command.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ci/docker/alpine.Dockerfile` at line 4, Update the Alpine image definition
around the FROM instruction to create a dedicated non-root user, ensure
/workspace is owned by that user, and declare USER before the default command so
bootstrap and smoke commands execute without root privileges.

Source: Linters/SAST tools

src/flext_core/result.py (1)

17-23: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Redundant base list; FlextResultUnwrap[T] alone is equivalent.

The five layers already form a linear chain (Unwrap → Composition → Transforms → Construction → Behavior), so the explicit list only duplicates the existing linearization — and it will raise an MRO error if that chain is ever reordered.

♻️ Collapse to the topmost layer
-class _FlextResult[T](
-    FlextResultUnwrap[T],
-    FlextResultComposition[T],
-    FlextResultTransforms[T],
-    FlextResultConstruction[T],
-    FlextResultBehavior[T],
-):
+class _FlextResult[T](FlextResultUnwrap[T]):
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/flext_core/result.py` around lines 17 - 23, Update the _FlextResult class
declaration to inherit only from FlextResultUnwrap[T], relying on its existing
inheritance chain instead of listing all five layers explicitly.
src/flext_core/service.py (1)

31-31: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Dropping the p.Base bound weakens the domain-result contract.

With only a default and no upper bound, FlextService[int] / FlextService[str] now type-check, so execute() -> p.Result[TDomainResult] no longer guarantees a structural p.Base payload. tests/base.py line 14 still declares TDomainResult: p.Base = p.Base, leaving the test base stricter than the production kernel. Restore the bound unless a concrete subclass required a non-p.Base payload.

♻️ Restore the bound alongside the default
-class FlextService[TDomainResult = p.Base](x):
+class FlextService[TDomainResult: p.Base = p.Base](x):
#!/bin/bash
# Which payload types are actually parameterized on FlextService / its aliases?
rg -nP --type=py -C2 'FlextService\[' src tests examples
# Declared runtime target for PEP 696 defaults
rg -n 'requires-python|target-version' pyproject.toml
cat .python-version 2>/dev/null
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/flext_core/service.py` at line 31, Update the TDomainResult declaration
on FlextService to retain p.Base as its upper bound while keeping p.Base as the
default, restoring the structural payload contract used by execute(). Verify
concrete FlextService parameterizations remain compatible and do not broaden the
type beyond p.Base.
src/flext_core/_result/behavior.py (1)

32-38: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Silence the SonarCloud "empty method" finding on __exit__.

The no-op __exit__ is intentional (context-manager sugar only), but SonarCloud flags it as a failure requiring either a comment or an implementation.

🔧 Proposed fix
     def __exit__(
         self,
         _exc_type: type[BaseException] | None,
         _exc_val: BaseException | None,
         _exc_tb: object,
     ) -> None:
+        # Intentional no-op: context-manager protocol exists only for `with` ergonomics.
         pass
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/flext_core/_result/behavior.py` around lines 32 - 38, Add an explanatory
comment inside the no-op __exit__ method documenting that it is intentionally
empty because the context manager provides syntax-only behavior, resolving
SonarCloud’s empty-method finding without changing its behavior.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci-matrix.yml:
- Around line 8-12: Update the branch filters in .github/workflows/ci-matrix.yml
lines 8-12 and .github/workflows/ci.yml lines 4-10 to include main for
pull_request events; also include main for push events if these workflows must
run on mainline pushes.
- Around line 33-39: Update the actions/checkout step in the CI matrix workflow
to set persist-credentials to false, while preserving the existing pinned action
reference and Docker build steps.

In `@ci/docker/alpine.Dockerfile`:
- Line 14: Replace the broad COPY instruction in the Alpine Docker build with a
controlled build context: add a suitable .dockerignore excluding repository
metadata, caches, environment files, credentials, and other unnecessary
artifacts, then copy only the project inputs required by the image build.
- Line 16: Update the Alpine bootstrap command containing `mise trust` and `mise
install` so it succeeds on `alpine:3.21`; capture and inspect the complete `mise
install` failure, then adjust the bootstrap prerequisites or invocation to
resolve the reported cause while preserving installation of the configured
tools.
- Around line 23-28: Update the failure handling around the bootstrap command in
the Dockerfile to stop classifying errors via broad “uv.lock” or “flext-core”
substring matches. Recognize the external blocker only through a precise
documented error signature or explicit external-blocker status, and continue
exiting with the original status for all other failures.
- Line 11: Replace the unpinned root-level installer command with a reproducible
mise installation in the Dockerfile: use a trusted pinned base image or package
source, or download a versioned release artifact and verify its checksum or
signature before installation. Keep the resulting mise installation available to
subsequent image build steps.

In `@ci/docker/arch.Dockerfile`:
- Line 18: Install a compatible Rust/Cargo toolchain before the mise
installation command in ci/docker/arch.Dockerfile:18-18,
ci/docker/debian.Dockerfile:19-19, ci/docker/fedora.Dockerfile:18-18, and
ci/docker/ubuntu.Dockerfile:19-19, ensuring mise can provision the
cargo:tokei@14.0.0 dependency in each image.
- Around line 22-31: Remove the broad bare “flext-core” fallback from the make
setup failure handling in ci/docker/arch.Dockerfile lines 22-31,
ci/docker/debian.Dockerfile lines 23-32, ci/docker/fedora.Dockerfile lines
22-31, and ci/docker/ubuntu.Dockerfile lines 23-32. Only soft-pass a uniquely
identified, explicitly accepted lock-boundary error; all other bootstrap
failures must exit with their original status.
- Line 13: Replace the mutable pipe-to-shell Mise installers with the generator
template’s version-pinned installation and checksum- or signature-verification
flow. Apply the same verified installation change at
ci/docker/arch.Dockerfile:13-13, ci/docker/debian.Dockerfile:14-14,
ci/docker/fedora.Dockerfile:13-13, and ci/docker/ubuntu.Dockerfile:14-14.

In `@pyproject.toml`:
- Line 732: Update the pyproject.toml uv configuration by replacing the
open-ended required-version constraint with the tested pinned uv version or an
explicitly bounded range, so untested newer releases are not permitted.

In `@src/flext_core/_result/composition.py`:
- Line 9: Replace package-root imports of c/r with their defining modules to
avoid partially initialized package access: in
src/flext_core/_result/composition.py:9-9 import c from
flext_core._constants.errors; in
src/flext_core/_utilities/parser_coerce.py:13-13 retain c and m if already safe,
but source r from flext_core.result; in
src/flext_core/_utilities/settings.py:23-23 restore r from flext_core.result; in
src/flext_core/dispatcher.py:12-12 remove r from the grouped root import and
import FlextResult as r from flext_core.result; and in
src/flext_core/loggings.py:21-21 remove r from the grouped root import and
source it from flext_core.result.
- Around line 81-86: Update the cleanup handling in the result composition flow
so a cleanup exception does not replace an already failed operation result. When
`result` represents an `op` failure, preserve its message, error code, error
data, and exception; only return the cleanup failure when the operation
otherwise succeeded.

In `@src/flext_core/_result/construction.py`:
- Around line 22-29: Update Result.require_error to allow legitimately empty
failure messages, including error="" produced by fail(None, ...) and
str(exception) for bare exceptions. Preserve failure propagation for downstream
callers such as from_failure, _from_result, and the transform methods by
returning the normalized error value without raising solely because it is empty.

In `@tests/integration/test_migration_validation.py`:
- Around line 172-181: Update test_service_execute_returns_success and its
NoopService docstring to use the r[bool] contract, changing the documented
payload from r[None] to r[bool]. Add an assertion that outcome.value is True,
while preserving the existing success assertion.

In `@tests/unit/test_result_recent_behaviors.py`:
- Around line 121-126: Update test_map_returning_none_reports_success to match
the current map/ok contract: assert the result is successful and verify
result.value is None, while retaining the existing mapping setup.

---

Outside diff comments:
In `@src/flext_core/_runtime/_dependency_bindings.py`:
- Around line 166-180: Update the dependency-wiring function containing
modules_to_wire to forward the configured packages argument to wiring.wire
instead of discarding it. Preserve the existing module and class-derived module
handling, and ensure package-only configuration from model_runtime.py’s
wire_packages reaches the wiring call.

---

Nitpick comments:
In @.mise.toml:
- Around line 6-15: Restore a patch-level Python pin in .mise.toml, matching the
repository’s pinned interpreter version, and update .python-version to the
identical patch-level value; keep both files in lockstep so mise and uv resolve
the same deterministic interpreter.

In `@ci/docker/alpine.Dockerfile`:
- Line 4: Update the Alpine image definition around the FROM instruction to
create a dedicated non-root user, ensure /workspace is owned by that user, and
declare USER before the default command so bootstrap and smoke commands execute
without root privileges.

In `@Makefile`:
- Around line 409-421: Update the flext-infra Makefile.j2 source template, not
the generated Makefile, to verify the downloaded mise asset against the
release-published checksum before chmod/mv or execution. Preserve the existing
temporary-file flow and version validation, and add an error message including
$$url in the curl failure branch before exiting.

In `@pyproject.toml`:
- Around line 57-65: Consolidate the duplicate dependency entries in the
project’s tool dependency list: keep exactly one intentional constraint for
pyrefly and pytest, and merge yamlfix’s duplicate constraints into its existing
bounded declaration. Preserve the intended version bounds while removing
redundant specifications from the SSOT.

In `@src/flext_core/_models/handler.py`:
- Around line 170-177: Update the PlainSerializer in the middleware field
configuration to use JSON-only serialization instead of applying stringification
in all modes. Preserve JSON output as fully qualified middleware class-name
strings while keeping python-mode dumps as the original middleware classes for
validation and consumers.

In `@src/flext_core/_protocols/result.py`:
- Line 11: Move the FlextModelsPydantic import for alias mp from the
module-level runtime imports into the existing TYPE_CHECKING block, while
preserving its use as the bound in to_model[U: mp.BaseModel]. Keep the runtime
protocol behavior and the existing m and t type-only import handling unchanged.

In `@src/flext_core/_result/behavior.py`:
- Around line 32-38: Add an explanatory comment inside the no-op __exit__ method
documenting that it is intentionally empty because the context manager provides
syntax-only behavior, resolving SonarCloud’s empty-method finding without
changing its behavior.

In `@src/flext_core/result.py`:
- Around line 17-23: Update the _FlextResult class declaration to inherit only
from FlextResultUnwrap[T], relying on its existing inheritance chain instead of
listing all five layers explicitly.

In `@src/flext_core/service.py`:
- Line 31: Update the TDomainResult declaration on FlextService to retain p.Base
as its upper bound while keeping p.Base as the default, restoring the structural
payload contract used by execute(). Verify concrete FlextService
parameterizations remain compatible and do not broaden the type beyond p.Base.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a91070d9-2953-4ecb-8a12-48fb658c15c0

📥 Commits

Reviewing files that changed from the base of the PR and between e334cfe and 59453ee.

📒 Files selected for processing (114)
  • .agents/INSTRUCTION_SURFACE.md
  • .agents/skills/rules-cmd.bak-20260725T214500/SKILL.md
  • .beads/.gitignore
  • .beads/README.md
  • .beads/backup/LOCK
  • .beads/backup/backup_state.json
  • .beads/backup/h6mbga66itkhrhtji8j986g8944trmlt.darc
  • .beads/backup/i5r9boc7btoavocdoffrrcnho6dfr995.darc
  • .beads/backup/manifest
  • .beads/backup/mt450ckcsvqtjh4v6ufap2cla4p8bjc9.darc
  • .beads/config.yaml
  • .beads/embeddeddolt/beads/.dolt/config.json
  • .beads/embeddeddolt/beads/.dolt/noms/LOCK
  • .beads/embeddeddolt/beads/.dolt/noms/journal.idx
  • .beads/embeddeddolt/beads/.dolt/noms/manifest
  • .beads/embeddeddolt/beads/.dolt/noms/nbs_manifest_3630928294
  • .beads/embeddeddolt/beads/.dolt/noms/vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
  • .beads/embeddeddolt/beads/.dolt/repo_state.json
  • .beads/embeddeddolt/beads/.dolt/temptf/dolt_embedded_metrics
  • .beads/interactions.jsonl
  • .beads/issues.jsonl
  • .beads/metadata.json
  • .github/workflows/ci-matrix.yml
  • .github/workflows/ci.yml
  • .gitignore
  • .mise.toml
  • .python-version
  • .vscode/settings.json
  • Makefile
  • ci/docker/alpine.Dockerfile
  • ci/docker/arch.Dockerfile
  • ci/docker/debian.Dockerfile
  • ci/docker/fedora.Dockerfile
  • ci/docker/ubuntu.Dockerfile
  • examples/_models/ex00.py
  • examples/ex_04_flext_dispatcher.py
  • examples/typings.py
  • pyproject.toml
  • src/flext_core/__version__.py
  • src/flext_core/_decorators/_railway.py
  • src/flext_core/_exceptions/_factories_parts/flextexceptionsfactories_part_01.py
  • src/flext_core/_exceptions/_factories_parts/flextexceptionsfactories_part_02.py
  • src/flext_core/_exceptions/_factories_parts/flextexceptionsfactories_part_03.py
  • src/flext_core/_exceptions/_factories_parts/flextexceptionsfactories_part_04.py
  • src/flext_core/_models/handler.py
  • src/flext_core/_protocols/_result_parts/flextprotocolsresult_part_01.py
  • src/flext_core/_protocols/_result_parts/flextprotocolsresult_part_02.py
  • src/flext_core/_protocols/_result_parts/flextprotocolsresult_part_03.py
  • src/flext_core/_protocols/_result_parts/flextprotocolsresult_part_04.py
  • src/flext_core/_protocols/handler.py
  • src/flext_core/_protocols/result.py
  • src/flext_core/_result/__init__.py
  • src/flext_core/_result/base.py
  • src/flext_core/_result/behavior.py
  • src/flext_core/_result/composition.py
  • src/flext_core/_result/construction.py
  • src/flext_core/_result/transforms.py
  • src/flext_core/_result/unwrap.py
  • src/flext_core/_result_parts/__init__.py
  • src/flext_core/_result_parts/behavior.py
  • src/flext_core/_result_parts/construction.py
  • src/flext_core/_result_parts/transforms.py
  • src/flext_core/_runtime/_dependency_bindings.py
  • src/flext_core/_settings.py
  • src/flext_core/_typings/services.py
  • src/flext_core/_utilities/_checker_parts/checker_part_02.py
  • src/flext_core/_utilities/_checker_parts/checker_part_03.py
  • src/flext_core/_utilities/_enforcement_collect_parts/enforcement_collect_part_01.py
  • src/flext_core/_utilities/_guards_type_protocol_types.py
  • src/flext_core/_utilities/_mapper_access_parts/mapper_access_part_01.py
  • src/flext_core/_utilities/args.py
  • src/flext_core/_utilities/config.py
  • src/flext_core/_utilities/dispatcher_execute.py
  • src/flext_core/_utilities/handler.py
  • src/flext_core/_utilities/mapper.py
  • src/flext_core/_utilities/model_runtime.py
  • src/flext_core/_utilities/parser_coerce.py
  • src/flext_core/_utilities/project_metadata.py
  • src/flext_core/_utilities/settings.py
  • src/flext_core/dispatcher.py
  • src/flext_core/loggings.py
  • src/flext_core/result.py
  • src/flext_core/service.py
  • tests/base.py
  • tests/integration/test_architecture.py
  • tests/integration/test_documented_patterns.py
  • tests/integration/test_integration.py
  • tests/integration/test_migration_validation.py
  • tests/integration/test_system.py
  • tests/protocols.py
  • tests/unit/_utilities/test_mapper.py
  • tests/unit/test_coverage_loggings.py
  • tests/unit/test_deprecation_warnings.py
  • tests/unit/test_enforcement_namespace_part_02.py
  • tests/unit/test_exceptions_structured_contracts.py
  • tests/unit/test_handler_decorator_discovery.py
  • tests/unit/test_handler_decorator_edges.py
  • tests/unit/test_handler_discovery_class.py
  • tests/unit/test_loggings_full_coverage.py
  • tests/unit/test_models_base_full_coverage.py
  • tests/unit/test_public_api_contract.py
  • tests/unit/test_result.py
  • tests/unit/test_result_callables_fold.py
  • tests/unit/test_result_chain_helpers.py
  • tests/unit/test_result_laws.py
  • tests/unit/test_result_recent_behaviors.py
  • tests/unit/test_result_transforms.py
  • tests/unit/test_service.py
  • tests/unit/test_service_registration_spec.py
  • tests/unit/test_typings_aliases.py
  • tests/unit/test_utilities_project_metadata.py
  • tests/unit/test_utilities_project_metadata_read.py
  • tests/unit/test_utilities_runtime_violation_registry_coverage_100.py
  • tests/unit/test_version.py
💤 Files with no reviewable changes (21)
  • .beads/embeddeddolt/beads/.dolt/config.json
  • .beads/embeddeddolt/beads/.dolt/noms/manifest
  • .beads/README.md
  • .beads/backup/manifest
  • .agents/INSTRUCTION_SURFACE.md
  • .beads/embeddeddolt/beads/.dolt/repo_state.json
  • .beads/.gitignore
  • .beads/backup/backup_state.json
  • src/flext_core/_protocols/_result_parts/flextprotocolsresult_part_04.py
  • .beads/config.yaml
  • .beads/metadata.json
  • .beads/embeddeddolt/beads/.dolt/noms/nbs_manifest_3630928294
  • .agents/skills/rules-cmd.bak-20260725T214500/SKILL.md
  • src/flext_core/_result_parts/behavior.py
  • src/flext_core/_result_parts/init.py
  • src/flext_core/_protocols/_result_parts/flextprotocolsresult_part_03.py
  • src/flext_core/_protocols/_result_parts/flextprotocolsresult_part_02.py
  • src/flext_core/_result_parts/transforms.py
  • src/flext_core/_result_parts/construction.py
  • src/flext_core/_protocols/_result_parts/flextprotocolsresult_part_01.py
  • tests/unit/test_utilities_project_metadata.py

Comment thread .github/workflows/ci-matrix.yml Outdated
Comment on lines +8 to +12
on:
push:
branches: [0.12.0-dev]
pull_request:
branches: [0.12.0-dev]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Restore CI coverage for the main PR target.

PR #341 targets main, but both workflows only match 0.12.0-dev; therefore neither workflow runs for this PR.

  • .github/workflows/ci-matrix.yml#L8-L12: include main in the pull_request branch filter (and in push if mainline pushes require this workflow).
  • .github/workflows/ci.yml#L4-L10: include main in the pull_request branch filter (and in push if mainline pushes require this workflow).
📍 Affects 2 files
  • .github/workflows/ci-matrix.yml#L8-L12 (this comment)
  • .github/workflows/ci.yml#L4-L10
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci-matrix.yml around lines 8 - 12, Update the branch
filters in .github/workflows/ci-matrix.yml lines 8-12 and
.github/workflows/ci.yml lines 4-10 to include main for pull_request events;
also include main for push events if these workflows must run on mainline
pushes.

Comment thread .github/workflows/ci-matrix.yml Outdated
Comment on lines +33 to +39
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Build ${{ matrix.distro }} image
run: >-
docker build
-f ci/docker/${{ matrix.distro }}.Dockerfile
-t ci-matrix-${{ matrix.distro }}
.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== workflow file =="
cat -n .github/workflows/ci-matrix.yml | sed -n '1,120p'

echo
echo "== usages of persist-credentials and checkout context in workflow =="
rg -n "persist-credentials|actions/checkout|checkout\\.|GITHUB_TOKEN|git " .github/workflows -S || true

echo
echo "== workflow files mentioning checkout context usage =="
rg -n "github\\.event|github.sha|checkout/shallow|baseRef|commit_sha|submodules|ssh-keys|persist-credentials" .github/workflows -S || true

Repository: flext-sh/flext-core

Length of output: 1927


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== workflow file =="
cat -n .github/workflows/ci-matrix.yml | sed -n '1,160p'

echo
echo "== actions/checkout steps with context in workflows =="
python3 - <<'PY'
from pathlib import Path
for p in Path('.github/workflows').glob('*.yml'):
    text = p.read_text()
    if 'actions/checkout@' in text:
        print(f'--- {p} ---')
        for i,line in enumerate(text.splitlines(), 1):
            if 'actions/checkout@' in line or 'persist-credentials' in line:
                start=max(1,i-8); end=min(len(text.splitlines()), i+14)
                lines=text.splitlines()
                for n in range(start,end+1):
                    print(f'{n:4}: {lines[n-1]}')
                print()
PY

echo
echo "== checkout with persist-credentials: false present? =="
rg -n "persist-credentials:\s*false" .github/workflows || true

Repository: flext-sh/flext-core

Length of output: 1927


Disable persisted checkout credentials.

This job’s Docker builds only need the repository context; there is no authenticated Git access after checkout. Set persist-credentials: false for the checkout step.

Proposed change
         with:
+          persist-credentials: false
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Build ${{ matrix.distro }} image
run: >-
docker build
-f ci/docker/${{ matrix.distro }}.Dockerfile
-t ci-matrix-${{ matrix.distro }}
.
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Build ${{ matrix.distro }} image
run: >-
docker build
-f ci/docker/${{ matrix.distro }}.Dockerfile
-t ci-matrix-${{ matrix.distro }}
.
🧰 Tools
🪛 zizmor (1.28.0)

[warning] 33-33: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci-matrix.yml around lines 33 - 39, Update the
actions/checkout step in the CI matrix workflow to set persist-credentials to
false, while preserving the existing pinned action reference and Docker build
steps.

Source: Linters/SAST tools


# mise installs the supported Python 3.13 family.
# uv is supplied by the managed environment without a project patch pin.
RUN curl -fsSL https://mise.run | sh

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate Dockerfile =="
git ls-files | rg '(^|/)ci/docker/alpine\.Dockerfile$|Dockerfile$' || true

echo "== target file =="
if [ -f ci/docker/alpine.Dockerfile ]; then
  nl -ba ci/docker/alpine.Dockerfile | sed -n '1,80p'
fi

echo "== curl/pipe occurrences in Dockerfiles =="
rg -n '\bcurl\s+.*\|\s*(sudo\s+)?sh\b|\bcurl\s+.*\|\s*bash\b|\bcurl\s+.*\|\s*sh\s+-s\b|\bcurl\s+.*\|\s*sh\s+' ci/docker Dockerfile .github 2>/dev/null || true

Repository: flext-sh/flext-core

Length of output: 1927


🌐 Web query:

mise.run installer curl https://mise.run/sh install script redirect curlfsSLL

💡 Result:

To install the mise CLI on macOS or Linux, you can use the official installer script provided at mise.run [1][2]. The standard method for installation is to pipe the output of the curl command into sh [1][3]: curl https://mise.run | sh This command downloads and executes an installer script [4][5], which by default installs the mise binary to ~/.local/bin/mise [6][1]. Shell-Specific Installers For a more streamlined setup, the project provides shell-specific endpoints that install mise and automatically append the necessary activation line to your shell's configuration file (e.g., ~/.zshrc, ~/.bashrc, or ~/.config/fish/config.fish) [1][7]: curl https://mise.run/zsh | sh curl https://mise.run/bash | sh curl https://mise.run/fish | sh Configuration Options You can customize the installation by setting environment variables before running the command [1][7]. Common options include: MISE_INSTALL_PATH=/some/path: Specifies the directory where the mise binary will be installed (default is ~/.local/bin/mise) [1][7]. MISE_VERSION=v202X.X.X: Installs a specific version of mise [1][7]. MISE_INSTALL_SKIP_IF_EXISTS=1: Skips the installation if the binary already exists at the target path and matches the version [1][7]. While your query mentioned curlfsSLL, the standard practice for this installer is using curl -fsSL [5]. The -fsSL flags are recommended to ensure the script runs quietly, fails on server errors, and follows redirects: curl -fsSL https://mise.run | sh [5] For security-conscious environments, you can also verify the installation by downloading the signature file and verifying it with GPG before executing the script [7].

Citations:


🌐 Web query:

site:github.com/jdx/mise "curl" "https://mise.run" "signature" "GPG"

💡 Result:

The command curl https://mise.run | sh is the standard method for installing mise [1][2]. This process installs the binary directly and does not involve a GPG signature verification of the installation script itself [1]. Regarding GPG signature verification in mise: 1. Software Verification: Mise handles security verification differently depending on the tool being installed. For tools using the aqua backend, mise provides native, automatic verification using methods like Cosign, Minisign, SLSA provenance, and GitHub attestations, requiring no external dependencies [1][2]. 2. GPG Verification: For tools that require GPG (such as Node.js), mise historically relied on the gpg binary installed on the system [3][4]. However, recent updates have moved toward native in-process verification using the rPGP crate to reduce external dependencies [5]. 3. Configuration: Verification for tools is enabled by default [5]. If you encounter issues with GPG verification, you can disable it for a specific operation using the MISE_GPG_VERIFY=false environment variable (e.g., MISE_GPG_VERIFY=false mise use --global node@24) [6][3]. Alternatively, verify that your system GPG configuration is not blocking required algorithms or causing conflicts [4][7]. For official installation instructions, always refer to the documentation at https://mise.run.

Citations:


Avoid running the unpinned mise installer as root.

curl -fsSL https://mise.run | sh fetches mutable install script code and executes it in the image build without checksum/signature verification. Use a reproducible install method: pin a trusted Docker/base image or package manager source, or download/checksum/signature-verify a versioned release artifact before installing mise.

🧰 Tools
🪛 GitHub Check: SonarCloud Code Analysis

[failure] 11-11: Avoid executing downloaded artifacts directly without verification.

See more on https://sonarcloud.io/project/issues?id=flext-sh_flext-core&issues=AZ-zxe3O9mhqhps4gQrS&open=AZ-zxe3O9mhqhps4gQrS&pullRequest=341


[warning] 11-11: Not enforcing HTTPS here might allow for redirections to insecure websites. Make sure it is safe here.

See more on https://sonarcloud.io/project/issues?id=flext-sh_flext-core&issues=AZ-zxe3O9mhqhps4gQrT&open=AZ-zxe3O9mhqhps4gQrT&pullRequest=341

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ci/docker/alpine.Dockerfile` at line 11, Replace the unpinned root-level
installer command with a reproducible mise installation in the Dockerfile: use a
trusted pinned base image or package source, or download a versioned release
artifact and verify its checksum or signature before installation. Keep the
resulting mise installation available to subsequent image build steps.

Source: Linters/SAST tools

RUN curl -fsSL https://mise.run | sh
ENV PATH="/root/.local/bin:/root/.local/share/mise/shims:${PATH}"
WORKDIR /workspace
COPY . .

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

Avoid copying the entire checkout into the image.

.gitignore does not control the Docker build context, so COPY . . can bake .git, caches, environment files, or credentials into image layers. Add a suitable .dockerignore and copy only required project inputs.

🧰 Tools
🪛 GitHub Check: SonarCloud Code Analysis

[failure] 14-14: Copying recursively might inadvertently add sensitive data to the container. Make sure it is safe here.

See more on https://sonarcloud.io/project/issues?id=flext-sh_flext-core&issues=AZ-zxe3O9mhqhps4gQrP&open=AZ-zxe3O9mhqhps4gQrP&pullRequest=341

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ci/docker/alpine.Dockerfile` at line 14, Replace the broad COPY instruction
in the Alpine Docker build with a controlled build context: add a suitable
.dockerignore excluding repository metadata, caches, environment files,
credentials, and other unnecessary artifacts, then copy only the project inputs
required by the image build.

Source: Linters/SAST tools

Comment thread tests/fixtures/ci/docker/alpine.Dockerfile
from pydantic import ValidationError

from flext_core._constants.errors import FlextConstantsErrors as c
from flext_core import c

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

flext_core submodules now resolve c/r through the package root instead of their defining modules. Each of these modules is imported (directly or transitively) by flext_core/__init__.py, so from flext_core import ... executes against a partially initialized package and only works while __init__.py happens to bind those names early enough. Import the defining module in each case; src/flext_core/_result/unwrap.py line 7 already shows the pattern.

  • src/flext_core/_result/composition.py#L9-L9: replace from flext_core import c with from flext_core._constants.errors import FlextConstantsErrors as c.
  • src/flext_core/_utilities/parser_coerce.py#L13-L13: keep c, m as-is if already proven safe, but source r from flext_core.result again.
  • src/flext_core/_utilities/settings.py#L23-L23: restore from flext_core.result import r alongside the protocol/type imports.
  • src/flext_core/dispatcher.py#L12-L12: drop r from the grouped root import and restore from flext_core.result import FlextResult as r.
  • src/flext_core/loggings.py#L21-L21: drop r from the grouped root import and source it from flext_core.result (this module initializes earliest, so it is the most exposed).
#!/bin/bash
# Import order in the package root vs. submodules that import from it
rg -n '^(from|import) ' src/flext_core/__init__.py | head -60
rg -n 'from flext_core import' src/flext_core --type=py
📍 Affects 5 files
  • src/flext_core/_result/composition.py#L9-L9 (this comment)
  • src/flext_core/_utilities/parser_coerce.py#L13-L13
  • src/flext_core/_utilities/settings.py#L23-L23
  • src/flext_core/dispatcher.py#L12-L12
  • src/flext_core/loggings.py#L21-L21
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/flext_core/_result/composition.py` at line 9, Replace package-root
imports of c/r with their defining modules to avoid partially initialized
package access: in src/flext_core/_result/composition.py:9-9 import c from
flext_core._constants.errors; in
src/flext_core/_utilities/parser_coerce.py:13-13 retain c and m if already safe,
but source r from flext_core.result; in
src/flext_core/_utilities/settings.py:23-23 restore r from flext_core.result; in
src/flext_core/dispatcher.py:12-12 remove r from the grouped root import and
import FlextResult as r from flext_core.result; and in
src/flext_core/loggings.py:21-21 remove r from the grouped root import and
source it from flext_core.result.

Comment on lines 81 to 86
if cleanup:
try:
cleanup(resource)
except c.CATCHABLE_RUNTIME_EXCEPTIONS as exc:
return result_class.fail(str(exc), exception=exc)
return cls.fail(str(exc), exception=exc)
return result

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Cleanup failure masks the primary op failure.

If op already failed and cleanup then raises, the returned result carries only the cleanup error; the original error message, error_code, error_data, and exception are dropped.

🐛 Preserve the primary failure
         if cleanup:
             try:
                 cleanup(resource)
             except c.CATCHABLE_RUNTIME_EXCEPTIONS as exc:
-                return cls.fail(str(exc), exception=exc)
+                if result.failure:
+                    return result
+                return cls.fail(str(exc), exception=exc)
         return result
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if cleanup:
try:
cleanup(resource)
except c.CATCHABLE_RUNTIME_EXCEPTIONS as exc:
return result_class.fail(str(exc), exception=exc)
return cls.fail(str(exc), exception=exc)
return result
if cleanup:
try:
cleanup(resource)
except c.CATCHABLE_RUNTIME_EXCEPTIONS as exc:
if result.failure:
return result
return cls.fail(str(exc), exception=exc)
return result
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/flext_core/_result/composition.py` around lines 81 - 86, Update the
cleanup handling in the result composition flow so a cleanup exception does not
replace an already failed operation result. When `result` represents an `op`
failure, preserve its message, error code, error data, and exception; only
return the cleanup failure when the operation otherwise succeeded.

Comment on lines +22 to +29
@staticmethod
def require_error(source: p.FailureLike) -> str:
"""Extract error message from any failed Result."""
error = source.error
if not error:
msg = c.ERR_RESULT_FAILURE_MESSAGE_REQUIRED
raise ValueError(msg)
return error

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

require_error raises on legitimately-empty failure messages.

fail(None, ...) normalizes to error="" (line 110), and a bare exception (raise ValueError()) caught by map/flat_map/filter/tap/create_from_callable produces str(exc) == "" via cls.fail(str(exc), exception=exc). Any later require_error() call on such a failed result (used by from_failure, _from_result, and — per transforms.py — flat_map, map, map_error, fold, lash, tap_error, to_model) will then raise an unrelated ValueError instead of propagating the failure, breaking the railway chain's fail-safety guarantee.

🐛 Proposed fix
     `@staticmethod`
     def require_error(source: p.FailureLike) -> str:
         """Extract error message from any failed Result."""
         error = source.error
-        if not error:
+        if error is None:
             msg = c.ERR_RESULT_FAILURE_MESSAGE_REQUIRED
             raise ValueError(msg)
         return error
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@staticmethod
def require_error(source: p.FailureLike) -> str:
"""Extract error message from any failed Result."""
error = source.error
if not error:
msg = c.ERR_RESULT_FAILURE_MESSAGE_REQUIRED
raise ValueError(msg)
return error
`@staticmethod`
def require_error(source: p.FailureLike) -> str:
"""Extract error message from any failed Result."""
error = source.error
if error is None:
msg = c.ERR_RESULT_FAILURE_MESSAGE_REQUIRED
raise ValueError(msg)
return error
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/flext_core/_result/construction.py` around lines 22 - 29, Update
Result.require_error to allow legitimately empty failure messages, including
error="" produced by fail(None, ...) and str(exception) for bare exceptions.
Preserve failure propagation for downstream callers such as from_failure,
_from_result, and the transform methods by returning the normalized error value
without raising solely because it is empty.

Comment on lines 172 to 181
def test_service_execute_returns_success(self) -> None:
"""A concrete FlextService.execute honors the r[None] contract."""

class NoopService(FlextService[None]):
class NoopService(FlextService[bool]):
@override
def execute(self, **_kwargs: t.Scalar) -> p.Result[None]:
return r[None].ok(None)
def execute(self, **_kwargs: t.Scalar) -> p.Result[bool]:
return r[bool].ok(True)

outcome = NoopService().execute()
tm.that(outcome.success, eq=True)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Assert the new bool service payload.

The test double now returns r[bool].ok(True), but the test only checks success and absence of an error. It would still pass if execute() returned False; also update the docstring at Line 173 from r[None] to r[bool].

Proposed test fix
-        """A concrete FlextService.execute honors the r[None] contract."""
+        """A concrete FlextService.execute honors the r[bool] contract."""
...
         tm.that(outcome.success, eq=True)
+        tm.that(outcome.value, eq=True)
         tm.that(outcome.error, none=True)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def test_service_execute_returns_success(self) -> None:
"""A concrete FlextService.execute honors the r[None] contract."""
class NoopService(FlextService[None]):
class NoopService(FlextService[bool]):
@override
def execute(self, **_kwargs: t.Scalar) -> p.Result[None]:
return r[None].ok(None)
def execute(self, **_kwargs: t.Scalar) -> p.Result[bool]:
return r[bool].ok(True)
outcome = NoopService().execute()
tm.that(outcome.success, eq=True)
def test_service_execute_returns_success(self) -> None:
"""A concrete FlextService.execute honors the r[bool] contract."""
class NoopService(FlextService[bool]):
`@override`
def execute(self, **_kwargs: t.Scalar) -> p.Result[bool]:
return r[bool].ok(True)
outcome = NoopService().execute()
tm.that(outcome.success, eq=True)
tm.that(outcome.value, eq=True)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/integration/test_migration_validation.py` around lines 172 - 181,
Update test_service_execute_returns_success and its NoopService docstring to use
the r[bool] contract, changing the documented payload from r[None] to r[bool].
Add an assertion that outcome.value is True, while preserving the existing
success assertion.

Comment on lines +121 to +126
def test_map_returning_none_reports_success(self) -> None:
"""``map`` producing ``None`` yields a success with a ``None`` payload."""
"""``map`` producing ``None`` is rejected and returns failure."""
result: p.Result[None] = r[str].ok("x").map(lambda _: None)

assert result.success is True
assert result.failure is True
assert result.error is not None

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Align this test with the current map contract.

Based on src/flext_core/_result/transforms.py:82-93 and src/flext_core/_result/construction.py:147-150, mapping None currently returns a successful result carrying None. Lines 125-126 therefore assert the opposite behavior and will fail. Either change map/ok to reject None, or update this test to assert success and result.value is None.

Proposed test alignment
-    def test_map_returning_none_reports_success(self) -> None:
-        """``map`` producing ``None`` is rejected and returns failure."""
+    def test_map_returning_none_preserves_none_value(self) -> None:
+        """``map`` may produce a successful ``None`` payload."""
         result: p.Result[None] = r[str].ok("x").map(lambda _: None)

-        assert result.failure is True
-        assert result.error is not None
+        assert result.success is True
+        assert result.value is None
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def test_map_returning_none_reports_success(self) -> None:
"""``map`` producing ``None`` yields a success with a ``None`` payload."""
"""``map`` producing ``None`` is rejected and returns failure."""
result: p.Result[None] = r[str].ok("x").map(lambda _: None)
assert result.success is True
assert result.failure is True
assert result.error is not None
def test_map_returning_none_preserves_none_value(self) -> None:
"""``map`` may produce a successful ``None`` payload."""
result: p.Result[None] = r[str].ok("x").map(lambda _: None)
assert result.success is True
assert result.value is None
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/test_result_recent_behaviors.py` around lines 121 - 126, Update
test_map_returning_none_reports_success to match the current map/ok contract:
assert the result is successful and verify result.value is None, while retaining
the existing mapping setup.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
ci/docker/fedora.Dockerfile (1)

28-37: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Restrict the setup soft-pass to the exact known lock boundary. Matching the generic string flext-core can hide unrelated bootstrap failures.

  • ci/docker/fedora.Dockerfile#L28-L37: replace the output substring check with a precise lock-boundary predicate.
  • ci/docker/ubuntu.Dockerfile#L29-L38: use the same precise predicate.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ci/docker/fedora.Dockerfile` around lines 28 - 37, Restrict the setup
soft-pass condition in ci/docker/fedora.Dockerfile lines 28-37 and
ci/docker/ubuntu.Dockerfile lines 29-38 to a precise uv.lock/flext-core
lock-boundary match, replacing the generic flext-core substring check. Keep
unrelated setup failures propagating their original status in both Dockerfiles.
🧹 Nitpick comments (1)
Makefile (1)

398-401: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

status --porcelain also trips on untracked files.

Setup will hard-fail on any stray untracked file inside a managed gitlink (build outputs, editor scratch files), even though nothing tracked diverges. Consider restricting the dirty check to tracked changes.

♻️ Suggested narrowing
-		if [ -n "$$(git -C "$$child_root" status --porcelain)" ]; then \
+		if [ -n "$$(git -C "$$child_root" status --porcelain --untracked-files=no)" ]; then \
 			printf 'ERROR: %s: local changes must be reconciled before setup\n' "$$child_path" >&2; \
 			exit 1; \
 		fi; \
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Makefile` around lines 398 - 401, Update the dirty-check condition in the
managed gitlink setup flow to detect only tracked modifications, excluding
untracked files from the failure condition. Preserve the existing error message
and exit behavior when tracked changes are present.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@ci/docker/alpine.Dockerfile`:
- Around line 16-17: Add the Alpine musl build dependencies with apk before the
rustup and mise installation steps: install gcc and musl-dev ahead of the RUN
command invoking rustup, while preserving the existing Rust toolchain and PATH
setup.

In `@ci/docker/fedora.Dockerfile`:
- Around line 16-19: Replace the mutable curl-piped installers in
ci/docker/fedora.Dockerfile lines 16-19 and ci/docker/ubuntu.Dockerfile lines
17-20 with pinned uv and Rustup artifacts downloaded at fixed versions and
verified against published checksums before installation; preserve the resulting
uv, Cargo, and mise shim PATH setup in both Dockerfiles.

In `@pyproject.toml`:
- Around line 304-309: Update the Pyrefly search-path configuration to avoid
invalid sibling paths during standalone CI checks. Either provision the
flext-cli, flext-infra, and flext-tests repositories before make check, or
conditionally include their src paths only when they exist, while preserving the
current paths when available.

---

Outside diff comments:
In `@ci/docker/fedora.Dockerfile`:
- Around line 28-37: Restrict the setup soft-pass condition in
ci/docker/fedora.Dockerfile lines 28-37 and ci/docker/ubuntu.Dockerfile lines
29-38 to a precise uv.lock/flext-core lock-boundary match, replacing the generic
flext-core substring check. Keep unrelated setup failures propagating their
original status in both Dockerfiles.

---

Nitpick comments:
In `@Makefile`:
- Around line 398-401: Update the dirty-check condition in the managed gitlink
setup flow to detect only tracked modifications, excluding untracked files from
the failure condition. Preserve the existing error message and exit behavior
when tracked changes are present.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 974c6f2e-9529-409a-bb93-1971132a6fa1

📥 Commits

Reviewing files that changed from the base of the PR and between 59453ee and 0cef39b.

📒 Files selected for processing (13)
  • .envrc
  • .github/workflows/ci-matrix.yml
  • .github/workflows/ci.yml
  • .gitignore
  • .mise.toml
  • .vscode/settings.json
  • Makefile
  • ci/docker/alpine.Dockerfile
  • ci/docker/arch.Dockerfile
  • ci/docker/debian.Dockerfile
  • ci/docker/fedora.Dockerfile
  • ci/docker/ubuntu.Dockerfile
  • pyproject.toml

Comment thread ci/docker/alpine.Dockerfile Outdated
Comment thread ci/docker/fedora.Dockerfile Outdated
Comment on lines +16 to +19
RUN curl -fsSL https://astral.sh/uv/install.sh | sh
# tokei (and any future cargo-backed mise tool) needs a Rust toolchain.
RUN curl -fsSL https://sh.rustup.rs | sh -s -- -y --default-toolchain stable
ENV PATH="/root/.local/bin:/root/.cargo/bin:/root/.local/share/mise/shims:${PATH}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== files =="
git ls-files | grep -E '^ci/docker/(fedora|ubuntu)\.Dockerfile$' || true

for f in ci/docker/fedora.Dockerfile ci/docker/ubuntu.Dockerfile; do
  if [ -f "$f" ]; then
    echo "== $f =="
    nl -ba "$f" | sed -n '1,80p'
  fi
done

echo "== related usage =="
for f in ci/docker/fedora.Dockerfile ci/docker/ubuntu.Dockerfile; do
  [ -f "$f" ] || continue
  echo "== security-related lines in $f =="
  rg -n 'curl |wget |sh -s|--fetch|checksum|sha|uv install|rustup.rs|sed -i|chmod|sudo|apt|dnf|apk|curl --insecure|-k|SKIP|curl .*curl|pip ' -- "$f" || true
done

Repository: flext-sh/flext-core

Length of output: 300


🏁 Script executed:

#!/bin/bash
set -euo pipefail

for f in ci/docker/ubuntu.Dockerfile ci/docker/fedora.Dockerfile; do
  if [ -f "$f" ]; then
    echo "== outline-ish $f =="
    awk '{printf "%4d: %s\n", NR, $0}' "$f" | sed -n '1,120p'
  fi
done

echo "== relevant installer/security lines =="
awk '
  /INSTALL_SOURCES|curl|wget|sh -s|--fetch|--default-toolchain|checksum|sha|uv install|rustup.rs|sed -i|chmod|sudo|apt|dnf|apk|curl --insecure|-k|--silent|--progress/{print FILENAME ":" FNR ":" $0}
' ci/docker/ubuntu.Dockerfile ci/docker/fedora.Dockerfile

Repository: flext-sh/flext-core

Length of output: 5059


Use reproducible, checksum-validated uv and Rust bootstraps. Both Dockerfiles execute mutable installer scripts directly from curl | sh, including uv and Rustup:

  • ci/docker/fedora.Dockerfile:16-18
  • ci/docker/ubuntu.Dockerfile:17-19

Replace those with pinned artifacts using verified downloads/checksums instead of invoking remote scripts at build time.

📍 Affects 2 files
  • ci/docker/fedora.Dockerfile#L16-L19 (this comment)
  • ci/docker/ubuntu.Dockerfile#L17-L20
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ci/docker/fedora.Dockerfile` around lines 16 - 19, Replace the mutable
curl-piped installers in ci/docker/fedora.Dockerfile lines 16-19 and
ci/docker/ubuntu.Dockerfile lines 17-20 with pinned uv and Rustup artifacts
downloaded at fixed versions and verified against published checksums before
installation; preserve the resulting uv, Cargo, and mise shim PATH setup in both
Dockerfiles.

Comment thread pyproject.toml Outdated
Comment on lines +304 to +309
search-path = [
".",
"src",
".",
"../flext-cli/src",
"../flext-infra/src",
"../flext-tests/src",
"src",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

for path in ../flext-cli/src ../flext-infra/src ../flext-tests/src; do
  if [[ -d "$path" ]]; then
    printf 'present: %s\n' "$path"
  else
    printf 'missing: %s\n' "$path"
  fi
done

rg -n -C2 'search-path|flext-(cli|infra|tests)' pyproject.toml .github/workflows/ci.yml

Repository: flext-sh/flext-core

Length of output: 1541


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '--- ci workflow excerpt ---\n'
sed -n '1,220p' .github/workflows/ci.yml

printf '\n--- pyproject pyrefly excerpt ---\n'
sed -n '285,315p' pyproject.toml

printf '\n--- repo tooling / pyrefly docs ---\n'
rg -n 'pyrefly|make check|check\s*=|run\s*=|search-path|pyrefly' . -g '!pyproject.toml' -g '!README.md' || true

Repository: flext-sh/flext-core

Length of output: 248


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- ci workflow excerpt ---'
sed -n '1,220p' .github/workflows/ci.yml

printf '%s\n' ''
printf '%s\n' '--- pyproject pyrefly excerpt ---'
sed -n '285,315p' pyproject.toml

printf '%s\n' ''
printf '%s\n' '--- repo tooling / pyrefly docs references ---'
rg -n 'pyrefly|make check|check\s*=|run\s*=|search-path|pyrefly' . -g '!pyproject.toml' -g '!README.md' || true

Repository: flext-sh/flext-core

Length of output: 11317


🌐 Web query:

Pyrefly 1.1.1 search-path missing directory configuration

💡 Result:

In Pyrefly 1.1.1, the "search-path" configuration option is used to define the root directories from which the tool resolves imports [1][2]. When Pyrefly cannot find a specific directory or module, it is often because the project's import root is not correctly identified or configured [3][4]. To resolve missing directory or import path issues: 1. Explicit Configuration: You can manually set the search path in your project's configuration file (pyproject.toml or pyrefly.toml) under the [tool.pyrefly] section [1][5]. For example: [tool.pyrefly] search-path = ["."] 2. Understand Automatic Heuristics: Pyrefly automatically attempts to infer an "import root" based on your project structure (e.g., looking for a src/ directory or the presence of init.py files) [1][3]. If these heuristics are incorrectly identifying your project layout, you can override them by explicitly setting search-path [6][2]. 3. Disable Heuristics if Needed: If automatic search path discovery is causing conflicts, you can disable these heuristics by setting disable-search-path-heuristics = true in your configuration [1][2]. 4. Check Command-Line Usage: If you need to test a configuration change quickly, you can pass the --search-path flag via the command line (e.g., pyrefly check --search-path=.) to override the default import root [1][6]. If you are encountering errors stating that a module cannot be found, ensure that the path added to search-path points to the directory containing your package root, not just the directory containing the pyproject.toml file [3][4]. For further debugging, ensure that your site-package-path is correctly configured if you are working within a virtual environment [4].

Citations:


🌐 Web query:

facebook pyrefly search-path missing directory error exit code

💡 Result:

When Pyrefly encounters a "missing directory" error—often manifesting as a "could not find import" diagnostic—it typically indicates that the tool's heuristic-based import resolution cannot locate your project files or dependencies [1][2]. Pyrefly commands, such as pyrefly check, return an exit code of 1 when configuration issues, missing files, or type errors are detected [3]. To resolve these errors, you can follow these steps: 1. Understand the Search Path Heuristics Pyrefly automatically adds certain directories (like src/) to your search path if they exist at the project root [1]. If your project structure deviates from these defaults, or if you need to include additional directories, you must manually configure the search-path [4][5]. 2. Configure search-path You can define explicit search paths in your pyproject.toml (under [tool.pyrefly]) or a pyrefly.toml file [5][6]: [tool.pyrefly] search-path = ["src", "."] If you need to disable Pyrefly's default path-guessing behavior to avoid conflicts, use the following configuration [7][4]: [tool.pyrefly] disable-search-path-heuristics = true search-path = ["."] 3. Verify Dependencies and Interpreter If the missing directory involves third-party packages, ensure your site-package-path is correctly configured or that Pyrefly is pointed to the correct Python interpreter [2][8]. You can check this by running python -c "import site; print(site.getsitepackages())" to verify where your packages are installed [8]. 4. CLI Override For quick testing or CI environments, you can override the configuration via the command line [5][3]: pyrefly check --search-path path/to/your/dir If you continue to see errors, verify the exact error message provided by Pyrefly, as it will often explicitly list the locations it checked, helping you identify if the issue is a missing directory, a misconfigured path, or an incorrect environment setting [2][8].

Citations:


🌐 Web query:

"pyrefly" "search-path" "does not exist" configuration

💡 Result:

In Pyrefly, a "does not exist" error related to the search-path configuration occurs when a directory specified in your configuration file or via command-line arguments cannot be found on the filesystem [1][2][3]. When you provide an invalid path to search-path, Pyrefly will issue a warning or error message—often formatted as Invalid --search-path: [path] does not exist—to notify you that the specified location is unreachable [1][2]. To resolve this issue, you should: 1. Verify the path: Check the directory path provided in your configuration file (e.g., pyrefly.toml) or command-line flag [2][3]. Ensure there are no typos and that the directory exists relative to your project root or as an absolute path [4]. 2. Check configuration location: If using a relative path, remember that Pyrefly resolves these paths based on the location of your configuration file [4]. 3. Debugging: You can use pyrefly dump-config to inspect how Pyrefly is currently interpreting your configuration and resolving paths [2][3]. If you wish to allow Pyrefly to operate without strict enforcement of all provided search paths or if you are encountering issues with automatic path resolution, you may want to review the disable-search-path-heuristics setting in your configuration, which controls how Pyrefly automatically constructs the search path [4][5][6].

Citations:


Keep Pyrefly search paths valid in CI.

The sibling paths ../flext-cli/src, ../flext-infra/src, and ../flext-tests/src are absent in standalone checks. Either provision/checkout those repos before make check, or conditionally omit these entries so Pyrefley does not fail when they are missing.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pyproject.toml` around lines 304 - 309, Update the Pyrefly search-path
configuration to avoid invalid sibling paths during standalone CI checks. Either
provision the flext-cli, flext-infra, and flext-tests repositories before make
check, or conditionally include their src paths only when they exist, while
preserving the current paths when available.

Marlon Costa added 2 commits July 30, 2026 21:46
Managed surfaces (.envrc, .mise.toml, CI matrix, docker images, Makefile,
pyproject) regenerated by the current flext-infra conform SSOT and
adopted as-is: the generated header moved from the retired 'workspace
sync' owner to 'flext-infra codegen conform'.
Marlon Costa added 2 commits July 30, 2026 22:05
A concurrent merge reintroduced the retired 'github:gastownhall/beads'
1.1.2 pin, whose binary only knows Dolt schema v53 and fails every
conform preflight against the shared v61 mro ledger. Regenerated from
the flext-infra SSOT (toolchain.beads: go module commit 423afdcb,
reported_version 1.1.0) instead of hand-editing the projection.
The returns library is fully exterminated, but _validate_success_value
survived it. That guard existed solely for the returns convention
(introduced by f607749 as "T cannot be None (returns convention)"),
so it kept rejecting a None payload after its only justification was
deleted, breaking r[None].ok(None) at 34 call sites across 7 packages.

Drop the guard and the last returns import, assign the payload directly,
and narrow it at the single assignment point. Success with no payload is
now representable; failure still leaves _payload unset, so the two states
stay distinguishable.

test_map_returning_none_reports_success asserted the opposite of its own
name: map() never special-cased None, the failure was the guard raising
inside ok() and being swallowed by the broad except. Corrected to the
observed contract.
Copilot AI review requested due to automatic review settings August 1, 2026 00:30

Copilot AI left a comment

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.

Pull request overview

This PR advances the 0.12.0-dev line by refactoring flext_core’s result system into a single covariant p.Result protocol with a concrete r[T] implementation (and None as a valid success payload), while also regenerating project tooling/CI surfaces (Makefile, pyproject, workflows, docker CI matrix) to match the new release environment.

Changes:

  • Refactors FlextResult internals into src/flext_core/_result/ and updates protocols/typings to remove ResultLike in favor of p.Result.
  • Updates utilities and enforcement/project-metadata helpers to use the new result and metadata boundaries.
  • Regenerates dev tooling and CI (Make surface, workflows, docker matrix, editor + env files) for 0.12.0-dev.

Reviewed changes

Copilot reviewed 93 out of 105 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tests/unit/test_version.py Adjusts subclass-creation test.
tests/unit/test_utilities_project_metadata.py Removes now-obsolete document default tests.
tests/unit/test_utilities_project_metadata_read.py Updates result contract wording.
tests/unit/test_service_registration_spec.py Adds casts for typed registration records.
tests/unit/test_result.py Adds None-payload success tests.
tests/unit/test_result_recent_behaviors.py Updates recent result behavior expectations.
tests/unit/test_result_laws.py Adds explicit result type annotations.
tests/unit/test_result_chain_helpers.py Adds explicit result type annotations.
tests/unit/test_result_callables_fold.py Adds explicit result/value type annotations.
tests/unit/test_models_base_full_coverage.py Small hash implementation tweak.
tests/unit/test_loggings_full_coverage.py Migrates ResultLikeResult.
tests/unit/test_handler_decorator_edges.py Updates middleware dump expectation.
tests/unit/test_enforcement_namespace_part_02.py Adds explicit typed local variable.
tests/unit/test_deprecation_warnings.py Adds explicit result type annotations.
tests/unit/test_coverage_loggings.py Migrates ResultLikeResult.
tests/protocols.py Exposes SuccessCheckable alias.
tests/integration/test_system.py Updates result typing in integration tests.
tests/integration/test_migration_validation.py Updates service example payload typing.
tests/integration/test_integration.py Adds explicit result type annotations.
tests/integration/test_documented_patterns.py Adds explicit result type annotations.
tests/integration/test_architecture.py Adds explicit scan result annotations.
tests/base.py Refactors test service base typing.
src/flext_core/service.py Adjusts service generic parameter definition.
src/flext_core/result.py Rebuilds FlextResult facade on new parts.
src/flext_core/loggings.py Switches to facade r import.
src/flext_core/dispatcher.py Switches to facade r import.
src/flext_core/_utilities/settings.py Switches to facade r import.
src/flext_core/_utilities/project_metadata.py Refactors metadata read/build boundary.
src/flext_core/_utilities/parser_coerce.py Switches to facade r import.
src/flext_core/_utilities/model_runtime.py Refactors local variable naming/typing.
src/flext_core/_utilities/mapper.py Switches to facade r import.
src/flext_core/_utilities/handler.py Fixes context variable usage clarity.
src/flext_core/_utilities/dispatcher_execute.py Migrates ResultLikeResult checks.
src/flext_core/_utilities/config.py Switches to facade r import.
src/flext_core/_utilities/args.py Switches to facade r import.
src/flext_core/_utilities/_mapper_access_parts/mapper_access_part_01.py Tightens local result typing.
src/flext_core/_utilities/_guards_type_protocol_types.py Updates protocol union to Result.
src/flext_core/_utilities/_enforcement_collect_parts/enforcement_collect_part_01.py Refactors enforcement project resolution.
src/flext_core/_utilities/_checker_parts/checker_part_03.py Switches to facade r import.
src/flext_core/_utilities/_checker_parts/checker_part_02.py Switches to facade r import.
src/flext_core/_typings/services.py Expands service registration typing.
src/flext_core/_settings.py Adjusts settings field declaration.
src/flext_core/_runtime/_dependency_bindings.py Updates DI wiring API usage.
src/flext_core/_result/unwrap.py Updates unwrap semantics for None payload.
src/flext_core/_result/transforms.py New transforms layer for result.
src/flext_core/_result/construction.py New construction/factory layer for result.
src/flext_core/_result/composition.py Refactors composition ops onto new layers.
src/flext_core/_result/behavior.py New dunder/behavior layer for result.
src/flext_core/_result/base.py New internal base model for result.
src/flext_core/_result/init.py New result package initializer.
src/flext_core/_result_parts/transforms.py Removes legacy result mixin transforms.
src/flext_core/_result_parts/construction.py Removes legacy result mixin construction.
src/flext_core/_result_parts/behavior.py Removes legacy result mixin behavior.
src/flext_core/_result_parts/init.py Removes legacy result parts package init.
src/flext_core/_protocols/result.py Consolidates protocols to single Result.
src/flext_core/_protocols/handler.py Updates handler return contracts to Result.
src/flext_core/_protocols/_result_parts/flextprotocolsresult_part_04.py Removes legacy protocol split file.
src/flext_core/_protocols/_result_parts/flextprotocolsresult_part_03.py Removes legacy protocol split file.
src/flext_core/_protocols/_result_parts/flextprotocolsresult_part_02.py Removes legacy protocol split file.
src/flext_core/_protocols/_result_parts/flextprotocolsresult_part_01.py Removes legacy protocol split file.
src/flext_core/_models/handler.py Serializes middleware types deterministically.
src/flext_core/_exceptions/_factories_parts/flextexceptionsfactories_part_04.py Updates result type references.
src/flext_core/_exceptions/_factories_parts/flextexceptionsfactories_part_03.py Updates result type references.
src/flext_core/_exceptions/_factories_parts/flextexceptionsfactories_part_02.py Updates result type references.
src/flext_core/_exceptions/_factories_parts/flextexceptionsfactories_part_01.py Updates lazy result type resolution.
src/flext_core/_decorators/_railway.py Switches to facade r import.
src/flext_core/version.py Improves homepage parsing robustness.
pyproject.toml Updates deps + tools + pytest/ruff/pyright config.
Makefile Regenerated canonical make surface.
examples/typings.py Migrates ResultLikeResult.
examples/ex_04_flext_dispatcher.py Updates handler signatures to r[T].
examples/_models/ex00.py Updates example domain result typing.
ci/docker/ubuntu.Dockerfile Adds Ubuntu clean-machine docker build.
ci/docker/fedora.Dockerfile Adds Fedora clean-machine docker build.
ci/docker/debian.Dockerfile Adds Debian clean-machine docker build.
ci/docker/arch.Dockerfile Adds Arch clean-machine docker build.
ci/docker/alpine.Dockerfile Adds Alpine clean-machine docker build.
.vscode/settings.json Updates editor excludes + env discovery.
.python-version Switches to 3.13 family pin.
.mise.toml Regenerated toolchain pins for 0.12.0-dev.
.gitignore Replaces restrictive ignore policy with generated ignores.
.github/workflows/ci.yml Updates CI workflow for 0.12.0-dev.
.github/workflows/ci-matrix.yml Adds cross-distro CI matrix workflow.
.envrc Regenerated direnv activation for standalone repo.
.beads/README.md Removes Beads README (repo-local).
.beads/metadata.json Removes repo-local beads metadata.
.beads/issues.jsonl Repo-local beads data file touched.
.beads/interactions.jsonl Repo-local beads data file touched.
.beads/embeddeddolt/beads/.dolt/temptf/dolt_embedded_metrics Removes embedded dolt metrics artifact.
.beads/embeddeddolt/beads/.dolt/repo_state.json Removes embedded dolt repo state.
.beads/embeddeddolt/beads/.dolt/noms/nbs_manifest_3630928294 Removes embedded dolt manifest.
.beads/embeddeddolt/beads/.dolt/noms/manifest Removes embedded dolt manifest file.
.beads/embeddeddolt/beads/.dolt/noms/LOCK Embedded dolt lock file touched.
.beads/embeddeddolt/beads/.dolt/config.json Removes embedded dolt config.
.beads/config.yaml Removes repo-local beads config.
.beads/backup/manifest Removes beads backup manifest.
.beads/backup/LOCK Beads backup lock file touched.
.beads/backup/backup_state.json Removes beads backup state.
.beads/.gitignore Removes beads-local ignore file.
Suppressed comments (1)

src/flext_core/_utilities/_enforcement_collect_parts/enforcement_collect_part_01.py:115

  • _project() calls _owning_project_root() (which can now raise RuntimeError) and re-raises on pyproject read errors. Since _namespace_items() calls _project() without a try/except, these RuntimeErrors can crash enforcement collection instead of skipping the target (consistent with the function’s ... | None contract).

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

Comment thread Makefile Outdated
Comment on lines +524 to +526
# Operator contract (mro-e9j0.6 C7): setup PROVISIONS tooling only — mise,
# venv, dependencies. It never generates, conforms, or mutates project code;
# `make gen` (APPLY=Y) is the single public conformance/generation surface.
Comment thread tests/base.py
Comment on lines 10 to +14
if TYPE_CHECKING:
from tests.protocols import p


class TestsFlextServiceBase[TDomainResult: t.JsonPayload | t.SequenceOf[t.JsonPayload]](
tests_s[TDomainResult]
class TestsFlextServiceBase[TDomainResult: p.Base = p.Base](
Comment on lines +89 to +92
try:
document = upm.read_project_document_cached(project_root)
except (OSError, ValueError) as exc:
raise RuntimeError(_ERR_ENFORCEMENT_NAMESPACE_METADATA) from exc

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

16 issues found across 105 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="ci/docker/ubuntu.Dockerfile">

<violation number="1" location="ci/docker/ubuntu.Dockerfile:23">
P1: A compromise or changed response from any installer endpoint becomes root code execution during CI image builds. Pin verified release artifacts and validate checksums/signatures before installation.</violation>

<violation number="2" location="ci/docker/ubuntu.Dockerfile:36">
P1: Local ignored files are baked into the image because the complete build context is copied with no `.dockerignore`. This can expose developer credentials/configuration to image consumers; add an allowlist or at least exclude VCS metadata, env files, and local tool state.</violation>
</file>

<file name="src/flext_core/_result/base.py">

<violation number="1" location="src/flext_core/_result/base.py:67">
P2: String-backed `success` input can create inconsistent result state: `success="false"` becomes `self.success is False`, but this raw-value branch stores `value` and never stores `exception`. Branch on Pydantic's validated `self.success` so payload/exception follow the exposed status.</violation>
</file>

<file name="src/flext_core/_result/construction.py">

<violation number="1" location="src/flext_core/_result/construction.py:26">
P2: Cloning a valid empty-message failure currently raises `ValueError`: `fail(None)` produces `error == ""`, but this truthiness check rejects it. Preserve empty strings so `from_failure(r.fail(None))` remains a failed result rather than breaking error propagation.</violation>
</file>

<file name="Makefile">

<violation number="1" location="Makefile:706">
P3: `make status` cannot diagnose a fresh or broken environment: it now exits at `_builtin_require_environment` before printing status. Leave this read-only diagnostic target runnable without a venv.</violation>
</file>

<file name=".mise.toml">

<violation number="1" location=".mise.toml:14">
P2: Python version pinned to `"3.13"` (floating) instead of the previous exact `"3.13.11"`. This means mise will resolve to whatever the latest 3.13.x patch is at install time, which can differ across environments and CI runs. Different patch versions may introduce subtle behavioral differences, making environment-dependent bugs harder to reproduce.</violation>
</file>

<file name="src/flext_core/_result/transforms.py">

<violation number="1" location="src/flext_core/_result/transforms.py:40">
P2: Transforms crash or replace a valid `fail(None)` result instead of propagating/recovering it. Avoid `require_error` in these instance failure paths; pass the normalized error string so empty-error failures retain their error metadata and carried exception.</violation>
</file>

<file name="ci/docker/fedora.Dockerfile">

<violation number="1" location="ci/docker/fedora.Dockerfile:22">
P2: Image builds execute whatever `mise.run` serves at build time as root, making this CI artifact non-reproducible and exposing the build to installer-endpoint compromise. Pin a release artifact and verify its checksum/signature before execution.</violation>

<violation number="2" location="ci/docker/fedora.Dockerfile:27">
P2: Rust tooling can change or be compromised independently of this repository because the mutable rustup installer and `stable` channel run during every build. Pin and verify the installer/toolchain used for the image.</violation>
</file>

<file name="src/flext_core/_typings/services.py">

<violation number="1" location="src/flext_core/_typings/services.py:99">
P2: Concrete-message free-function handlers now fail static checking when passed to `register_handler` or assigned to `DispatchableHandler`, despite being the supported routed-handler pattern. Keep this callable arm variadic (or make the alias generic over the routed message type) so handlers such as `def handler(command: CreateCommand)` remain registerable.</violation>
</file>

<file name="src/flext_core/_utilities/project_metadata.py">

<violation number="1" location="src/flext_core/_utilities/project_metadata.py:60">
P2: A pyproject without `[project]` now succeeds as fabricated `unknown`/`0.0.0` package metadata, so callers cannot distinguish a non-package workspace from valid PEP 621 metadata. Preserve the prior failure in `read_project_metadata` (or make `project` optional) rather than inventing a `Project`.</violation>
</file>

<file name="src/flext_core/_utilities/dispatcher_execute.py">

<violation number="1" location="src/flext_core/_utilities/dispatcher_execute.py:31">
P2: Handlers returning a non-`r` implementation of the advertised `p.Result` contract are rejected before this branch runs. Normalize `p.Result` values as results too, so structural result handlers preserve success/failure outcomes.</violation>
</file>

<file name="pyproject.toml">

<violation number="1" location="pyproject.toml:721">
P2: Example files can now violate module naming and executable-shebang checks without CI reporting them. This blanket example-tree suppression conflicts with the repository’s required tool coverage; keep these checks enabled and fix or narrowly justify individual files instead.</violation>
</file>

<file name="src/flext_core/result.py">

<violation number="1" location="src/flext_core/result.py:18">
P3: The explicit base list repeats the complete inheritance chain already supplied by `FlextResultUnwrap`. Keeping only that base preserves the same public methods while avoiding a fragile, needlessly complex MRO.</violation>

<violation number="2" location="src/flext_core/result.py:29">
P3: Direct `FlextResult(..., error_data=ConfigMap_or_model_dump_carrier)` calls now fail type checking despite remaining supported by the constructor implementation and factory API. Preserve the public mapping/model-input annotation so direct construction retains its established contract.</violation>
</file>

<file name="src/flext_core/_protocols/result.py">

<violation number="1" location="src/flext_core/_protocols/result.py:24">
P1: Public protocol aliases disappear from `p`, so existing annotations/imports such as `p.ResultLike[...]` fail at evaluation and the public-API contract no longer matches. Preserve these protocol names (or update every supported consumer as an intentional breaking API change) while consolidating the implementation.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

# End SECTION: managed tool bootstrap

WORKDIR /workspace
COPY . .

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1: Local ignored files are baked into the image because the complete build context is copied with no .dockerignore. This can expose developer credentials/configuration to image consumers; add an allowlist or at least exclude VCS metadata, env files, and local tool state.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At ci/docker/ubuntu.Dockerfile, line 36:

<comment>Local ignored files are baked into the image because the complete build context is copied with no `.dockerignore`. This can expose developer credentials/configuration to image consumers; add an allowlist or at least exclude VCS metadata, env files, and local tool state.</comment>

<file context>
@@ -0,0 +1,60 @@
+# End SECTION: managed tool bootstrap
+
+WORKDIR /workspace
+COPY . .
+
+# === SECTION: mise install (managed) ===
</file context>

Comment thread ci/docker/ubuntu.Dockerfile Outdated
# Source: config:python_version, template (installer URLs)
# mise installs the supported Python 3.13 family.
# uv is supplied by the managed environment without a project patch pin.
RUN curl -fsSL https://mise.run | sh

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1: A compromise or changed response from any installer endpoint becomes root code execution during CI image builds. Pin verified release artifacts and validate checksums/signatures before installation.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At ci/docker/ubuntu.Dockerfile, line 23:

<comment>A compromise or changed response from any installer endpoint becomes root code execution during CI image builds. Pin verified release artifacts and validate checksums/signatures before installation.</comment>

<file context>
@@ -0,0 +1,60 @@
+# Source: config:python_version, template (installer URLs)
+# mise installs the supported Python 3.13 family.
+# uv is supplied by the managed environment without a project patch pin.
+RUN curl -fsSL https://mise.run | sh
+# uv is intentionally supplied by the caller environment; install it explicitly
+# in clean-machine images so the project bootstrap can resolve dependencies.
</file context>

Comment thread ci/docker/fedora.Dockerfile Outdated
Comment thread ci/docker/arch.Dockerfile Outdated
Comment thread .mise.toml
python = "3.13.11"
uv = "0.11.32"
# Deploy toolchain (single source: Infra.codegen.toolchain in codegen.yaml).
python = "3.13"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: Python version pinned to "3.13" (floating) instead of the previous exact "3.13.11". This means mise will resolve to whatever the latest 3.13.x patch is at install time, which can differ across environments and CI runs. Different patch versions may introduce subtle behavioral differences, making environment-dependent bugs harder to reproduce.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .mise.toml, line 14:

<comment>Python version pinned to `"3.13"` (floating) instead of the previous exact `"3.13.11"`. This means mise will resolve to whatever the latest 3.13.x patch is at install time, which can differ across environments and CI runs. Different patch versions may introduce subtle behavioral differences, making environment-dependent bugs harder to reproduce.</comment>

<file context>
@@ -1,14 +1,24 @@
-python = "3.13.11"
-uv = "0.11.32"
-# Deploy toolchain (single source: Infra.codegen.toolchain in codegen.yaml).
+python = "3.13"
+# Native toolchain (single source: Infra.codegen.toolchain in codegen.yaml).
 kubectl = "1.32.0"
</file context>
Suggested change
python = "3.13"
python = "3.13.11"

Comment thread src/flext_core/result.py
FlextResultTransformsMixin[T],
FlextResultUnwrapMixin[T],
class _FlextResult[T](
FlextResultUnwrap[T],

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: The explicit base list repeats the complete inheritance chain already supplied by FlextResultUnwrap. Keeping only that base preserves the same public methods while avoiding a fragile, needlessly complex MRO.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/flext_core/result.py, line 18:

<comment>The explicit base list repeats the complete inheritance chain already supplied by `FlextResultUnwrap`. Keeping only that base preserves the same public methods while avoiding a fragile, needlessly complex MRO.</comment>

<file context>
@@ -2,200 +2,60 @@
-    FlextResultTransformsMixin[T],
-    FlextResultUnwrapMixin[T],
+class _FlextResult[T](
+    FlextResultUnwrap[T],
+    FlextResultComposition[T],
+    FlextResultTransforms[T],
</file context>

Comment thread src/flext_core/result.py
self,
error_code: str | None = None,
error_data: tb.JsonMapping | ts.ConfigModelInput | None = None,
error_data: JsonDict | None = None,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: Direct FlextResult(..., error_data=ConfigMap_or_model_dump_carrier) calls now fail type checking despite remaining supported by the constructor implementation and factory API. Preserve the public mapping/model-input annotation so direct construction retains its established contract.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/flext_core/result.py, line 29:

<comment>Direct `FlextResult(..., error_data=ConfigMap_or_model_dump_carrier)` calls now fail type checking despite remaining supported by the constructor implementation and factory API. Preserve the public mapping/model-input annotation so direct construction retains its established contract.</comment>

<file context>
@@ -2,200 +2,60 @@
         self,
         error_code: str | None = None,
-        error_data: tb.JsonMapping | ts.ConfigModelInput | None = None,
+        error_data: JsonDict | None = None,
         *,
         value: T | None = None,
</file context>

Comment thread Makefile Outdated
Comment thread Makefile
@$(UV_RUN) $(PROJECT_NAME) $(ARGS)

_builtin_status_diagnostics:
_builtin_status_diagnostics: _builtin_require_environment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: make status cannot diagnose a fresh or broken environment: it now exits at _builtin_require_environment before printing status. Leave this read-only diagnostic target runnable without a venv.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At Makefile, line 706:

<comment>`make status` cannot diagnose a fresh or broken environment: it now exits at `_builtin_require_environment` before printing status. Leave this read-only diagnostic target runnable without a venv.</comment>

<file context>
@@ -210,80 +386,361 @@ _builtin_help_usage:
 	@$(UV_RUN) $(PROJECT_NAME) $(ARGS)
 
-_builtin_status_diagnostics:
+_builtin_status_diagnostics: _builtin_require_environment
 	@printf 'profile=%s\nattached=%s\nproject=%s\nruntime=%s\n' \
 		'$(MAKE_PROFILE)' '$(ATTACHED_MEMBER)' '$(PROJECT_ROOT)' '$(RUNTIME_ROOT)'
</file context>
Suggested change
_builtin_status_diagnostics: _builtin_require_environment
_builtin_status_diagnostics:

Marlon Costa and others added 16 commits August 1, 2026 10:39
FlextService declared aliases but not validate_by_name, so constructing any
service with its declared field name (e.g. workspace_root= for the workspace
alias) was rejected by static analysis: 299 unexpected-keyword errors across
flext-infra. Runtime already accepted it via a subclass model_config, which
hid the contract gap.
pydantic.computed_field has no zero-argument overload, so `@m.computed_field()`
failed no-matching-overload under static analysis. The bare decorator is the
documented form.
Regenerated stale managed projections (ci workflows, Dockerfiles,
Makefile, .gitignore, pyproject managed sections) to match current
flext-infra templates/config via make gen WHAT=all APPLY=Y.
Refs mro-xf56.
Remove stray blank line after # [MANAGED] section markers so
deps-modernize and codegen-conform agree on a single fixed point.
Refs mro-xf56.
The managed pyproject projection was missing the blank line the
canonical generator emits after each '# [MANAGED]' marker, so
'make gen WHAT=check' reported drift from a clean clone.

Regenerated through the canonical generator, never hand-edited;
a second generator run is byte-identical (idempotent fixed point).

Refs: mro-wkii.17.39
flext c9832249/81cc760ad inserted a blank line after each '# [MANAGED]'
marker. That was a regression: the canonical emitter appends the marker
immediately before its section (deps/phases/inject_comments.py:173-182,
out.append(marker) then out.append(line)) and _collapse_blank_lines only
removes duplicates -- it never inserts one. So the generator's fixed
point has NO blank line, and the committed projection permanently
disagreed with it, keeping 'make gen WHAT=check' red on 32 pyproject
files with no tree state able to satisfy it.

Reverted by running the canonical modernizer.conform_source over each
projection, never by hand.

Refs: mro-shxw
Co-authored-by: Cursor <cursoragent@cursor.com>
@sonarqubecloud

sonarqubecloud Bot commented Aug 3, 2026

Copy link
Copy Markdown

@marlon-costa-dc
marlon-costa-dc merged commit eaa35ec into main Aug 3, 2026
4 of 16 checks passed
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.

2 participants