#!/usr/bin/env python3 """Write architecture-evidence.txt: the reviewer's index into the pack. It resolves a named symbol list against this checkout and prints where each one is, or says plainly that it does not exist. A requested name that is absent is evidence too, so nothing here is silently dropped or silently corrected. Every contradiction is re-checked at generation time by running its own probe, so the claim and the grep that supports it cannot drift apart in the pack. python3 docs/architecture/build_evidence.py """ import os import re import subprocess import sys HERE = os.path.dirname(os.path.abspath(__file__)) ROOT = os.path.abspath(os.path.join(HERE, "..", "..")) TREES = ["cmd", "internal"] # The reviewer's list, verbatim on the left. Where a name does not exist in this # repo, the right side is what it appears to mean. Resolution below reports both # so a wrong name is visible rather than quietly fixed. REQUESTED = [ ("auth.TierFor", "auth.MaxLayer"), ("auth.Surface", None), ("auth.Layer", None), ("tool.Executor.Exec", None), ("tool.PolicyFor", None), ("tool.RiskOf", None), ("tool.RiskSafe", "tool.TierSafe"), ("tool.RiskDestructive", "tool.TierDestructive"), ("tool.RiskIrreversible", "tool.TierIrreversible"), ("router.ClaimOf", None), ("reactiveHandler", None), ("tickLoop", None), ] # Added because the authorization function the reviewer wants to reconstruct # runs through these and the list above does not reach them. ALSO = [ "auth.Gate", "auth.Can", "auth.Requirement", "auth.Authority", "auth.NewFloorEnrollment", "auth.StaticEnrollment", "auth.Scope", "tool.Policy", "tool.RiskOfCapability", "tool.irreversibleVerbs", "tool.ErrNeedsConfirm", "tool.ErrNeedsAuthedSurface", "tool.ErrNotEnabled", "ipc.Server.Check", "ipc.CheckFunc", "voice.PushToTalkReq", "voice.Sessions.Add", "voice.Session", "PolicyFor", "RiskOf", "Executor.Exec", "pendingAct", "resolveConfirm", "actionAct", "runTurn", "applyAction", "querySources", "queryWalk", "StageZeroGrammars", "Router.Route", ] PKG_DIR = { "auth": "internal/auth", "tool": "internal/tool", "claim": "internal/claim", "modes": "internal/modes", "router": "internal/router", "voice": "internal/voice", "ipc": "internal/ipc", "store": "internal/store", } def go_files(rel): full = os.path.join(ROOT, rel) out = [] for base, _, names in os.walk(full): for n in sorted(names): if n.endswith(".go"): out.append(os.path.relpath(os.path.join(base, n), ROOT)) return sorted(out) def all_go(): out = [] for t in TREES: out.extend(go_files(t)) return out _CACHE = {} def lines_of(rel): """Read once. resolve() sweeps every file per pattern per symbol, and re-reading cmd/ and internal/ that many times took minutes.""" if rel not in _CACHE: try: _CACHE[rel] = open(os.path.join(ROOT, rel), errors="replace").read().splitlines() except OSError: _CACHE[rel] = [] return _CACHE[rel] def resolve(sym): """Find the declaration of sym. Returns (path, line, text) or (None,)*3.""" tail = sym.split(".")[-1] recv = sym.split(".")[-2] if sym.count(".") >= 1 else None pats = [ re.compile(r"^func\s+\(\w+\s+\*?" + re.escape(recv or "\x00") + r"\)\s+" + re.escape(tail) + r"\b"), re.compile(r"^func\s+" + re.escape(tail) + r"\b"), re.compile(r"^type\s+" + re.escape(tail) + r"\b"), re.compile(r"^\s*" + re.escape(tail) + r"\s+\w+\s*=\s"), # typed const re.compile(r"^\s*" + re.escape(tail) + r"\s*=\s"), re.compile(r"^(var|const)\s+" + re.escape(tail) + r"\b"), re.compile(r"^\s*" + re.escape(tail) + r"\s+\w"), # struct field ] pkg = sym.split(".")[0] files = go_files(PKG_DIR[pkg]) if pkg in PKG_DIR else all_go() files = [f for f in files if not f.endswith("_test.go")] for pat in pats: for rel in files: for i, line in enumerate(lines_of(rel), 1): if pat.match(line): return rel, i, line.strip() return None, None, None def exported(pkg_rel): """Every exported declaration in a package, for the `claim.*` / `modes.*` asks.""" out = [] pat = re.compile(r"^(func|type|const|var)\s+\(?[^)]*\)?\s*([A-Z]\w*)") fn = re.compile(r"^func\s+(\([^)]*\)\s*)?([A-Z]\w*)") for rel in go_files(pkg_rel): if rel.endswith("_test.go"): continue for i, line in enumerate(lines_of(rel), 1): m = fn.match(line) or pat.match(line) if m: name = m.group(m.lastindex) if name and name[0].isupper(): out.append((name, f"{rel}:{i}", line.strip())) return out def sh(cmd): return subprocess.run(cmd, shell=True, cwd=ROOT, capture_output=True, text=True).stdout.strip() # Each probe is a shell command whose output IS the evidence. Re-run at pack # time so the pack cannot claim something the checkout no longer shows. CONTRADICTIONS = [ ("auth surface/layer documented as control, not consumed on turn path", # px.Surface is the Praxis lifecycle verb, an unrelated name collision, and # Surfaced* are the read-out-item helpers. Excluded by name so the absence # this probe reports is the auth Surface and not a filtering accident. "grep -rnE 'req\\.Surface|sess\\.Surface|Session\\.Surface|auth\\.Surface|voice\\.Surface' cmd/mavend/*.go " "| grep -v _test | grep -vE 'px\\.Surface|Surfaced' " "|| echo '(no match: no file in cmd/mavend reads the auth Surface of a request or a session)'"), ("auth.Can runs only behind the IPC boundary", "grep -rn 'auth\\.' cmd/ internal/ --include='*.go' | grep -v _test " "| grep -v '^internal/auth/' | grep -vE ':[0-9]+:\\s*(//|\\*)'"), ("tool risk policy live on execution path", "sed -n '176,190p' internal/tool/tool.go"), ("tool executor receives no reach/surface", "grep -n 'func (e \\*Executor) Exec' internal/tool/tool.go"), ("voice server normalizes incoming surface to pc-client", "grep -n 'SurfacePCClient' internal/voice/server.go"), ("claim abstraction exists but Route does not consume it", "grep -rn 'ClaimOf' --include='*.go' cmd internal | grep -v _test || echo '(only the definition; no caller)'"), ("modes package is imported by nothing", "grep -rn 'internal/modes' --include='*.go' cmd internal | grep -v '^internal/modes/' || echo '(no importer)'"), ("voice server DEFAULTS an empty surface, it does not overwrite a sent one", "sed -n '193,201p' internal/voice/server.go"), ("session surface is hardcoded, independently of the request field", "sed -n '146,149p' internal/voice/server.go"), ("HandlePushToTalk never reads req.Surface", "sed -n '200,203p' cmd/mavend/voice.go"), ("hexis reuses the same risk policy", "grep -n 'RiskOfCapability\\|PolicyFor' cmd/mavend/ecosystem_acts.go"), ("praxis lifecycle mutations bypass the risk policy entirely", "sed -n '156,172p' cmd/mavend/ecosystem_acts.go"), ("Exec trusts a confirmed bool it cannot verify was bound", "grep -n 'func (e \\*Executor) Exec' internal/tool/tool.go; grep -rn 'tools.Exec(' cmd/mavend/*.go | grep -v _test"), ("FloorEnrollment maps every same-uid caller to one surface", "sed -n '63,72p' internal/auth/enrollment.go"), ("PasskeySession ignores Scope in both methods", "grep -n 'func (s \\*PasskeySession) CurrentLayer\\|func (s \\*PasskeySession) Assert' internal/webauthn/session.go"), ("Claim.Coverage can be 1.0 with nothing extracted", "grep -n 'func claimSpans' -A 4 internal/router/claim.go; grep -n 'd.Slots.Text = ex.Text' -B 2 internal/router/router.go; grep -n 'func (c Claim) Coverage' -A 7 internal/claim/claim.go"), ("claim_test asserts Band only, and every case sets Text == Utterance", "grep -n 'Utterance:\\|Text:\\|want:' internal/router/claim_test.go | head -20"), ("systemctl reboot is destructive, not irreversible", "grep -n 'irreversibleVerbs = map' -A 8 internal/tool/risk.go; grep -n 'reboot' deploy/mavend.json"), ] def main() -> int: out = [] w = out.append w("architecture evidence pack") w("=" * 72) w("") w("commit: " + sh("git rev-parse HEAD")) w("date: " + sh("git log -1 --format=%cd --date=short")) w("branch: " + sh("git rev-parse --abbrev-ref HEAD")) w("") w("working tree at pack time (git status --short):") for line in (sh("git status --short") or "(clean)").splitlines(): w(" " + line) w("") w("The pack is built from the WORKING TREE, not from the commit. The lines") w("above are the difference. deploy/mavend.json in particular is modified:") w("phraser.model_path points at maven-instruct-b2, the committed value was") w("Qwen3-1.7B-UD-Q4_K_XL. Sixteen 'configured-off' claims read this file.") w("") w("requested symbols") w("-" * 72) for name, actual in REQUESTED: rel, line, text = resolve(name) if rel: w(f"- {name}") w(f" {rel}:{line} {text}") elif actual: arel, aline, atext = resolve(actual) w(f"- {name} -> DOES NOT EXIST in this repo") if arel: w(f" the name appears to be {actual}") w(f" {arel}:{aline} {atext}") else: w(f" and neither does {actual}") else: w(f"- {name} -> NOT FOUND") w("") for pkg, rel in (("claim.*", "internal/claim"), ("modes.*", "internal/modes")): w(f"{pkg} ({rel})") w("-" * 72) for name, anchor, text in exported(rel): w(f"- {name}") w(f" {anchor} {text}") w("") w("additional symbols on the authorization path") w("-" * 72) for name in ALSO: rel, line, text = resolve(name) w(f"- {name}") w(f" {rel}:{line} {text}" if rel else " NOT FOUND") w("") w("known contradictions, each re-checked at pack time") w("=" * 72) w("The command under each claim was run against this checkout just now.") w("Its output is what follows. Nothing here is transcribed by hand.") w("") for claim, cmd in CONTRADICTIONS: w("- " + claim) w(" $ " + cmd) res = sh(cmd) for line in (res or "(no output)").splitlines(): w(" " + line) w("") w("what the pack does NOT contain, and why") w("=" * 72) w("- .git, so no history and no gitignored working files travel with it.") w("- deploy/telegram.env and deploy/db_key.env. The second holds the") w(" database key. Both are gitignored and present in the working tree.") w("- docker-compose.yml verbatim. It carries one live-looking credential on") w(" line 132 (an uptime-kuma API key). The pack ships") w(" docker-compose.redacted.yml with that one value replaced and nothing") w(" else changed, so the mavcaldav and mavmaild claims stay checkable.") w("- models/, deps/, *.db, *.onnx, *.gguf, certs, logs, node_modules.") w("- internal/session, internal/db and tests/ from the requested list: none") w(" of the three exists. Sessions live in internal/voice/session.go, the") w(" store is internal/store, and tests sit beside their code as *_test.go.") w("") w("included test files, since the ask named them by subject:") for pat, label in ( ("internal/router", "routing and arbitration"), ("internal/tool", "risk and confirmation"), ("internal/auth", "authorization"), ("internal/claim", "claim"), ("cmd/mavend", "turn path, confirm gate, query chain"), ): n = sh(f"find {pat} -name '*_test.go' | wc -l") w(f" {label}: {n} *_test.go under {pat}/") w("") w("fixtures are synthetic, not captured speech: internal/router/eval/*.json") w("and cmd/mavend/testdata/**.json are hand-written contracts. Named here") w("because they are Russian utterances and look like personal data.") path = os.path.join(HERE, "architecture-evidence.txt") open(path, "w").write("\n".join(out) + "\n") print(f"architecture-evidence.txt: {os.path.getsize(path)} bytes, {len(out)} lines") return 0 if __name__ == "__main__": sys.exit(main())