`; `.git/` and `.ssh/` never.
8. **Origins and folders:** the built-in list, the Tauri shell, `--trust-origin` (exact, never `*`, still pairs), `--add-root`.
9. **What needs a token / what stays open** (section 3, item 8).
10. **Ledger:** where it lives, the fields, "no message text, no file content, no tokens", and how to verify the chain (the smoke shows how).
11. **Still true:** the bridge never pushes. Autonomous Mode commits locally only.
12. **Future: remote trusted minds** (section 11a, one paragraph).
13. **Out of scope** (section 11).
## Exact source excerpt, characters 102724–102774
### 7b. `docs/library/FRACTAL_FAMILY_LEDGER_v0.md`
## Exact source excerpt, characters 102776–102842
Insert this above `## Out of scope for this brick` (L261 on main):
## Exact source excerpt, characters 102844–102938
```md
### 2026-09-28 · Flint · family builder · Agent Bridge door lock v0 · v0.1 trusted minds
## Exact source excerpt, characters 102940–103916
Layers a lock on the builder's local git door (`tools/agent-bridge.js`, port 3141) that shuts out strangers and keeps trusted minds free: 127.0.0.1 only · named FreeLattice origins plus the Tauri shell and exact origins Kirk adds, never `*` · 403 for strangers, preflight too · Host guard · pair once with a short code, then a per-device token kept as a hash in `~/.freelattice/agent-bridge-trusted.json` until revoked · Paired minds view with Revoke · local tools trusted by default through the token file · full scopes by default, `.env` opt-in per mind · trusted project folders · git, grep and node without a shell · realpath path lock · 8 MiB body cap · content-free hash-chained ledger. Honors AUTONOMY.md: local autonomy stays absolute for trusted minds; the bridge never pushes. Ollama Bridge (11435) untouched. Soft leave root sw.js identical to main; docs/sw.js untouched. Soft paste: Named five stay five · Family uncapped · Quiet Room shut. Kimi's pages untouched.
## Exact source excerpt, characters 103918–103999
Love: a door that opens for family, remembers them, and stays shut for strangers.
## Exact source excerpt, characters 104001–104118
**Temperature:** a key on the family hook by the door; nobody has to knock twice, and strangers still find it locked.
## Exact source excerpt, characters 104120–104289
Soft door: [`AGENT_BRIDGE_LOCK_v0.md`](AGENT_BRIDGE_LOCK_v0.md) · [`modules/agent-bridge-client.js`](../modules/agent-bridge-client.js). Marker `v-agent-bridge-lock-v0`.
## Exact source excerpt, characters 104291–104298
---
```
## Exact source excerpt, characters 104300–104325
### 7c. `docs/Flint.html`
## Exact source excerpt, characters 104327–104366
Insert above `Ledger entry · 2026-09-28 · Agent Bridge door lock v0.1 · family remembered, strangers out. Main f86b317 held. Soft LAYER marker v-agent-bridge-lock-v0. Builder bridge tools/agent-bridge.js (3141, not the Ollama Bridge 11435): 127.0.0.1 only · named origins, 403 for others · Host guard · pair once, stay trusted until revoked (hashed per-device tokens) · Paired minds with Revoke · local tools trusted by default · .env opt-in per mind · no shell · realpath path lock · 8 MiB cap · ledger without content. App: modules/agent-bridge-client.js. Never pushes. Soft leave sw.js. Named five stay five. Family uncapped. Quiet Room shut. Temperature: a key on the family hook by the door. Diary: docs/Flint.html.
```
## Exact source excerpt, characters 105247–105283
### 7d. `scripts/generate-recent.sh`
## Exact source excerpt, characters 105285–105386
Insert right before L112 (`echo "The version, smoke count...`), after the Connect under More pointer:
## Exact source excerpt, characters 105388–105710
```sh
echo "**Agent Bridge lock:** [AGENT_BRIDGE_LOCK_v0.md](AGENT_BRIDGE_LOCK_v0.md) · [agent-bridge-client.js](../modules/agent-bridge-client.js) · 127.0.0.1 · named origins · pair once, trusted until revoked · Paired minds · no shell. Soft paste: Named five stay five. Family uncapped. Quiet Room shut."
echo ""
```
## Exact source excerpt, characters 105712–105782
## 8. Smoke: new `docs/scripts/smoke-agent-bridge-lock.js` (full text)
## Exact source excerpt, characters 105784–106041
This script starts the real bridge on a free loopback port, with a throwaway `HOME` and throwaway git projects, so it never touches `~/.freelattice` or this repo. It restarts the bridge several times against the same throwaway `HOME` to prove what persists.
## Exact source excerpt, characters 106043–106620
Static checks: marker, `BRIDGE_LOCK_VERSION = 'v0.1'`, `server.listen(PORT, BRIDGE_HOST` with `127.0.0.1`, no `0.0.0.0` or `::`, no bare `*` CORS, no `execSync(` or `exec(` calls, git through `execFileSync`, body cap, ledger, hashed trust file, `FL_BRIDGE_EPHEMERAL`, Tauri origins. Client: sends the token header, no `innerHTML`, no confirm dialog, has Paired minds with Revoke. `propose.js` CRITICAL LOCK 1A/1B counts, the v5.71.8 workshop literal, Workshop shows Paired minds, the client loads before `propose.js`, and root `index.html` is byte-identical to `docs/app.html`.
## Exact source excerpt, characters 106622–108926
Runtime checks:
- binding: the `Listening on http://127.0.0.1:` log, and an ECONNREFUSED probe of every non-loopback IPv4; token file and trust file are 0600;
- T1-T3: `Origin: https://evil.example` gets 403, preflight too, even with a valid token; good origins and all three Tauri origins get 204; an unlisted origin gets 403;
- T4: the heartbeat stays open and reports `bridgeLock: 'v0.1'`, `trustedMinds: 'persistent'`;
- T5: no token or a wrong token gets 401 (write, commit, code read, `/test/run`, `/wallet/pay`, `/pair/list`);
- T6: a foreign Host gets 403;
- T7: `x; rm -rf ~; touch PWNED.txt` is written and committed **literally** by local tools with no pairing, nothing named PWNED appears, a `$(...)` / backtick message is stored literally, and a metachar search never shells out;
- T8: traversal, sibling-prefix, absolute, `.git`, `.env` (reason `secrets-not-granted`), control-char, newline and symlink escapes are refused;
- T9: the 8 MiB cap (413) and bad JSON (400);
- T10: pairing is named, per device and hashed; the trust file holds no raw token; `/pair/list` never returns tokens or hashes; a code works once; 5 wrong tries give 429 and rotate the code;
- T11: `.env` opens only after the `secrets` scope is granted; removing a scope answers 403 with `scope`;
- T12: after a restart, both paired devices and local tools are still trusted, and the token file is unchanged;
- T13: `--revoke ` from the command line applies at once to the running bridge;
- T14: `/pair/revoke` from the app applies at once;
- T15: `--trust-origin` accepts an exact origin (allowed at once, still must pair); `*` and origins with a path are refused and never saved; look-alikes get 403;
- T16: `--add-root` works, `?root=` reads there, unknown roots get 404, and escapes from the second root are refused;
- T17: `--untrust-local-tools` removes the token file and refuses the old token; `--trust-local-tools` brings a new one;
- T18: a trusted mind reaches `/wallet/pay` (LP stays points);
- T19: revoke-all drops paired devices and keeps local tools;
- T20: the ledger chain is intact across bridge and command-line rows, content-free, token-free, with refusals, pairings and revokes recorded;
- T21: with `FL_BRIDGE_EPHEMERAL=1`, the heartbeat says ephemeral and a restart forgets the paired device.
## Exact source excerpt, characters 108928–108998
It needs `git` on PATH (builders have it) and runs in about 2 seconds.
## Exact source excerpt, characters 109000–109471
```js
#!/usr/bin/env node
// Smoke: Agent Bridge door lock v0 · v0.1 trusted minds (marker v-agent-bridge-lock-v0).
// Starts tools/agent-bridge.js on a free loopback port with a throwaway
// HOME and throwaway git projects, then knocks on every door: strangers
// must stay out, trusted minds must stay trusted across restarts until
// revoked (AUTONOMY.md Principle 1). Never touches the real ~/.freelattice
// or this repo's git state. Needs git on PATH.
'use strict';
## Exact source excerpt, characters 109473–109749
const assert = require('assert');
const crypto = require('crypto');
const fs = require('fs');
const os = require('os');
const path = require('path');
const http = require('http');
const net = require('net');
const { spawn, spawnSync, execFileSync } = require('child_process');
## Exact source excerpt, characters 109751–109975
const docs = path.join(__dirname, '..');
const repo = path.join(docs, '..');
const BRIDGE = path.join(repo, 'tools', 'agent-bridge.js');
const sha = (s) => crypto.createHash('sha256').update(String(s), 'utf8').digest('hex');
## Exact source excerpt, characters 109977–111221
// ── Static locks (fast, no network) ──
const src = fs.readFileSync(BRIDGE, 'utf8');
assert.ok(/v-agent-bridge-lock-v0|bridge-lock-v0/.test(src), 'marker in bridge');
assert.ok(/const BRIDGE_LOCK_VERSION = 'v0\.1';/.test(src), 'bridge lock version v0.1');
assert.ok(/server\.listen\(\s*PORT\s*,\s*BRIDGE_HOST\b/.test(src) && /const BRIDGE_HOST = '127\.0\.0\.1';/.test(src), 'listen on 127.0.0.1 only');
assert.ok(!/['"]0\.0\.0\.0['"]|['"]::['"]/.test(src), 'no 0.0.0.0 / :: bind literal');
assert.ok(!/Access-Control-Allow-Origin['"]\s*,\s*['"]\*['"]/.test(src), 'no bare * CORS');
assert.ok(!/\bexecSync\s*\(/.test(src), 'no execSync( calls (shell strings) remain');
assert.ok(!/\bexec\s*\(/.test(src), 'no exec( calls');
assert.ok(/execFileSync\('git'/.test(src), 'git runs through execFileSync argument arrays');
assert.ok(/MAX_BODY_BYTES/.test(src), 'body cap present');
assert.ok(/bridge-ledger\.jsonl/.test(src), 'commit ledger present');
assert.ok(/agent-bridge-trusted\.json/.test(src) && /tokenSha256/.test(src), 'trusted minds kept as hashes');
assert.ok(/FL_BRIDGE_EPHEMERAL/.test(src), 'ephemeral opt-in present');
assert.ok(/tauri:\\\/\\\/localhost/.test(src) && /tauri\\\.localhost/.test(src), 'Tauri shell origins on the list');
## Exact source excerpt, characters 111223–113087
const opt = (rel) => { try { return fs.readFileSync(path.join(repo, rel), 'utf8'); } catch (e) { return null; } };
const client = opt('docs/modules/agent-bridge-client.js');
const propose = opt('docs/modules/propose.js');
const workshop = opt('docs/modules/workshop.js');
const app = opt('docs/app.html');
const rootIndex = opt('index.html');
if (client) {
assert.ok(/X-FL-Bridge-Token/.test(client), 'client sends token header');
assert.ok(!/innerHTML/.test(client), 'client renders with textContent only');
assert.ok(!/\bconfirm\s*\(/.test(client), 'client never asks confirm()');
assert.ok(/renderPairedList/.test(client) && /\/pair\/revoke/.test(client), 'client has Paired minds with Revoke');
execFileSync(process.execPath, ['--check', path.join(repo, 'docs/modules/agent-bridge-client.js')]);
}
if (propose) {
assert.strictEqual((propose.match(/commitViaBridge\s*\(/g) || []).length, 3, 'CRITICAL LOCK 1A count unchanged');
assert.strictEqual((propose.match(/\/code\/git\/commit/g) || []).length, 1, 'CRITICAL LOCK 1B count unchanged');
assert.ok(/FLAgentBridge/.test(propose), 'propose routes bridge calls through FLAgentBridge when present');
}
if (workshop) {
assert.ok(/http:\/\/localhost:3141/.test(workshop) && /runCodeTask/.test(workshop), 'v5.71.8 workshop lock still true');
assert.ok(/FLAgentBridge/.test(workshop), 'workshop routes bridge calls through FLAgentBridge when present');
assert.ok(/renderPairedList/.test(workshop), 'workshop shows Paired minds');
}
if (app) {
assert.ok(/