package config import ( "path/filepath" configkit "gitea.maximumdirect.net/eric/ConfigKit" ) // LoadOptions contains configuration selections supplied by an application // boundary. It is intentionally narrow: configuration discovery and CLI flag // parsing remain outside this package. type LoadOptions struct { Profile string Overrides []configkit.Override InvocationDirectory string } // loadDocument composes and validates a version 5 file with ConfigKit before // runtime conversion, retaining source provenance and frozen inspection output. func loadDocument(path string, options LoadOptions) (*configkit.Result[Document], error) { return loadDocumentWithSource(configkit.File(path), options, true) } func loadDocumentSource(source configkit.Source, options LoadOptions) (*configkit.Result[Document], error) { return loadDocumentWithSource(source, options, false) } func loadDocumentWithSource(source configkit.Source, options LoadOptions, imports bool) (*configkit.Result[Document], error) { state := newDocumentLoadState(options.InvocationDirectory) return configkit.Load(source, configkit.Options[Document]{ Definition: documentDefinition(state), Imports: imports, Profile: options.Profile, Overrides: options.Overrides, }) } func cleanInvocationDirectory(value string) string { if value == "" { return "" } absolute, err := filepath.Abs(value) if err != nil { return "" } return filepath.Clean(absolute) } func documentDefinition(state *documentLoadState) configkit.Definition[Document] { return configkit.Definition[Document]{ Defaults: documentDefaults, Resolve: func(document *Document, resolution *configkit.Resolution) error { return resolveDocumentOperations(document, resolution, state) }, Validate: validateDocumentOperations, Version: &configkit.VersionRule{ Path: configkit.Keys("version"), Check: validateDocumentVersion, }, Secret: sensitiveDocumentPath, } } func documentDefaults() Document { return Document{ Pipelines: map[string]PipelineDocument{}, Concurrency: &ConcurrencyDocument{ TotalLLM: documentValue(defaultLLMConcurrency), StageWorkers: map[string]int{}, }, Output: &OutputDocument{Directory: documentValue("./notarius-output")}, Cache: &CacheDocument{ ChunkPlans: &ChunkPlanCacheDocument{ Directory: documentValue(""), Mode: documentValue("auto"), }, Checkpoints: &CheckpointCacheDocument{ Enabled: documentValue(false), Directory: documentValue(""), }, }, Debug: &DebugDocument{Directory: documentValue("./notarius-debug")}, } } func documentValue[T any](value T) *T { return &value } func validateDocumentVersion(version configkit.Version, validation *configkit.Validation) error { if !version.Present || version.Null { validation.Error(configkit.Keys("version"), "configuration version is required") return nil } if version.Text == "4" { validation.Error(configkit.Keys("version"), "configuration version 4 is no longer supported; migrate to version 5") return nil } if version.Text != "5" { validation.Error(configkit.Keys("version"), "unsupported configuration version") } return nil }