Skip to content

refactor: den-fx#462

Merged
vic merged 15 commits intovic:mainfrom
sini:feat/fx-resolution
Apr 17, 2026
Merged

refactor: den-fx#462
vic merged 15 commits intovic:mainfrom
sini:feat/fx-resolution

Conversation

@sini
Copy link
Copy Markdown
Collaborator

@sini sini commented Apr 17, 2026

Summary

Replace den's legacy recursive tree-walking resolution with an effects-based pipeline. Aspects compile into effectful computations via aspectToEffect — the tree structure emerges from effect composition, not explicit recursion. All resolution strategy (constraint checking, dedup, tracing, context dispatch) lives in handlers.

  • aspectToEffect compiler — single function compiles any aspect into a computation that emits emit-class, register-constraint, emit-include, and resolve-complete effects
  • Handler-owned recursionemit-include handler checks constraints and recurses via effectful resume; into-transition handler processes context transitions with scope.stateful
  • Constraint systemmeta.handleWith / meta.excludes replace fx usage of meta.adapter; scoped constraints via includes-chain ancestry; exclude, substitute, filterBy constructors with subtree/global variants
  • Includes chain provenancechain-push/chain-pop effects replace __parent string tracking; observable by any handler for diagrams, scope visualization, composable analysis
  • Module wiring{ lib, den } only, no init function, barrel default.nix; nix-effects accessed as den.lib.fx
  • den.fxPipeline option — defaults to true; legacy tests using resolve.withAdapter run with fxPipeline = false

Pipeline architecture

nix/lib/aspects/fx/
  aspect.nix        — aspectToEffect compiler
  pipeline.nix      — mkPipeline, defaultHandlers, fxResolve
  identity.nix      — path/identity utilities, collectPathsHandler, pathSetHandler
  constraints.nix   — exclude, substitute, filterBy constructors
  includes.nix      — includeIf conditional inclusion
  trace.nix         — structuredTraceHandler, tracingHandler
  handlers/
    include.nix     — emit-include handler (owns recursion)
    transition.nix  — into-transition handler (scope.stateful)
    ctx.nix         — constantHandler, ctxSeenHandler
    tree.nix        — constraintRegistryHandler, chainHandler, classCollectorHandler

Effect protocol

Effect Handler responsibility
emit-class Accumulate modules by class
emit-include Check constraints, recurse via aspectToEffect
register-constraint Store in registry with scope/ownerChain
check-constraint Query registry, first-registered-wins
chain-push / chain-pop Track includes-path stack
into-transition Walk context transitions with scoped handlers
ctx-seen Dedup context stages
resolve-complete Emit trace entries, accumulate paths
get-path-set Return accumulated path set for includeIf guards
<arg-name> constantHandler resumes with context value

Compatibility shims

The type system operates at declaration time and cannot be gated on config.den.fxPipeline without circular evaluation:

  • aspect-chain in constantHandler — provider functions from providerFnType.merge create { class, aspect-chain } functors
  • options.nix uses legacy ctxApplyconfig.resolved can't access config.den without circularity
  • Legacy adapter tests run with fxPipeline = false

Also in this PR

Test plan

  • nix develop -c just ci "" — 488/488 pass
  • nix develop -c just ci-fast — parallel eval, 488/488 pass
  • nix flake check — templates, packages, devShells all pass
  • Checkmate system-agnostic tests — 15/15 pass
  • Legacy tests with fxPipeline = false verify backward compatibility

sini and others added 13 commits April 16, 2026 21:48
Add nix-effects as fx library accessible via den.lib.fx. Handlers can
now return computations as resume values (effectful handlers), enabling
handler-owned recursion in the fx pipeline.

Loaded from flake input when available, falls back to locked fetchTarball.
…ompat shims

- aspects/default.nix: fxResolveTree entry point, fxPipeline gate,
  defaultFunctor from parametric.withOwn
- aspects/types.nix: meta.handleWith + meta.excludes options
- parametric.nix: carry handleWith in identity envelope alongside adapter
- statics.nix: legacy pipeline marker
- aspects/resolve.nix: legacy pipeline marker
- aspects/adapters.nix: legacy pipeline marker, revert meta.adapter to
  function-only
- ctx-apply.nix: __ctxStage/__ctxKind/__ctxAspect tag propagation
- home-env.nix: uses { class, aspect-chain } provider function
- default.nix: wire fx into den.lib
Rename the underscore alias to the explicit provides. accessor in all
aspect modules, output modules, and templates for clarity.
- Move tests from batteries/, context/, perf/, home-manager/ subdirs
  to flat features/ directory
- Add fx-specific test suites: fx-aspect, fx-constraints, fx-handlers,
  fx-resolve, fx-trace, fx-e2e, fx-full-pipeline, fx-identity,
  fx-includeIf, fx-integration, fx-flag, fx-ctx-apply, fx-ctx-parametric,
  fx-effectful-resolve, fx-parametric-meta, fx-regressions,
  fx-adapter-integration
- Update existing tests for constraint terminology and provides. alias
- Add fxPipeline=false for legacy adapter tests
- Add regression reproductions for issues vic#413, vic#423, vic#426, vic#437
Consolidated spec for the unified effects pipeline architecture:
aspectToEffect compiler, handler set, effect protocol, constraints,
includes chain provenance, context transitions, compatibility shims,
and followup work items.
…fields

The aspect type system now includes meta.handleWith and meta.excludes
in all aspects. Update the identity fixture in aspect-functor tests
to include these fields.
Add parens around (result.state.imports null) in builtins.length calls.
Without parens, Nix parses as (builtins.length result.state.imports) null
which passes the thunk to length instead of evaluating it first.
@sini sini self-assigned this Apr 17, 2026
@sini sini added allow-ci allow all CI integration tests allow-bench allow benchmark CI to run merge-approved Approved, merge yourself when ready ai-assisted design-approved Design looks good lets get into implementation labels Apr 17, 2026
@sini sini requested a review from vic April 17, 2026 16:40
Copy link
Copy Markdown
Owner

@vic vic left a comment

Choose a reason for hiding this comment

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

Awesome work, @sini 🚀

@vic vic merged commit 68c2655 into vic:main Apr 17, 2026
30 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-assisted allow-bench allow benchmark CI to run allow-ci allow all CI integration tests design-approved Design looks good lets get into implementation merge-approved Approved, merge yourself when ready

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants