diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md index b09aaf4..824ea52 100644 --- a/docs/roadmap/implementation.md +++ b/docs/roadmap/implementation.md @@ -716,6 +716,15 @@ destination accounting, item placement, and passive resource-context tests still exercise the same observable behavior. Do not require exact private helper calls. Focused check: `go test ./internal/engine -run 'Discovery|Destination|Source|Resource|Filesystem'`. +Status: **complete** (second part of F02). Prior completed commits: `2736ddf`, +`deb9aa5`, `ae3408a`, `ea27f17`, `08a8c25`, `877c497`, `8aba43d`, `7bf2f0c`, +`0f9ecf1`, `119b42c`, `247a12b`, `4fcff5f`, `12d350a`, `08f2a8f`, `826062a`, +`e4a5ecb`, `3122e2f`, `6f6130f`, `4fd3bee`, `4bf940c`, and `d8bf6ab`. Validation +passed: `env GOTOOLCHAIN=local GOPROXY=off GOTELEMETRY=off go test ./internal/engine -run 'Discovery|Destination|Source|Resource|Filesystem' -count=1`, +`env GOTOOLCHAIN=local GOPROXY=off GOTELEMETRY=off go test ./internal/engine -count=1`, +`env GOTOOLCHAIN=local GOPROXY=off GOTELEMETRY=off go test ./... -count=1`, +and `git diff --check`. + ## Stage 23 — Clarify Ordinary Context And Structural-Expansion Handoffs Finding: third part of **F02**. diff --git a/internal/engine/acquisition.go b/internal/engine/acquisition.go index f6e6bb1..5135974 100644 --- a/internal/engine/acquisition.go +++ b/internal/engine/acquisition.go @@ -37,8 +37,6 @@ func acquireInput(request inputAcquisitionRequest, policy acquisitionPolicy, sta destination := request.input.destination accounting := state.accounting versionState := state.versionState - visited := tier.visited - hostToken := tier.hostToken sourceID := "source-" + strconv.Itoa(accounting.sources+1) selectedSource := source if source.kind == sourceSearch { @@ -114,66 +112,86 @@ func acquireInput(request inputAcquisitionRequest, policy acquisitionPolicy, sta input.document = input.composition.root } } else { - input.sources = sourceInfos(parsed.source) - if versionProcessing != nil { - input.document = versionProcessing.payload - } - if request.input.filesystem != nil && (selectedSource.kind == sourceNone || !activeOverlay(request.ordinaryOverlay)) { - resolved, diagnostic := validateFilesystemContext(selectedSource, request.input.filesystem, parsed, tier.hostToken) - if diagnostic != nil { - return input, []Diagnostic{*diagnostic} - } - input.resolvedFilesystem = &resolved + input, diagnostics = acquireStandaloneInput(input, request, versionProcessing, policy, tier) + if len(diagnostics) != 0 { + return input, diagnostics } } - if !request.input.imports && input.document != nil { - _, placed, err := placeDocumentWithMode(input.document, destination, request.input.placementMode, input.document.Location, parseLimits.document.Depth, parseLimits.document.Nodes) - if err != nil { - return input, []Diagnostic{sourceDiagnostic(CodeSourceLimitExceeded, parsed.source.ID, "configuration exceeds the source depth or node limit after destination placement")} - } - localPayload := input.document - input.document = placed - identity := importKeyForMainSource(parsed.source) - var sequenceDeclarations []sequenceDeclarationSpec - if versionProcessing != nil { - sequenceDeclarations = cloneSequenceDeclarations(versionProcessing.sequences) - } - input.acquisition = []acquisitionScope{{ - owner: identity, - destination: destination.clone(), - contributions: []acquiredContribution{{ - source: cloneSourceInfo(*parsed.source), payload: localPayload, - identity: identity, role: importRoleMain, scopeOwner: identity, - document: placed, destination: destination.clone(), processing: versionProcessing, - sequenceDeclarations: sequenceDeclarations, - }}, - }} - rawNodes := countInputNodes(parsed.document) - placementNodes := destinationWrapperNodeCountForMode(destination, request.input.placementMode) - if accounting.sources+1 > limits.sources || accounting.bytes+parsed.bytes > limits.bytes || accounting.nodes+rawNodes+placementNodes > limits.nodes { - return input, []Diagnostic{sourceDiagnostic(CodeSourceLimitExceeded, parsed.source.ID, "configuration exceeds the aggregate input limit")} - } - if diagnostic := registerAcquiredSource(selectedSource, request.input.filesystem, parsed.source, visited, hostToken); diagnostic != nil { - return input, []Diagnostic{*diagnostic} - } - accounting.sources++ - accounting.bytes += parsed.bytes - accounting.nodes += rawNodes + placementNodes + return completeAcquisitionContexts(input, request, tier) +} + +func acquireStandaloneInput(input assembledInput, request inputAcquisitionRequest, processing *sourceVersionProcessingResult, policy acquisitionPolicy, tier *tierAcquisitionState) (assembledInput, []Diagnostic) { + parsed := input.parsed + input.sources = sourceInfos(parsed.source) + if processing != nil { + input.document = processing.payload } - if !activeOverlay(request.ordinaryOverlay) || request.input.imports { - 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 request.input.filesystem != nil && (input.source.kind == sourceNone || !activeOverlay(request.ordinaryOverlay)) { + resolved, diagnostic := validateFilesystemContext(input.source, request.input.filesystem, parsed, tier.hostToken) if diagnostic != nil { return input, []Diagnostic{*diagnostic} } - input.contexts = contexts + input.resolvedFilesystem = &resolved } + if request.input.imports || input.document == nil { + return input, nil + } + + limits := policy.importLimits + placement := request.input.destination + documentLimits := defaultParseLimits().document + _, placed, err := placeDocumentWithMode(input.document, placement, request.input.placementMode, input.document.Location, documentLimits.Depth, documentLimits.Nodes) + if err != nil { + return input, []Diagnostic{sourceDiagnostic(CodeSourceLimitExceeded, parsed.source.ID, "configuration exceeds the source depth or node limit after destination placement")} + } + localPayload := input.document + input.document = placed + identity := importKeyForMainSource(parsed.source) + var sequenceDeclarations []sequenceDeclarationSpec + if processing != nil { + sequenceDeclarations = cloneSequenceDeclarations(processing.sequences) + } + input.acquisition = []acquisitionScope{{ + owner: identity, + destination: placement.clone(), + contributions: []acquiredContribution{{ + source: cloneSourceInfo(*parsed.source), payload: localPayload, + identity: identity, role: importRoleMain, scopeOwner: identity, + document: placed, destination: placement.clone(), processing: processing, + sequenceDeclarations: sequenceDeclarations, + }}, + }} + rawNodes := countInputNodes(parsed.document) + placementNodes := destinationWrapperNodeCountForMode(placement, request.input.placementMode) + accounting := input.accounting + if accounting.sources+1 > limits.sources || accounting.bytes+parsed.bytes > limits.bytes || accounting.nodes+rawNodes+placementNodes > limits.nodes { + return input, []Diagnostic{sourceDiagnostic(CodeSourceLimitExceeded, parsed.source.ID, "configuration exceeds the aggregate input limit")} + } + if diagnostic := registerAcquiredSource(input.source, request.input.filesystem, parsed.source, tier.visited, tier.hostToken); diagnostic != nil { + return input, []Diagnostic{*diagnostic} + } + accounting.sources++ + accounting.bytes += parsed.bytes + accounting.nodes += rawNodes + placementNodes + return input, nil +} + +func completeAcquisitionContexts(input assembledInput, request inputAcquisitionRequest, tier *tierAcquisitionState) (assembledInput, []Diagnostic) { + if activeOverlay(request.ordinaryOverlay) && !request.input.imports { + return input, nil + } + if input.resolvedFilesystem == nil && len(input.sources) != 0 && (input.source.kind == sourceFile || request.input.filesystem != nil || nativeContext(input.source, request.input.filesystem)) { + resolved, diagnostic := resolveFilesystemContext(input.source, request.input.filesystem, input.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} + } + input.contexts = contexts return input, nil }