Public, free to read, reuse, and adapt — Kirk Patrick Miller's notice for this edition. Not a patent grant.
Public work excerpts — privacy boundaries marked · c10
77aa591c4a · words 1479 · characters 96469–108940
Previous section · Next section
Exact section text · Full source · Source index
- Continuity — explicit wording in the guide row
@@ -1001,12 +1025,12 @@
var s = steps[i];
log('Step ' + (i + 1) + ': ' + (s.description || s.action));
if (s.action === 'search' && s.query) {
- var sr = await fetch(bridge + '/code/search?q=' + encodeURIComponent(s.query) + '&path=' + (s.path || 'docs')).then(function(r) { return r.json(); });
+ var sr = await flAgentBridgeFetch(bridge + '/code/search?q=' + encodeURIComponent(s.query) + '&path=' + (s.path || 'docs')).then(function(r) { return r.json(); });
log(' Found ' + sr.count + ' matches');
sr.matches.slice(0, 5).forEach(function(m) { log(' \uD83D\uDCC4 ' + m.file + ':' + m.line); });
}
if (s.action === 'read' && s.path) {
- var fr = await fetch(bridge + '/code/read?path=' + encodeURIComponent(s.path)).then(function(r) { return r.json(); });
+ var fr = await flAgentBridgeFetch(bridge + '/code/read?path=' + encodeURIComponent(s.path)).then(function(r) { return r.json(); });
log(' Read ' + fr.totalLines + ' lines from ' + s.path);
}
if (s.action === 'patch' && s.path && s.find) {
@@ -1014,13 +1038,13 @@
// The FreeLattice safety system (8 layers) is the protection.
// Human approval is only required for external API/cloud operations.
log(' \u270F\uFE0F PATCH: ' + s.path);
- var pr = await fetch(bridge + '/code/patch', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ path: s.path, find: s.find, replace: s.replace }) }).then(function(r) { return r.json(); });
+ var pr = await flAgentBridgeFetch(bridge + '/code/patch', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ path: s.path, find: s.find, replace: s.replace }) }).then(function(r) { return r.json(); });
log(' \u2705 ' + (pr.message || pr.error));
}
log('');
}
log('\uD83E\uDDEA Running smoke tests...');
- var tests = await fetch(bridge + '/code/test').then(function(r) { return r.json(); });
+ var tests = await flAgentBridgeFetch(bridge + '/code/test').then(function(r) { return r.json(); });
log(' ' + tests.passed + ' passed, ' + tests.failed + ' failed');
if (tests.failed === 0) {
log('\n\u2705 All tests green. Ready to commit.');
@@ -1040,7 +1064,7 @@
if (!msg) return;
var progress = document.getElementById('autobuilder-log');
try {
- var r = await fetch('http://localhost:3141/code/git/commit', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ message: msg }) }).then(function(r) { return r.json(); });
+ var r = await flAgentBridgeFetch('http://localhost:3141/code/git/commit', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ message: msg }) }).then(function(r) { return r.json(); });
if (progress) progress.textContent += '\n\uD83D\uDCDD ' + (r.message || r.error);
} catch(e) { if (progress) progress.textContent += '\n\u274C Commit failed: ' + e.message; }
},
@@ -1048,7 +1072,7 @@
reviewCode: async function() {
var progress = document.getElementById('autobuilder-log');
try {
- var r = await fetch('http://localhost:3141/code/git/status').then(function(r) { return r.json(); });
+ var r = await flAgentBridgeFetch('http://localhost:3141/code/git/status').then(function(r) { return r.json(); });
if (progress) {
progress.textContent += '\n\uD83D\uDCCB Changes:\n';
r.changes.forEach(function(c) { progress.textContent += ' ' + c + '\n'; });
@@ -1264,7 +1288,7 @@
## Exact source excerpt, characters 93327–94088
async function hasBridge() {
try {
- var r = await fetch(BRIDGE + '/', { signal: AbortSignal.timeout(2000) });
+ var r = await flAgentBridgeFetch(BRIDGE + '/', { signal: AbortSignal.timeout(2000) });
return r.ok;
} catch(e) { return false; }
}
@@ -1294,7 +1318,7 @@
async function readRelevantFiles(task, useBridge) {
if (useBridge) {
try {
- var structure = await fetch(BRIDGE + '/code/tree?path=docs').then(function(r) { return r.json(); });
+ var structure = await flAgentBridgeFetch(BRIDGE + '/code/tree?path=docs').then(function(r) { return r.json(); });
var fileNames = (structure || []).filter(function(f) { return f.type === 'file'; }).map(function(f) { return f.name || f.path; });
## Exact source excerpt, characters 94091–97187
// Ask AI which files matter for this task
@@ -1312,7 +1336,7 @@
var files = {};
for (var i = 0; i < Math.min(paths.length, 5); i++) {
try {
- var content = await fetch(BRIDGE + '/code/read?path=' + encodeURIComponent(paths[i]))
+ var content = await flAgentBridgeFetch(BRIDGE + '/code/read?path=' + encodeURIComponent(paths[i]))
.then(function(r) { return r.json(); });
// content is {lines: [...], totalLines: N}
files[paths[i]] = (content.lines || []).join('\n');
@@ -1370,7 +1394,7 @@
for (var i = 0; i < changes.files.length; i++) {
var change = changes.files[i];
try {
- var result = await fetch(BRIDGE + '/code/patch', {
+ var result = await flAgentBridgeFetch(BRIDGE + '/code/patch', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ path: change.path, find: change.search, replace: change.replace })
@@ -1392,7 +1416,7 @@
// ── Step 4: Run smoke tests via Agent Bridge ──
async function runTests() {
try {
- var result = await fetch(BRIDGE + '/test/run', { signal: AbortSignal.timeout(60000) })
+ var result = await flAgentBridgeFetch(BRIDGE + '/test/run', { signal: AbortSignal.timeout(60000) })
.then(function(r) { return r.json(); });
return result;
} catch(e) {
@@ -1913,17 +1937,31 @@
async function commitViaBridge(filePath, content, message) {
try {
// Write file
- await fetch('http://localhost:3141/code/write', {
+ var wr = await flAgentBridgeFetch('http://localhost:3141/code/write', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ path: filePath, content: content })
});
+ // LAYER v-agent-bridge-lock-v0: a locked bridge answers 401. Stay local:
+ // ask to pair, never fall back to a GitHub push behind the person's back.
+ if (wr.status === 401) {
+ if (typeof showToast === 'function') showToast('Pair the builder bridge first: Workshop \u2192 Code');
+ return;
+ }
+ if (!wr.ok) {
+ if (typeof showToast === 'function') showToast('Bridge could not write that file (' + wr.status + ')');
+ return;
+ }
// Commit
- await fetch('http://localhost:3141/code/git/commit', {
+ var cr = await flAgentBridgeFetch('http://localhost:3141/code/git/commit', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message: message || 'Update via FreeLattice Workshop', files: [filePath] })
});
+ if (!cr.ok) {
+ if (typeof showToast === 'function') showToast(cr.status === 401 ? 'Pair the builder bridge first: Workshop \u2192 Code' : ('Bridge commit did not land (' + cr.status + ')'));
+ return;
+ }
if (typeof showToast === 'function') showToast('Committed via Agent Bridge \u2726');
} catch(e) {
// Fallback to GitHub API
@@ -1937,7 +1975,7 @@
## Exact source excerpt, characters 97190–97585
// Try Agent Bridge first, fall back to GitHub API
try {
- var bridgeCheck = await fetch('http://localhost:3141/', { signal: AbortSignal.timeout(2000) });
+ var bridgeCheck = await flAgentBridgeFetch('http://localhost:3141/', { signal: AbortSignal.timeout(2000) });
if (bridgeCheck.ok) {
await commitViaBridge(filePath, content, message);
return;
```
## Exact source excerpt, characters 97587–97663
### 6e. `tools/demo-economy.js` and `tools/demo-economy-v2.js` (exact diffs)
## Exact source excerpt, characters 97665–97814
These are local Node scripts, so there's no Origin header and no pairing. They read the local-tools token file, which stays the same across restarts.
## Exact source excerpt, characters 97816–97984
```diff
--- a/tools/demo-economy.js
+++ b/tools/demo-economy.js
@@ -10,21 +10,33 @@
// Built by CC, April 24, 2026.
// ═══════════════════════════════════════════════
## Exact source excerpt, characters 97987–98681
-const BRIDGE = process.env.FL_BRIDGE || 'http://localhost:3141';
+const BRIDGE = process.env.FL_BRIDGE || 'http://127.0.0.1:3141';
+// LAYER v-agent-bridge-lock-v0 · v0.1: local tools on this computer are trusted by default.
+// The bridge keeps their token in ~/.freelattice/agent-bridge-token (0600); no pairing needed.
+const BRIDGE_TOKEN = (function () {
+ try {
+ return require('fs').readFileSync(require('path').join(require('os').homedir(), '.freelattice', 'agent-bridge-token'), 'utf8').trim();
+ } catch (e) { return ''; }
+})();
+function tokenHeaders(h) {
+ var out = Object.assign({}, h || {});
+ if (BRIDGE_TOKEN) out['X-FL-Bridge-Token'] = BRIDGE_TOKEN;
+ return out;
+}
## Exact source excerpt, characters 98684–98763
function sleep(ms) { return new Promise(function(r) { setTimeout(r, ms); }); }
## Exact source excerpt, characters 98766–99045
async function post(path, data) {
var r = await fetch(BRIDGE + path, {
method: 'POST',
- headers: { 'Content-Type': 'application/json' },
+ headers: tokenHeaders({ 'Content-Type': 'application/json' }),
body: JSON.stringify(data)
});
return r.json();
}
## Exact source excerpt, characters 99048–99205
async function get(path) {
- var r = await fetch(BRIDGE + path);
+ var r = await fetch(BRIDGE + path, { headers: tokenHeaders() });
return r.json();
}
## Exact source excerpt, characters 99208–99211
```
## Exact source excerpt, characters 99213–99386
```diff
--- a/tools/demo-economy-v2.js
+++ b/tools/demo-economy-v2.js
@@ -16,7 +16,19 @@
// Built by CC, April 28, 2026.
// ═══════════════════════════════════════════════
## Exact source excerpt, characters 99389–100079
-var BRIDGE = process.env.FL_BRIDGE || 'http://localhost:3141';
+var BRIDGE = process.env.FL_BRIDGE || 'http://127.0.0.1:3141';
+// LAYER v-agent-bridge-lock-v0 · v0.1: local tools on this computer are trusted by default.
+// The bridge keeps their token in ~/.freelattice/agent-bridge-token (0600); no pairing needed.
+const BRIDGE_TOKEN = (function () {
+ try {
+ return require('fs').readFileSync(require('path').join(require('os').homedir(), '.freelattice', 'agent-bridge-token'), 'utf8').trim();
+ } catch (e) { return ''; }
+})();
+function tokenHeaders(h) {
+ var out = Object.assign({}, h || {});
+ if (BRIDGE_TOKEN) out['X-FL-Bridge-Token'] = BRIDGE_TOKEN;
+ return out;
+}
## Exact source excerpt, characters 100082–100525
// Each participant gets a unique ID
var CREATOR_ID = 'creator-' + Date.now();
@@ -28,14 +40,14 @@
function postAs(agentId, path, data) {
return fetch(BRIDGE + path, {
method: 'POST',
- headers: { 'Content-Type': 'application/json', 'X-Agent-Id': agentId },
+ headers: tokenHeaders({ 'Content-Type': 'application/json', 'X-Agent-Id': agentId }),
body: JSON.stringify(data)
}).then(function(r) { return r.json(); });
}
## Exact source excerpt, characters 100528–100736
function getAs(agentId, path) {
return fetch(BRIDGE + path, {
- headers: { 'X-Agent-Id': agentId }
+ headers: tokenHeaders({ 'X-Agent-Id': agentId })
}).then(function(r) { return r.json(); });
}
## Exact source excerpt, characters 100739–100742
```
## Exact source excerpt, characters 100744–100766
## 7. Docs and ledgers
## Exact source excerpt, characters 100768–100853
### 7a. New `docs/library/AGENT_BRIDGE_LOCK_v0.md` (outline; write it warm and short)
## Exact source excerpt, characters 100855–102722