Skip to content

refactor(engine): collapse resolver host I/O onto the Session seam (deepen-engine-seams)#30

Merged
ncode merged 13 commits into
mainfrom
juliano/deepen-engine-seams
Jul 3, 2026
Merged

refactor(engine): collapse resolver host I/O onto the Session seam (deepen-engine-seams)#30
ncode merged 13 commits into
mainfrom
juliano/deepen-engine-seams

Conversation

@ncode

@ncode ncode commented Jul 3, 2026

Copy link
Copy Markdown
Owner

Summary

Behavior-preserving deepening of internal/engine: the run-scoped Session host seam becomes the only path resolvers use to reach the host, structurally enforced by a new AST gate. This is the ADR-0010-deferred commandRunner/fileReader → Session collapse, extended by six adjacent deepenings found by the same deletion-test review. No public API, CLI flag, output, input-source precedence, diagnostic, or cache behavior changes.

Implements the deepen-engine-seams OpenSpec change (archived in this PR; 47 tasks across 9 groups).

What changed

  • Session host-I/O collapse — the FromRoot/WithHost/WithReader/ForPlatform variant families (networking 10→4, processors triple→1, dmi's five ForPlatform pairs, virtual/xen, os/uptime/memory) collapse onto the Session; raw os.ReadDir/os.Stat leaks are closed. TestNoRawHostIOInResolvers (AST-based) freezes the boundary.
  • goos/env seam — category assembly reads platform via s.goos() and environment via s.getenv (case-insensitive only on Windows), so windows/plan9 paths are exercisable with a fake host; the ssh/fips gating-test skips are gone.
  • Virtualization memo — the DMI/dmidecode/virt-what/vmware/lspci gather runs once per discovery instead of up to three times (Linux), memoized on the Session (ADR-0005-compliant).
  • Cloud transportmetadatahttp.go consolidates four hand-rolled ec2/gce/az clients (proxy-less, 200-required, 1 MiB-capped, fail-closed) with the first transport-invariant tests.
  • Loader armsEngine.Discover's two near-identical external-loader arms collapse to one; the test-only LoadExternalFacts facade is deleted.
  • Version fast path — reuses engine.DisabledUnion and engine.BuildFormatter instead of an internal/app mirror; the four bare Format* become test-only.
  • Dead code removeddetector.go, query.go Select delegates, filehelper.go, dead gceFacts, the fast-path crutch exports.

Verification

  • go build ./..., go vet ./..., go test ./... (2326 tests), go test -race on engine + app — all green.
  • The TestNoRawHostIOInResolvers seam gate passes.
  • Contract test files unchanged vs main.
  • Real-host behavior-preservation (branch vs main, stable fact subset byte-identical, only volatile uptime/memory/disk facts differ):
    • Linux via the Facter 4.10.0 Lima VM.
    • Windows Server 2025 (nlab) — os.windows.system32 = C:\WINDOWS\system32, path leads with it (proves s.getenv("SystemRoot") matches os.Getenv).
    • Plan 9 / 9front (nlab) — path = ["/bin", "."] (non-empty, NUL-split).

🤖 Generated with Claude Code

ncode added 13 commits July 2, 2026 23:12
factMatchesQuery moves beside its sole caller in projection.go; the
delegate-driven tests retarget NewProjection(...).Select directly.
detector.go had zero production callers (deletion test: concentrates).

deepen-engine-seams group 1
…v seam

- fakeHostOS grows additive knobs: per-path error maps, emptyRunDefault,
  fakeFileEntries (IsDir-skipping loops need file entries)
- pure envValue (case-insensitive only on windows) + Session.getenv
- ~30 runtime.GOOS reads across fips/selinux/timezone/uptime/ssh/identity/
  dmi/os/core bind s.goos(); SystemRoot/programdata/PROCESSOR_ARCHITEW6432/
  PATH read the Session host environ
- ssh + fips gating-test skips deleted; fake-windows ssh/os assembly tests

deepen-engine-seams groups 2-3
Linux ran the dmidecode/virt-what/vmware/lspci gather three times per
discovery (virtual, hypervisors.*, uptime container gate); Windows ran
the wmic/reg gather twice. One Session memo per platform (cachedDMI
pattern, ADR-0005-compliant: per-discovery, never Engine-resident);
classification stays pure so resolved values are unchanged.

deepen-engine-seams group 4
…art 1)

Groups 5.1-5.4, 5.6: core.go reader helpers take required readers;
networking metadata/bonding/DHCP variant families collapse to
host-taking functions (10 variants -> 4), closing raw os.ReadDir at
networking.go:1099/1170; processors physical-count triple -> 1, closing
os.ReadDir at processors.go:457; dmi five ForPlatform pairs + windows
fold onto the Session. Resolver tests migrate to fakeHostOS under the
same-assertions-relocated-fixtures rule.

deepen-engine-seams group 5 (part 1)
…ze the seam

