make-identity-episode13-demo.sh bash
97 lines 3.1 KB
Raw
sha256:5472be4fece32b606c308fad9d57295ce327955fb2b87b8beec6ea1626050473 Add published YouTube URL to Episode 00 Sonnet 5 9 hours ago
1 #!/usr/bin/env bash
2 # Builds identity-episode13/ — a disposable repo demonstrating real
3 # per-agent Ed25519 identity injection for Episode 13 ("Agents Are
4 # First-Class Citizens"). Re-run to regenerate; never hand-edit the repo
5 # directory itself.
6 set -euo pipefail
7
8 HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
9 REPO="$HERE/identity-episode13"
10
11 rm -rf "$REPO"
12 mkdir -p "$REPO"
13 cd "$REPO"
14
15 muse init --json | python3 -m json.tool
16 echo "hello" > README.md
17 muse code add README.md
18 muse commit -m "Initial commit" --agent-id claude-code --model-id claude-sonnet-5 --json | python3 -m json.tool
19
20 echo
21 echo "=== Deriving an operator identity and a scoped agent sub-seed ==="
22 python3 - <<'PY'
23 import os
24 import sys
25 sys.path.insert(0, "/Users/gabriel/ecosystem/muse")
26 from muse.core.hdkeys import (
27 derive_agent_sub_seed, derive_identity_key, DOMAIN_IDENTITY, ENTITY_HUMAN,
28 )
29 from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
30
31 # Throwaway 64-byte seed for this demo -- never a real operator mnemonic.
32 operator_seed = os.urandom(64)
33
34 operator_dk = derive_identity_key(operator_seed, entity_type=ENTITY_HUMAN)
35 operator_priv = Ed25519PrivateKey.from_private_bytes(operator_dk.private_bytes)
36 operator_pub = operator_priv.public_key().public_bytes_raw()
37
38 # Scoped sub-seed for agent slot 0 -- SLIP-0010 hardened, cannot derive
39 # the operator's own key or any other domain's keys.
40 agent_sub_seed = derive_agent_sub_seed(operator_seed, domain=DOMAIN_IDENTITY, agent_id=0)
41
42 print("operator pubkey:", operator_pub.hex())
43 with open("sub_seed.bin", "wb") as f:
44 f.write(agent_sub_seed)
45 PY
46
47 echo
48 echo "=== Injecting the sub-seed through a real pipe fd (never an env var) ==="
49 muse code add README.md 2>/dev/null || true
50 echo "hello v2" > README.md
51 muse code add README.md
52 python3 - <<'PY'
53 import os
54 import sys
55
56 with open("sub_seed.bin", "rb") as f:
57 sub_seed = f.read()
58 assert len(sub_seed) == 64
59
60 read_fd, write_fd = os.pipe()
61 os.set_inheritable(read_fd, True)
62
63 pid = os.fork()
64 if pid == 0:
65 os.close(write_fd)
66 env = dict(os.environ)
67 env["MUSE_AGENT_KEY_FD"] = str(read_fd)
68 env["MUSE_AGENT_HANDLE"] = "agent-slot-0"
69 os.execvpe("muse", ["muse", "commit", "-m", "Agent-signed commit via pipe fd",
70 "--agent-id", "claude-code", "--model-id", "claude-sonnet-5",
71 "--sign", "--json"], env)
72 else:
73 os.close(read_fd)
74 os.write(write_fd, sub_seed)
75 os.close(write_fd)
76 _, status = os.waitpid(pid, 0)
77 sys.exit(os.waitstatus_to_exitcode(status))
78 PY
79
80 echo
81 echo "=== Confirming the agent's key is real, unique, and verifies ==="
82 muse read --json | python3 -c "import json,sys; print('signer_public_key:', json.load(sys.stdin)['signer_public_key'])"
83 muse verify-commit HEAD --json | python3 -m json.tool
84
85 rm -f sub_seed.bin
86
87 echo
88 echo "=== The provenance-vs-cryptography distinction, across the real season ==="
89 cd ~/ecosystem/muse
90 muse shortlog --group-by model --json | python3 -c "
91 import json, sys
92 d = json.load(sys.stdin)
93 for g in d['groups']:
94 print(f\"{g['key']:<20} {g['count']}\")
95 "
96
97 echo "Demo repo built at $REPO"
File History 1 commit
sha256:5472be4fece32b606c308fad9d57295ce327955fb2b87b8beec6ea1626050473 Add published YouTube URL to Episode 00 Sonnet 5 9 hours ago