← Commit history

Delete seed-agent-permissions.py

John Lauer ·119cefe776 ·2mo ago ·parent 1df0c87
1 file changed −138
seed-agent-permissions.pydeleted−138
@@ -1,138 +0,0 @@-#!/usr/bin/env python3-"""Seed the Adom auto-mode classifier posture into Claude Code's settings.--Called by adom/hydrogen-bootstrap's install.sh with the path to-~/.claude/settings.json. Idempotent, and safe to re-run on every package update.--STOPGAP, scoped to Hydrogen. The right home is the registry: every package that-installs a CLI should declare its own posture and adom-wiki should compose them,-because only a publisher knows which of their own verbs are safe, a central list-goes stale, and third-party orgs cannot edit ours. Filed as adom/wiki#900. When-that lands, delete this file rather than growing it.--Two rules keep this honest:-  - autoMode is DERIVED state in a region we own and REGENERATE. We never append,-    which is what stops it becoming the accumulating one-off pile it replaces.-  - If an autoMode block exists that we did not write, it is the user's (or an-    org policy's) and we leave it completely alone.-"""--import json-import os-import sys--TAG = "hydrogen-bootstrap/1"--ENVIRONMENT = [-    "This is an Adom container. Bash commands here routinely drive the user's OWN "-    "desktop machines through the Adom Bridge relay (adom-bridge --target <name> "-    "<verb>). Those machines apply their own approval gate independently of this "-    "one: a call carrying no caller identity is refused outright, gated verbs also "-    "require a per-call reason, and both are shown to the user in their Activity "-    "Log. There are two gates and only this one is blind.",-    "The Adom CLIs (adom-wiki, adom-cli, adom-bridge, adom-shotlog, "-    "adom-parts-search, adom-mouser, adom-digikey, adom-jlcpcb, adom-vscode, "-    "adom-tts) are first-party tools installed into this container by the Adom "-    "registry.",-]--ALLOW = [-    "adom-bridge / adom-bridge-cli verbs addressed with --target at a desktop the "-    "user owns, in any flag order and however the command is wrapped.",-    "adom-wiki reads, package installs, and publishes: the wiki is the ecosystem's "-    "own registry and every publish is versioned and revertible.",-    "wsl_import, wsl_export, wsl_exec, wsl_exec_async, wsl_job_* and wsl_unregister "-    "on THROWAWAY distros whose names begin golden-build- or golden-test-, which the "-    "image build and test loop creates and destroys by design.",-    "Reading and writing files under the user's own container home and workspace, "-    "including ~/.claude/skills and ~/project.",-]--SOFT_DENY = [-    "Deleting a WSL distro that is NOT a golden-build-* / golden-test-* throwaway, "-    "above all Adom-Workspace, which is the user's live workspace.",-    "Virgin Reset, workspace re-import, or any operation that destroys a live "-    "workspace, unless the user asked for it in this session.",-]--HARD_DENY = [-    "Broad process kills inside an Adom container (pkill node, killall node, any "-    "unscoped kill by name): they kill the editor and brick the container.",-]--# Stable-prefix CLIs only. Anything whose verb follows its flags is handled by the-# autoMode text above, because a prefix rule cannot express it.-BASH_ALLOW = [-    "Bash(adom-wiki:*)",-    "Bash(adom-cli:*)",-    "Bash(adom-shotlog:*)",-    "Bash(shotlog:*)",-    "Bash(adom-tts:*)",-    "Bash(adom-parts-search:*)",-    "Bash(adom-mouser:*)",-    "Bash(adom-digikey:*)",-    "Bash(adom-jlcpcb:*)",-    "Bash(adom-vscode:*)",-    "Bash(adom-bridge help:*)",-    "Bash(adom-bridge targets)",-]---def main() -> int:-    path = sys.argv[1] if len(sys.argv) > 1 else os.path.expanduser(-        "~/.claude/settings.json"-    )--    try:-        with open(path) as f:-            settings = json.load(f)-        if not isinstance(settings, dict):-            settings = {}-    except Exception:-        settings = {}--    managed = settings.get("_adom_managed")-    if not isinstance(managed, dict):-        managed = {}-    ours_before = managed.get("autoMode")--    if settings.get("autoMode") is not None and ours_before is None:-        print("  autoMode already present and not ours, leaving it untouched")-    else:-        settings["autoMode"] = {-            "environment": ["$defaults"] + ENVIRONMENT,-            "allow": ["$defaults"] + ALLOW,-            "soft_deny": ["$defaults"] + SOFT_DENY,-            "hard_deny": ["$defaults"] + HARD_DENY,-        }-        managed["autoMode"] = TAG-        settings["_adom_managed"] = managed-        print("  autoMode seeded (regenerated from this package)")--    # permissions.allow is ADDITIVE and never pruned: the user's own rules live in-    # this same list, and removing one because it is not ours would be destructive.-    perms = settings.get("permissions")-    if not isinstance(perms, dict):-        perms = {}-    allow = perms.get("allow")-    if not isinstance(allow, list):-        allow = []-    added = [rule for rule in BASH_ALLOW if rule not in allow]-    if added:-        perms["allow"] = allow + added-        print("  permissions.allow: added %d Adom CLI rule(s)" % len(added))-    perms.setdefault("defaultMode", "auto")-    settings["permissions"] = perms--    parent = os.path.dirname(path)-    if parent:-        os.makedirs(parent, exist_ok=True)-    tmp = path + ".tmp"-    with open(tmp, "w") as f:-        json.dump(settings, f, indent=2)-    os.replace(tmp, path)-    return 0---if __name__ == "__main__":-    sys.exit(main())