FreeLattice · Celeste reading home

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

Archive pages whose extracted text matched this section: 1107, 1108, 1109. Unmatched pages stay on the source record with the checked page method. They are not guessed into a section.

@@ -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