Groups 5.5, 5.9-5.11: virtual/xen fold WithCommands/WithHost onto the
Session (procVZEntryCount closes os.ReadDir at virtual.go:605);
fips/identity/augeas/ec2 fileExecutable take the Session (closes os.Stat
at ec2.go:106); delete dead filehelper.go. TestNoRawHostIOInResolvers
AST-gates the collapsed state: no raw os.ReadDir/ReadFile/Stat/Lstat/
filepath.Glob/exec.Command outside session*.go/external.go/cache.go/
config.go/statfs*.

deepen-engine-seams group 5 (part 2)
metadatahttp.go: newMetadataHTTPClient (proxy-less) + fetchMetadata
(200-required, 1MB-capped, fail-closed) replace four hand-rolled copies
in ec2/gce/az. Providers keep their own headers, token/flavor handling,
parse, gates, and per-provider timeouts. Delete dead gceFacts (retarget
its 6 tests to linuxGCEFacts with production {gce: nil} empty-case
expectations); metadatahttp_test.go adds the first transport-invariant
tests (proxy-less, non-200, request-build error, transport error, 1MB
body cap, header passthrough).

deepen-engine-seams group 6
…ession

Groups 5.7-5.8: currentOSRelease/currentFilesystems/currentLinuxDistro
and the macOS probe pairs (os.go); the currentUptime*/currentLoadAverages
family (keeping the now func() time.Time param — the clock is not on the
host seam) and currentWindowsMemory/currentDarwinSwapUsage (memory.go)
take their readers/runner/goos from the Session. ~50 test closures
migrate to fakeHostOS under the same-assertions-relocated-fixtures rule.

deepen-engine-seams group 5 (part 3) — group 5 complete
The two near-identical loader arms in Engine.Discover become one
construction + one load() call with a single mode-conditional branch:
CLI mode returns newSnapshot(nil, logger), err byte-identically (partial
facts + planFailures discarded, finish() skipped); library mode appends
to failures and keeps partial facts. Discover-level pins lock both error
policies. Delete the test-only LoadExternalFacts/WithBlocklist facade
(zero production callers); external_test.go gets a field-for-field
in-package helper, ~98 call sites retargeted.

deepen-engine-seams group 7
Export one pure DisabledUnion (config + --disable + FACTS_DISABLE union,
group-expanded); discovery planning and internal/app's fast path both
derive their disabled set from it, so they can never disagree on whether
facterversion is disabled. Delete the EnvironmentDisabledFacts /
DisabledFactsForFiltering crutch exports. Route writeVersionQuery through
engine.BuildFormatter (three format booleans only; --color/--force-dot
stay ignored). Demote the four bare Format* functions to an in-package
test helper — 102 formatter_test call sites + 3 benchmarks untouched,
production build loses the exports. Byte pins + fall-through pins lock
identity.

deepen-engine-seams group 8
…010 follow-on

CHANGELOG internal-refactor entry; ADR-0010's deferred commandRunner/
fileReader->Session collapse marked done (structurally enforced by
TestNoRawHostIOInResolvers), resolving the archived 2026-06-17
LoadExternalFacts open question; design.md records the Lima real-Linux
behavior-preservation result and the plan9/windows guest-smoke accepted
risk (nlab unavailable; covered by cross-builds + fake-host tests).

deepen-engine-seams group 9
Both guests reachable and validated: main vs branch binaries diff
stable-subset byte-identical on Windows Server 2025 and Plan 9 (9front),
only volatile uptime/memory/disk facts differ. Windows os.windows.system32
= C:\WINDOWS\system32 (s.getenv(SystemRoot) matches os.Getenv); Plan 9
path fact = [/bin, .] (non-empty, NUL-split).
Applies the change's spec deltas to the main specs (facts-library-api
diagnostics drops OS-hierarchy detection; go-port-supported-platform-facts
gains the Session-only-host-I/O-path enforcement and single-gather
requirement; facts-cli-option-contract gains the version fast-path seam
reuse) and moves the completed change to the archive.
Four fake-host tests passed on darwin/linux but failed on the Windows CI
runner: fakeHostPath normalized lookups with filepath.ToSlash (a no-op
off Windows), while fixtures keyed windows paths with backslashes and
newLeaseDirHost keyed with filepath.Join — so keys and lookups diverged
only on Windows, and the want-empty lease tests passed vacuously.

Normalize fakeHostPath with an unconditional backslash->slash replace
(sshCoreFacts forces backslash joins for the windows branch on every
host, so a slash-keyed fixture must resolve on unix dev hosts too) and
key the lease/ssh fixtures with forward slashes.

Fixes the Windows Server 2022/2025 go-test failures on PR #30.
@ncode ncode merged commit 86208e6 into main Jul 3, 2026
37 checks passed
@ncode ncode deleted the juliano/deepen-engine-seams branch July 3, 2026 16:40
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.

1 participant