generated from coulomb/repo-seed
feat(explain): implement ATLAS-WP-0004 T01+T02 — effective-config resolver + config explain
Some checks failed
validate-registry / validate (push) Has been cancelled
Some checks failed
validate-registry / validate (push) Has been cancelled
Activate WP-0003 and WP-0004. Add tools/effective_config.py (deterministic, order-independent override-path resolver — path only, never a value) and tools/config_explain.py + `make explain` to render the layer path, winning layer, validator, owner, consumers, and secret references for any surface.*. Verified on all 4 seeded surfaces; order-independent; no values/secrets leak. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
65
tools/config_explain.py
Normal file
65
tools/config_explain.py
Normal file
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env python3
|
||||
"""`config explain <surface-id>` (ATLAS-WP-0004-T02).
|
||||
|
||||
Render the effective-config override PATH for a configuration surface as a
|
||||
human/agent-readable view. Shows which layer wins, what it overrode, the
|
||||
validating schema, owner, and consumers -- never a resolved or secret value.
|
||||
|
||||
Usage:
|
||||
python3 tools/config_explain.py surface.infotech.state-hub.api-config
|
||||
make explain SURFACE=surface.infotech.state-hub.api-config
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
|
||||
from effective_config import OverridePath, find_entry, resolve_path
|
||||
|
||||
|
||||
def render(op: OverridePath) -> str:
|
||||
lines: list[str] = []
|
||||
lines.append(f"config explain {op.surface_id}")
|
||||
lines.append("")
|
||||
lines.append(f" {op.name}")
|
||||
lines.append(f" kind: {op.kind} owner: {op.owner} mutability: {op.mutability} class: {op.security_class}")
|
||||
if op.allowed_layers:
|
||||
lines.append(f" allowed layers: {', '.join(op.allowed_layers)} default: {op.default_layer}")
|
||||
lines.append("")
|
||||
lines.append(" effective layer path (most-specific wins):")
|
||||
if not op.contributions:
|
||||
lines.append(" (no sources declared)")
|
||||
for c in op.contributions:
|
||||
layer = c.layer if c.layer else f"[{c.role}]"
|
||||
marker = " <== winning" if c.winning else ""
|
||||
over = f" (overrides {c.overrides})" if c.overrides else ""
|
||||
lines.append(f" {layer:<16} {c.ref}{over}{marker}")
|
||||
lines.append("")
|
||||
if op.validator:
|
||||
lines.append(f" validated by: {op.validator}")
|
||||
if op.consumers:
|
||||
lines.append(f" consumed by: {', '.join(op.consumers)}")
|
||||
if op.secret_deps:
|
||||
lines.append(f" depends on secret (ref): {', '.join(op.secret_deps)}")
|
||||
if op.related:
|
||||
lines.append(f" related: {', '.join(op.related)}")
|
||||
for note in op.notes:
|
||||
lines.append(f" · {note}")
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def main(argv: list[str]) -> int:
|
||||
if len(argv) != 1:
|
||||
print(__doc__)
|
||||
return 2
|
||||
surface_id = argv[0]
|
||||
try:
|
||||
entry = find_entry(surface_id)
|
||||
except FileNotFoundError as exc:
|
||||
print(f"error: {exc}", file=sys.stderr)
|
||||
return 1
|
||||
print(render(resolve_path(entry)))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main(sys.argv[1:]))
|
||||
Reference in New Issue
Block a user