Skip to content

fix: surface the requesting scope's own quirk emits into host-aspects spawns - #633

Merged
sini merged 1 commit into
denful:mainfrom
sini:fix/user-scope-quirk-class-exposure
Jul 17, 2026
Merged

fix: surface the requesting scope's own quirk emits into host-aspects spawns#633
sini merged 1 commit into
denful:mainfrom
sini:fix/user-scope-quirk-class-exposure

Conversation

@sini

@sini sini commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

Problem

A quirk produced within a user's class context (a homeManager aspect's bare quirk key) does not reach that user's homeManager consumer when the consumer is projected onto the user via den.batteries.host-aspects. The projected consumer sees only host-scope emits (re-emitted host → home), never the user's own — asymmetric with host ↔ nixos, where a host's quirk reaches the host's nixos consumer directly.

Surfaced downstream: an overlay declared on a user-scoped homeManager aspect never reached that user's nixpkgs.overlays, so pkgs.<x> provided by the overlay was undefined in the user's home-manager evaluation. It "worked" only because the aspects carrying such overlays happened to be host-level roles (re-emit covered them); a genuinely user-scoped overlay broke.

Cause

The host-aspects policy.spawn roots the projected consumer with from = the requesting scope's parent = the host scope, and links the spawn root's parent to from. So the consumer's quirk collection walks the host parent chain and never traverses the requesting user scope — its own directly-included quirk emits are outside the walk. #625 added the upward half (surface the spawn's emits up into the requesting scope's imports); the downward half was missing.

Fix

The downward dual of #625.

  • spawn-node.nix takes the requesting scope's own raw imports (requestingImports) and merges its non-host-bound quirk emits into the spawn root's imports used for assembly (mergedClassImports) — not into spawnedClassImports, which feeds the upward quirkEmits return (folding them there would double-count the emit back at the requesting scope). Host-bound quirks are excluded (they inherit the host's policy-assembled value, matching the existing strip).
  • resolve.nix passes scopedClassImportsRaw.<scopeId> through as requestingImports.
  • from = host is untouched, so fix: surface spawn-projected quirk emits at the requesting scope #625's fleet-peer collection is preserved.

Tests

New suite user-class-quirk-exposure:

  • test-host-quirk-local-nixos — host ↔ nixos baseline
  • test-user-quirk-local-home — user ↔ own home baseline
  • test-user-quirk-into-host-aspects-projected-consumer — the repro (failed pre-fix: consumer read [])

Full suite green: 1057/1057.

… spawns

## Problem

A quirk produced within a user's class context (a homeManager aspect's bare
quirk key) does not reach that user's homeManager consumer when the consumer is
projected onto the user via `den.batteries.host-aspects`. The projected consumer
sees only host-scope emits (re-emitted host -> home), never the user's own —
asymmetric with host <-> nixos, where a host's quirk reaches the host's nixos
consumer directly.

(Surfaced in nix-config: an overlay declared on a user-scoped `homeManager`
aspect never reached that user's `nixpkgs.overlays`, so `pkgs.<x>` from the
overlay was undefined in the user's HM.)

## Cause

The host-aspects `policy.spawn` roots the projected consumer with `from` = the
requesting scope's parent = the host scope, and links the spawn root's parent to
`from`. So the consumer's quirk collection walks the *host* parent chain and
never traverses the requesting *user* scope — its own directly-included quirk
emits are outside the walk. denful#625 added the UPWARD half (surface the spawn's
emits up into the requesting scope's imports); the DOWNWARD half was missing.

## Fix

The downward dual of denful#625. `spawn-node.nix` takes the requesting scope's own raw
imports (`requestingImports`) and merges its non-host-bound quirk emits into the
spawn root's imports used for assembly (`mergedClassImports`) — but NOT into
`spawnedClassImports`, which feeds the upward `quirkEmits` return (folding them
there would double-count the emit back at the requesting scope). Host-bound
quirks are excluded (they inherit the host's policy-assembled value, matching the
existing strip). `resolve.nix` passes `scopedClassImportsRaw.<scopeId>` through
as `requestingImports`. `from` = host is untouched, so denful#625's fleet-peer
collection is preserved.

## Tests

New suite `user-class-quirk-exposure` (host<->nixos + user<->home baselines +
the host-aspects-projected-consumer repro). Full suite green: 1057/1057.
@sini
sini requested a review from vic as a code owner July 17, 2026 19:32
@github-actions github-actions Bot added the allow-ci allow all CI integration tests label Jul 17, 2026
sini added a commit to sini/nix-config that referenced this pull request Jul 17, 2026
Temporarily points the den input at denful/den#633 so a quirk declared on a
user-scoped homeManager aspect reaches that user's homeManager consumer through
the host-aspects projection. Revert to github:denful/den once merged.
@sini

sini commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator Author

Going to go ahead and merge this fix directly as it builds on #625

@sini
sini merged commit 2fcac84 into denful:main Jul 17, 2026
30 of 37 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

allow-ci allow all CI integration tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant