Carry resolved filesystem facts through loads

This commit is contained in:
2026-10-25 13:13:47 +00:00
parent 6158e9db3b
commit 9a64a65b6c
8 changed files with 103 additions and 65 deletions

View File

@@ -1,6 +1,6 @@
# Consolidation Implementation Plan
Status: in progress. Stages 1 through 7 are complete; follow Stage 8 through Stage 20 in order.
Status: in progress. Stages 1 through 8 are complete; follow Stage 9 through Stage 20 in order.
The target executor is a Luna coding agent working through one end-to-end sprint.
## Authority, Baseline, And Execution
@@ -381,7 +381,7 @@ derivation adapters remain for the validator and overlay migration. Focused
acquisition tests, `GOTOOLCHAIN=local GOPROXY=off go test ./...`, and
`git diff --check` passed.
## Stage 8 — Carry Context Facts Through Input And Passive Views
## Stage 8 — Carry Context Facts Through Input And Passive Views (Complete)
**Owners:** engine `load_input.go`, `source_context.go`, `load_request.go`, and
the ordinary context backfill in `load.go`.
@@ -407,6 +407,12 @@ the ordinary context backfill in `load.go`.
**Finish:** ordinary/underlay acquisition and passive views use the common facts;
selected-overlay callers are the remaining migration in Stage 9.
Progress notes (2026-10-25): input acquisition now retains resolved filesystem
facts and builds passive contexts from those facts for ordinary and underlay
sources. Migrated the ordinary backfill and reordered-source context test. The
selected-overlay adapters remain for Stage 9. Focused context/acquisition tests,
`GOTOOLCHAIN=local GOPROXY=off go test ./...`, and `git diff --check` passed.
## Stage 9 — Migrate Selected Overlays Without Merging Their Semantics
**Owners:** engine `selected_overlay.go`, ordinary `applyInputLayers`, and

View File

@@ -164,7 +164,7 @@ func acquireInput(request inputAcquisitionRequest, policy acquisitionPolicy, sta
request.input.source = selectedSource
if request.input.imports && selectedSource.kind != sourceNone {
importRequest := importAcquisitionRequest{input: request, main: parsed, processing: versionProcessing}
input.composition, input.sources, diagnostics = acquireImportedInput(importRequest, &policy, state, tier)
input.composition, input.sources, input.resolvedFilesystem, diagnostics = acquireImportedInput(importRequest, &policy, state, tier)
if len(diagnostics) != 0 {
return input, diagnostics
}
@@ -218,7 +218,14 @@ func acquireInput(request inputAcquisitionRequest, policy acquisitionPolicy, sta
accounting.nodes += rawNodes + placementNodes
}
if !activeOverlay(request.ordinaryOverlay) || request.input.imports {
contexts, diagnostic := contextsForAcquiredSources(selectedSource, request.input.filesystem, parsed.source, input.sources)
if input.resolvedFilesystem == nil && len(input.sources) != 0 && (selectedSource.kind == sourceFile || request.input.filesystem != nil || nativeContext(selectedSource, request.input.filesystem)) {
resolved, diagnostic := resolveFilesystemContext(selectedSource, request.input.filesystem, parsed, tier.hostToken)
if diagnostic != nil {
return input, []Diagnostic{*diagnostic}
}
input.resolvedFilesystem = &resolved
}
contexts, diagnostic := contextsForResolvedSources(input.resolvedFilesystem, input.sources)
if diagnostic != nil {
return input, []Diagnostic{*diagnostic}
}

View File

@@ -165,6 +165,10 @@ func validateNativeDirectories(access *filesystemAccess, basePath, mainPath stri
}
func importFilesystem(source Source, context *FilesystemContext, main parsedSource) (rootPath, basePath, mainPath string, diagnostic *Diagnostic) {
if main.source == nil || main.document == nil {
value := importDiagnostic(CodeImportInvalid, "imports require a selected configuration source", nil)
return "", "", "", &value
}
resolved, diagnostic := resolveHostFilesystemContext(source, context, main, nil)
if diagnostic != nil {
return "", "", "", diagnostic

View File

@@ -17,12 +17,35 @@ type resolvedFilesystemContext struct {
}
func resolveFilesystemContext(source Source, context *FilesystemContext, main parsedSource, hostToken *namespaceToken) (resolvedFilesystemContext, *Diagnostic) {
if source.kind == sourceNone && context != nil {
return resolveAbsentFilesystemContext(context)
}
if nativeContext(source, context) {
return resolveNativeFilesystemContext(source, context)
}
return resolveHostFilesystemContext(source, context, main, hostToken)
}
func resolveAbsentFilesystemContext(context *FilesystemContext) (resolvedFilesystemContext, *Diagnostic) {
if context.FS != nil {
return resolveNativeFilesystemContext(Source{kind: sourceNone}, context)
}
rootPath, err := canonicalExistingPath(context.Root)
if err != nil {
value := importDiagnostic(CodeImportInvalid, "configuration root could not be canonicalized", nil)
return resolvedFilesystemContext{}, &value
}
basePath := rootPath
if context.BaseDir != "" {
basePath, err = canonicalExistingPath(context.BaseDir)
if err != nil {
value := importDiagnostic(CodeImportInvalid, "import base directory could not be canonicalized", nil)
return resolvedFilesystemContext{}, &value
}
}
return resolvedFilesystemContext{rootPath: rootPath, basePath: basePath}, nil
}
func resolveNativeFilesystemContext(source Source, context *FilesystemContext) (resolvedFilesystemContext, *Diagnostic) {
var namespace *nativeNamespace
resolved := resolvedFilesystemContext{rootPath: ".", basePath: "."}
@@ -50,7 +73,7 @@ func resolveNativeFilesystemContext(source Source, context *FilesystemContext) (
}
func resolveHostFilesystemContext(source Source, context *FilesystemContext, main parsedSource, hostToken *namespaceToken) (resolvedFilesystemContext, *Diagnostic) {
if main.source == nil || main.document == nil {
if main.source == nil {
value := importDiagnostic(CodeImportInvalid, "imports require a selected configuration source", nil)
return resolvedFilesystemContext{}, &value
}

View File

@@ -72,26 +72,30 @@ func compositionTraversal(policy sequencePolicy, rule *VersionRule, versionState
}
}
func acquireImportedInput(request importAcquisitionRequest, policy *acquisitionPolicy, state *acquisitionState, tier *tierAcquisitionState) (*composedDocument, []SourceInfo, []Diagnostic) {
func acquireImportedInput(request importAcquisitionRequest, policy *acquisitionPolicy, state *acquisitionState, tier *tierAcquisitionState) (*composedDocument, []SourceInfo, *resolvedFilesystemContext, []Diagnostic) {
source := request.input.input.source
context := request.input.input.filesystem
main := request.main
resolved, diagnostic := resolveFilesystemContext(source, context, main, tier.hostToken)
if diagnostic != nil {
return nil, sourceInfos(main.source), []Diagnostic{*diagnostic}
return nil, sourceInfos(main.source), nil, []Diagnostic{*diagnostic}
}
if resolved.native == nil {
if diagnostic := validateResolvedFilesystemDirectories(resolved); diagnostic != nil {
return nil, sourceInfos(main.source), []Diagnostic{*diagnostic}
return nil, sourceInfos(main.source), nil, []Diagnostic{*diagnostic}
}
}
access, err := openResolvedFilesystemAccess(resolved)
if err != nil {
diagnostic := globFilesystemDiagnostic(err, "configuration root could not be opened", Location{})
diagnostic.Primary = nil
return nil, sourceInfos(main.source), []Diagnostic{diagnostic}
return nil, sourceInfos(main.source), nil, []Diagnostic{diagnostic}
}
return acquireImportedWithAccess(request, policy, state, tier, access, resolved)
composition, sources, diagnostics := acquireImportedWithAccess(request, policy, state, tier, access, resolved)
if len(diagnostics) != 0 {
return composition, sources, nil, diagnostics
}
return composition, sources, &resolved, nil
}
func acquireImportedWithAccess(request importAcquisitionRequest, policy *acquisitionPolicy, loadState *acquisitionState, tier *tierAcquisitionState, access *filesystemAccess, resolved resolvedFilesystemContext) (*composedDocument, []SourceInfo, []Diagnostic) {

View File

@@ -156,7 +156,12 @@ func TestAcquiredContextsUseSelectedFileWhenSourceRecordsAreReordered(t *testing
{ID: "source-2", Path: canonicalTestPath(t, importedPath), Kind: SourceKindFile},
{ID: "source-1", Path: canonicalTestPath(t, mainPath), Kind: SourceKindFile},
}
contexts, diagnostic := contextsForAcquiredSources(File(mainPath), nil, nil, sources)
mainInfo := &SourceInfo{Path: canonicalTestPath(t, mainPath)}
resolved, diagnostic := resolveFilesystemContext(File(mainPath), nil, parsedSource{source: mainInfo}, nil)
if diagnostic != nil {
t.Fatalf("resolve main context: %#v", diagnostic)
}
contexts, diagnostic := contextsForResolvedSources(&resolved, sources)
if diagnostic != nil {
t.Fatalf("source contexts: %#v", diagnostic)
}
@@ -1443,7 +1448,8 @@ func testAcquireInput(request inputAcquisitionRequest, policy acquisitionPolicy,
}
func testAcquireImport(request importAcquisitionRequest, policy acquisitionPolicy, state *acquisitionState, tier *tierAcquisitionState) (*composedDocument, []SourceInfo, []Diagnostic) {
return acquireImportedInput(request, &policy, state, tier)
composition, sources, _, diagnostics := acquireImportedInput(request, &policy, state, tier)
return composition, sources, diagnostics
}
func testAcquireImportWithLimits(request importAcquisitionRequest, limits importLimits) (*composedDocument, []SourceInfo, []Diagnostic) {

View File

@@ -264,7 +264,15 @@ func executeLoadRequest[T any](request loadRequest[T], secrets SecretBinding, lo
}
}
if len(baseSources) != 0 && input.contexts[baseSources[0].ID].FS == nil {
contexts, diagnostic := contextsForAcquiredSources(request.main.source, request.main.filesystem, input.parsed.source, baseSources)
if input.resolvedFilesystem == nil && (request.main.source.kind == sourceFile || request.main.filesystem != nil || nativeContext(request.main.source, request.main.filesystem)) {
resolved, diagnostic := resolveFilesystemContext(request.main.source, request.main.filesystem, input.parsed, nil)
if diagnostic != nil {
accumulator.add(*diagnostic)
return nil, accumulator.loadError()
}
input.resolvedFilesystem = &resolved
}
contexts, diagnostic := contextsForResolvedSources(input.resolvedFilesystem, baseSources)
if diagnostic != nil {
accumulator.add(*diagnostic)
return nil, accumulator.loadError()

View File

@@ -7,62 +7,18 @@ import (
"strings"
)
func contextsForAcquiredSources(source Source, context *FilesystemContext, baseSource *SourceInfo, sources []SourceInfo) (map[string]ResourceContext, *Diagnostic) {
func contextsForResolvedSources(resolved *resolvedFilesystemContext, sources []SourceInfo) (map[string]ResourceContext, *Diagnostic) {
if len(sources) == 0 {
return nil, nil
}
var rootPath, basePath string
var filesystem fs.FS
if source.kind == sourceFilesystem {
filesystem = source.namespace.filesystem
rootPath, basePath = ".", path.Dir(source.path)
if context != nil && context.Root != "" {
rootPath = context.Root
}
} else if context != nil && context.FS != nil {
filesystem = context.FS.namespace.filesystem
rootPath, basePath = context.Root, context.BaseDir
} else if source.kind == sourceFile {
filePath := source.path
if baseSource != nil {
filePath = baseSource.Path
} else {
canonical, err := canonicalExistingPath(filePath)
if err != nil {
value := importDiagnostic(CodeImportInvalid, "selected source could not be canonicalized", nil)
return nil, &value
}
filePath = canonical
}
basePath = filepath.Dir(filePath)
rootPath = basePath
if context != nil && context.Root != "" {
canonical, err := canonicalExistingPath(context.Root)
if err != nil {
value := importDiagnostic(CodeImportInvalid, "configuration root could not be canonicalized", nil)
return nil, &value
}
rootPath = canonical
}
} else if context != nil {
var err error
rootPath, err = canonicalExistingPath(context.Root)
if err != nil {
value := importDiagnostic(CodeImportInvalid, "configuration root could not be canonicalized", nil)
return nil, &value
}
if source.kind == sourceNone && context.BaseDir == "" {
basePath = rootPath
} else {
basePath, err = canonicalExistingPath(context.BaseDir)
if err != nil {
value := importDiagnostic(CodeImportInvalid, "import base directory could not be canonicalized", nil)
return nil, &value
}
}
} else {
if resolved == nil {
return nil, nil
}
rootPath, basePath := resolved.rootPath, resolved.basePath
var filesystem fs.FS
if resolved.native != nil {
filesystem = resolved.native.filesystem
}
var rooted fs.FS
if filesystem != nil {
rooted = rootedNativeFS{filesystem: filesystem, root: rootPath}
@@ -81,7 +37,7 @@ func contextsForAcquiredSources(source Source, context *FilesystemContext, baseS
}
var relative string
if filesystem != nil {
if !fs.ValidPath(rootPath) || !fs.ValidPath(base) || rootPath != "." && base != rootPath && !strings.HasPrefix(base, rootPath+"/") {
if !containsNativePath(rootPath, base) {
value := importDiagnostic(CodeImportOutsideRoot, "source base is outside the configuration root", nil)
return nil, &value
}
@@ -110,6 +66,30 @@ func contextsForAcquiredSources(source Source, context *FilesystemContext, baseS
return result, nil
}
// contextsForAcquiredSources is retained for selected-overlay callers until
// their request migration. Input acquisition resolves the facts at its own
// lifecycle boundary and uses contextsForResolvedSources directly.
func contextsForAcquiredSources(source Source, context *FilesystemContext, baseSource *SourceInfo, sources []SourceInfo) (map[string]ResourceContext, *Diagnostic) {
if len(sources) == 0 {
return nil, nil
}
if source.kind == sourceNone {
if context == nil {
return nil, nil
}
resolved, diagnostic := resolveAbsentFilesystemContext(context)
if diagnostic != nil {
return nil, diagnostic
}
return contextsForResolvedSources(&resolved, sources)
}
resolved, diagnostic := resolveFilesystemContext(source, context, parsedSource{source: baseSource}, nil)
if diagnostic != nil {
return nil, diagnostic
}
return contextsForResolvedSources(&resolved, sources)
}
func mergeResourceContexts(target *map[string]ResourceContext, incoming map[string]ResourceContext) {
if len(incoming) == 0 {
return