Files
Agent-System/internal/config/explain.go
T
agent-bot 93ab4802e9
CI / go-vet (pull_request) Successful in 13s
CI / short-tests-report (pull_request) Failing after 36s
CI / backup-restore-drill (pull_request) Successful in 37s
CI / web (pull_request) Successful in 32s
feat(config): field-level source attribution via layer snapshots (U10b core 1/2)
- LoadWithSources: reflection snapshots at layer boundaries (default ->
  env-file per file -> process-env incl. DSN/CORS/KB normalization); diff
  yields exact per-field source - no manual key registry, no drift
- Load unchanged signature/behavior (wrapper); ApplyCLIOverlay records the
  cli layer on a cloned config
- 'config explain' upgraded to field table (59 fields; source + set flag
  only, values never printed per KTD17)
- replaces the reporting-only key registry from PR #12
- tests: layer attribution (file/process override), cli overlay, Load regression
2026-09-29 08:06:06 +00:00

53 lines
1.3 KiB
Go

package config
import (
"bufio"
"fmt"
"os"
"sort"
"strings"
)
// ParseEnvFileKeys 用与 applyEnvFile 相同的解析规则列出文件中出现的键。
func ParseEnvFileKeys(path string) ([]string, error) {
f, err := os.Open(path)
if err != nil {
return nil, err
}
defer f.Close()
var keys []string
scanner := bufio.NewScanner(f)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if line == "" || strings.HasPrefix(line, "#") {
continue
}
parts := strings.SplitN(line, "=", 2)
if len(parts) != 2 {
continue
}
keys = append(keys, strings.TrimSpace(parts[0]))
}
return keys, scanner.Err()
}
// FormatFieldSources 渲染字段级来源表(KTD17:只报告来源/状态,不打印值)。
func FormatFieldSources(entries []FieldSource) string {
var b strings.Builder
b.WriteString("field layer set\n")
for _, e := range entries {
fmt.Fprintf(&b, "%-37s %-19s %v\n", e.Field, e.Layer, e.Set)
}
return b.String()
}
// SortedFieldSourceNames 返回已知来源字段名(测试辅助)。
func SortedFieldSourceNames(m map[string]FieldSource) []string {
names := make([]string, 0, len(m))
for k := range m {
names = append(names, k)
}
sort.Strings(names)
return names
}