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 · c04

7730821e3a · words 1588 · characters 35487–48388

Previous section · Next section

Exact section text · Full source · Source index

Archive pages whose extracted text matched this section: 1181, 1182, 1183, 1184, 1185. Unmatched pages stay on the source record with the checked page method. They are not guessed into a section.

  // POST /code/write — write a file (token-gated; UI approval lives in the app)
  if (url === '/code/write' && method === 'POST') {
    if (!data.path || typeof data.content !== 'string' || !data.content) return respond(res, 400, { error: 'path and content required' });
    var wlp = lockedPath(data.path);
    if (wlp.error) return respond(res, wlp.error, { error: 'Path refused', reason: wlp.reason });
    try {
      fs.mkdirSync(path.dirname(wlp.full), { recursive: true });
      fs.writeFileSync(wlp.full, data.content, 'utf8');
      earnLP(activeId, 'core_plant', 'Wrote file: ' + wlp.rel);
      return respond(res, 200, { message: 'File written.', path: wlp.rel, bytes: data.content.length });
    } catch(e) { return respond(res, 500, { error: 'Write failed: ' + e.message }); }
  }

## Exact source excerpt, characters 32409–33319

  // POST /code/patch — find-and-replace in a file
  if (url === '/code/patch' && method === 'POST') {
    if (!data.path || typeof data.find !== 'string' || !data.find || typeof data.replace !== 'string') return respond(res, 400, { error: 'path, find, and replace required' });
    var plp = lockedPath(data.path);
    if (plp.error) return respond(res, plp.error, { error: 'Path refused', reason: plp.reason });
    try {
      var pcontent = fs.readFileSync(plp.full, 'utf8');
      if (!pcontent.includes(data.find)) return respond(res, 400, { error: 'Search text not found in file', hint: 'Check whitespace and line endings.' });
      fs.writeFileSync(plp.full, pcontent.replace(data.find, function() { return data.replace; }), 'utf8');
      return respond(res, 200, { message: 'Patch applied.', path: plp.rel });
    } catch(e) { return respond(res, 500, { error: 'Patch failed: ' + e.message }); }
  }

## Exact source excerpt, characters 33321–33795

  // GET /code/git/status
  if (url === '/code/git/status') {
    try {
      var status = runGit(['status', '--porcelain']);
      var branch = runGit(['branch', '--show-current']).trim();
      var log = runGit(['log', '--oneline', '-5']);
      return respond(res, 200, { branch: branch, changes: status.split('\n').filter(Boolean), recentCommits: log.split('\n').filter(Boolean) });
    } catch(e) { return respond(res, 500, { error: 'Git failed: ' + e.message }); }
  }

## Exact source excerpt, characters 33797–35737

  // POST /code/git/commit — stage and commit (local only; this bridge never pushes)
  if (url === '/code/git/commit' && method === 'POST') {
    var lg = { route: '/code/git/commit', origin: (meta && meta.origin) || '', agent: activeId };
    var msgOk = typeof data.message === 'string' && data.message.trim() &&
      data.message.length <= MAX_COMMIT_MESSAGE && !/[\u0000-\u0008\u000b-\u001f\u007f]/.test(data.message);
    if (!msgOk) {
      lg.result = 'refused:message'; ledgerAppend(lg);
      return respond(res, 400, { error: 'message required (1-' + MAX_COMMIT_MESSAGE + ' chars, no control characters)' });
    }
    var files = data.files === undefined ? ['.'] : data.files;
    if (!Array.isArray(files) || files.length === 0 || files.length > MAX_COMMIT_FILES) {
      lg.result = 'refused:files'; ledgerAppend(lg);
      return respond(res, 400, { error: 'files must be a list of 1-' + MAX_COMMIT_FILES + ' project paths' });
    }
    var rels = [];
    for (var fi = 0; fi < files.length; fi++) {
      var clp = lockedPath(files[fi], { allowRoot: true });
      if (clp.error) {
        lg.result = 'refused:path:' + clp.reason; ledgerAppend(lg);
        return respond(res, clp.error, { error: 'Path refused', reason: clp.reason });
      }
      rels.push(clp.rel);
    }
    lg.filesCount = rels.length;
    lg.filesSha256 = sha256Hex(rels.slice().sort().join('\n'));
    lg.messageSha256 = sha256Hex(data.message);
    try {
      runGit(['add', '--'].concat(rels));
      runGit(['commit', '-m', data.message]);
      var headSha = runGit(['rev-parse', 'HEAD']).trim();
      lg.result = 'ok'; lg.commitSha = headSha; ledgerAppend(lg);
      return respond(res, 200, { message: 'Committed: ' + data.message, commit: headSha });
    } catch(e) {
      lg.result = 'error'; ledgerAppend(lg);
      return respond(res, 500, { error: 'Commit failed: ' + String((e.stderr || e.message || '')).slice(0, 400) });
    }
  }

## Exact source excerpt, characters 35739–36499

  // GET /test/run — run smoke tests (AutoBuilder format)
  // Returns { allPassed, count, failures[], output }
  if (url === '/test/run') {
    var tr = runSmokeFile(60000);
    var testOutput = tr.out || (tr.error ? String(tr.error.message) : '');
    var passedMatch = testOutput.match(/ALL (\d+) CHECKS PASSED/);
    var failLines = (testOutput.match(/✗.*/g) || []);
    if (tr.status !== 0 && failLines.length === 0) failLines.push(tr.error ? tr.error.message : 'Smoke exited with status ' + tr.status);
    return respond(res, 200, {
      allPassed: tr.status === 0 && failLines.length === 0 && passedMatch !== null,
      count: passedMatch ? parseInt(passedMatch[1], 10) : 0,
      failures: failLines,
      output: testOutput.slice(-800)
    });
  }

## Exact source excerpt, characters 36501–37120

  // GET /code/test — run smoke tests (legacy format)
  if (url === '/code/test') {
    var ct = runSmokeFile(30000);
    if (ct.status === 0) {
      var passed = (ct.out.match(/✓/g) || []).length;
      var allMatch = ct.out.match(/ALL (\d+) CHECKS PASSED/);
      return respond(res, 200, { passed: allMatch ? parseInt(allMatch[1], 10) : passed, failed: 0, output: ct.out.slice(-500) });
    }
    var failMatch = ct.out.match(/(\d+) FAILED/);
    return respond(res, 200, { passed: 0, failed: failMatch ? parseInt(failMatch[1], 10) : 1, output: (ct.out || (ct.error ? ct.error.message : '')).slice(-500) });
  }
```

## Exact source excerpt, characters 37122–37163

### Block E: listen (replaces L1153-1157)

## Exact source excerpt, characters 37165–37840

```js
var server = http.createServer(handleRequest);
server.on('error', function(e) {
  console.error('  ! Agent Bridge could not start on ' + BRIDGE_HOST + ':' + PORT + ': ' + e.message);
  process.exitCode = 1;
});
// LAYER bridge-lock-v0: loopback only. No env override. Never 0.0.0.0.
server.listen(PORT, BRIDGE_HOST, function() {
  console.log('');
  console.log('  \u2726 FreeLattice Agent Bridge');
  console.log('  \u2726 Listening on http://' + BRIDGE_HOST + ':' + PORT);
  console.log('  \u2726 Door lock: ' + BRIDGE_LOCK_VERSION + ' (named origins, token, no shell)');
  console.log('  \u2726 Token file (local tools): ' + TOKEN_FILE);
  newPairCode('launch');
```

## Exact source excerpt, characters 37842–37856

## 6. App side

## Exact source excerpt, characters 37858–37919

### 6a. New `docs/modules/agent-bridge-client.js` (full text)

## Exact source excerpt, characters 37921–38185

It sends the token only when one is stored, so an older bridge keeps working. It rewrites `localhost:3141` to `127.0.0.1:3141`. On 401 it clears the token, fires `fl-agent-bridge-needs-pair`, and **never falls back to GitHub**. All text goes through `textContent`.

## Exact source excerpt, characters 38187–39039

```js
/* FLAgentBridge: the app side of the Agent Bridge door lock.
 * Marker: v-agent-bridge-lock-v0 (2026-09-28, Celeste's brief, built by Flint).
 *
 * The Agent Bridge (tools/agent-bridge.js, port 3141) is the builder's
 * local git door. It is NOT the Ollama Bridge (bridge/, port 11435).
 * Since bridge-lock-v0 it wants a per-launch token on every change.
 * The app gets that token once per bridge launch by a short pairing
 * code the bridge window shows (like pairing a speaker).
 *
 * - Sends X-FL-Bridge-Token only when a token is stored, so an older
 *   bridge keeps working exactly as before.
 * - Talks to 127.0.0.1 (local minds are 127.0.0.1 only).
 * - Everything shown to people goes through textContent.
 * - A 401 never falls back to GitHub. Local stays local.
 */
(function () {
  'use strict';
  if (window.FLAgentBridge) return;

## Exact source excerpt, characters 39041–39174

  var TOKEN_KEY = 'fl_agentBridgeToken';
  var BASE = 'http://127.0.0.1:3141';
  var NEEDS_PAIR_EVENT = 'fl-agent-bridge-needs-pair';

## Exact source excerpt, characters 39176–39700

  function normalize(url) {
    return String(url).replace(/^http:\/\/localhost:3141(?=\/|$)/, BASE);
  }
  function getToken() {
    try { return localStorage.getItem(TOKEN_KEY) || ''; } catch (e) { return ''; }
  }
  function setToken(t) {
    try {
      if (t) localStorage.setItem(TOKEN_KEY, t);
      else localStorage.removeItem(TOKEN_KEY);
    } catch (e) {}
  }
  function copy(obj) {
    var o = {};
    if (obj) for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k)) o[k] = obj[k];
    return o;
  }

## Exact source excerpt, characters 39702–40113

  function bridgeFetch(url, opts) {
    var o = copy(opts);
    var h = copy(opts && opts.headers);
    var t = getToken();
    if (t) h['X-FL-Bridge-Token'] = t;
    o.headers = h;
    return fetch(normalize(url), o).then(function (r) {
      if (r.status === 401) {
        setToken('');
        try { window.dispatchEvent(new CustomEvent(NEEDS_PAIR_EVENT)); } catch (e) {}
      }
      return r;
    });
  }

## Exact source excerpt, characters 40115–40865

  function pair(code) {
    return fetch(BASE + '/pair', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ code: String(code || '').slice(0, 16) })
    }).then(function (r) {
      return r.json().catch(function () { return {}; }).then(function (j) {
        if (r.status === 200 && j && typeof j.token === 'string' && /^[a-f0-9]{64}$/.test(j.token)) {
          setToken(j.token);
          return { ok: true };
        }
        return { ok: false, status: r.status, reason: (j && typeof j.error === 'string') ? j.error : ('HTTP ' + r.status) };
      });
    }).catch(function () {
      return { ok: false, status: 0, reason: 'The bridge is not answering on this computer.' };
    });
  }

## Exact source excerpt, characters 40867–41280

  function status() {
    return fetch(BASE + '/', { signal: (typeof AbortSignal !== 'undefined' && AbortSignal.timeout) ? AbortSignal.timeout(2000) : undefined })
      .then(function (r) { return r.json(); })
      .then(function (j) { return { up: true, lock: (j && j.bridgeLock) || null, hasToken: !!getToken() }; })
      .catch(function () { return { up: false, lock: null, hasToken: !!getToken() }; });
  }

## Exact source excerpt, characters 41282–43026

  // A small pairing card. All text via textContent, never parsed as HTML.
  function renderPairCard(container) {
    if (!container || container.querySelector('.fl-bridge-pair')) return;
    var box = document.createElement('div');
    box.className = 'fl-bridge-pair';
    box.style.cssText = 'margin:8px 0;padding:10px;border:1px solid rgba(255,255,255,0.12);border-radius:10px;';
    var p = document.createElement('div');
    p.textContent = 'Your builder bridge is awake. Its window shows a short code. Type it here to pair.';
    var input = document.createElement('input');
    input.type = 'text';
    input.maxLength = 7;
    input.placeholder = 'ABC-123';
    input.setAttribute('aria-label', 'Bridge pairing code');
    input.autocomplete = 'off';
    input.style.cssText = 'margin:6px 6px 0 0;padding:6px 8px;width:7em;text-transform:uppercase;letter-spacing:0.1em;';
    var btn = document.createElement('button');
    btn.type = 'button';
    btn.textContent = 'Pair';
    var msg = document.createElement('div');
    msg.style.cssText = 'margin-top:6px;opacity:0.8;';
    btn.addEventListener('click', function () {
      btn.disabled = true;
      msg.textContent = 'Pairing\u2026';
      pair(input.value).then(function (res) {
        btn.disabled = false;
        if (res.ok) {
          msg.textContent = 'Paired. Your builds can use the bridge now.';
          setTimeout(function () { if (box.parentNode) box.parentNode.removeChild(box); }, 1500);
        } else {
          msg.textContent = res.reason || 'That did not pair. Check the code in the bridge window.';
        }
      });
    });
    box.appendChild(p); box.appendChild(input); box.appendChild(btn); box.appendChild(msg);
    container.appendChild(box);
  }

## Exact source excerpt, characters 43028–43341

  window.FLAgentBridge = {
    BASE: BASE,
    TOKEN_KEY: TOKEN_KEY,
    NEEDS_PAIR_EVENT: NEEDS_PAIR_EVENT,
    fetch: bridgeFetch,
    pair: pair,
    status: status,
    hasToken: function () { return !!getToken(); },
    forget: function () { setToken(''); },
    renderPairCard: renderPairCard
  };
})();
```

## Exact source excerpt, characters 43343–43404

### 6b. `docs/app.html` (then byte-copy to root `index.html`)

## Exact source excerpt, characters 43406–43481

Right above L68472 `<script src="modules/propose.js" defer></script>`, add:

## Exact source excerpt, characters 43483–43662