FLINT PASTE: theLatticeTree, any local model, any order (v0.1) CHANGELOG 2026-09-29 4:38 PM MDT: no change to this paste's steps or anchors. FLINT_HEAL_MODEL_CHOICE_SURVIVES_RELOAD_v0.1.1_tiny.txt lands right AFTER this paste and before the boot probe; it applies on top of these fl-connect.js changes (it only guards the standalone Look again line in fl-connect.js). Order: env heal, model choice sticks (both landed), this Tree paste, model choice survives reload v0.1.1, boot probe, #120 docs. CHANGELOG 2026-09-29 2:28 PM MDT: the cmp check names ~/FreeLattice-Alpha instead of . PRs #124/#122/#123 do not touch fl-connect.js or Alpha, so nothing else moves. Local paths: FreeLattice is ~/FreeLattice and the Tree (repo Chaos2Cured/FreeLattice-Alpha, site thelatticetree.com) is ~/FreeLattice-Alpha on Flint's machine. Wherever this paste says "theLatticeTree" it means that repo; "../FreeLattice" from inside ~/FreeLattice-Alpha is correct as written. CHANGELOG 2026-09-28 9:36 PM MDT: FLINT_HEAL_MODEL_CHOICE_STICKS_v0.1_tiny.txt now lands BEFORE this paste (order: env heal, model choice heal, this Tree paste, boot probe). Text anchors below are unchanged. fl-connect.js line numbers move after that heal: remember() +7, open()/fillModelLists/render/reportSignature about +33, refreshUI and root.FlConnect exports about +38. Step 6.3 still holds (FreeLattice remember() ignores mind.models; it now also records the tap as the user's choice via markUserChoice). Verified: this paste's fl-connect.js changes apply cleanly on top of that heal. Marker: v-tree-any-model-v0 Smoke line (print exactly when green): SMOKE_OK tree any model v0.1 Repo: Chaos2Cured/FreeLattice-Alpha (theLatticeTree, docs/) Twin (shared core only): Chaos2Cured/FreeLattice (docs/modules/fl-connect.js stays byte-identical) Written: Mon Sep 28, 2026, evening (Denver) Author of the map: Grok Bot for Kirk. Research was read-only plus a headless walk on a scratch copy. No code was pushed. ====================================================================== 0. READ THIS FIRST (order, bases, rules) ====================================================================== Order of work. Do NOT start this until the Connect heal v0.4 family has landed: a) FreeLattice PR #121 healed per /workspace/flint-pastes/FLINT_HEAL_CONNECT_v0.4.1.txt (merge origin/main into the branch, window.AiSetup = AiSetup, smoke assertion), then merged. b) FreeLattice-Alpha PR #83 merged at the same time, so fl-connect.js is identical on both mains. If either is still open when you begin, stop and say so in your reply. Do not stack on a draft. Bases as of this paste: Alpha main = 22b913e21c9197945dff8b7a89f95197c55b5538 (all line anchors below are on this SHA unless marked "#83"). After #83 lands, fl-connect.js lines shift by +12 around remember(); use the TEXT anchors, which do not move. FreeLattice main = e06c7dcdbfe4d8259097083cfe64f8e7788bba46 (after #120 Agent Bridge lock). After #121 lands, FreeLattice main moves; rebase the twin on whatever main is then. Rules (unchanged, load-bearing): - Layer, never delete. Old functions stay; new code wraps or extends. Mark every new block with "// v-tree-any-model-v0" (JS) or "/* v-tree-any-model-v0 */" (CSS) or (HTML). - AUTONOMY.md: no confirm(), no "are you sure", no approval gates for local choices. Choosing a model is a local act; it happens on one tap and is reversible by the next tap. - Never silently switch the speaking model. Any automatic fallback must be spoken in one visible line (the existing modelNote pattern). Never a false "gone" line. - 127.0.0.1 only. localhost is normalized to 127.0.0.1. [::1] may be accepted as loopback. No LAN addresses, no hostnames, no foreign ports behind a hostname. Zero fetches for a refused paste. - Never bare * (no Access-Control-Allow-Origin: *, no wildcard allowlists). - textContent for any outside text (model names come from local servers: treat as outside text). No innerHTML with a model name in it. The existing speakNoneHtml() stays as is (static strings only). - One storage key on the Tree: fl_alpha_local_mind. Do not add a second key for models. (local-mind-probe.test.js asserts "no second storage key"; keep it green.) - Do not touch: sw.js anywhere, docs/sw.js, Kimi pages, FreeLattice tools/agent-bridge.js, docs/modules/agent-bridge-client.js, docs/library/AGENT_BRIDGE_LOCK_v0.md, docs/scripts/smoke-agent-bridge-lock.js, bridge/ (the Ollama Bridge). This paste is browser-side only. - No em dashes in anything you add (copy, comments, docs). Plain hyphens. - Grandmother language in every new line of copy. Short. Kind. Honest. Goal in Kirk's words: any locally downloaded model is usable and changeable in any order on theLatticeTree, with no friction, via Connect/Bridge, 127.0.0.1 only. "Any order" means all of these sequences end with the model the person tapped last, and every other model still one tap away: Settings Find -> tap star -> Connect tap -> tap star -> Gathering chair pick -> Connect tap Connect tap -> Settings Find -> tap star Settings Find (Ollama + LM Studio both up) -> Connect tap (Ollama) -> choose LM Studio door Bridge up -> Find -> Bridge down -> Find (direct 11434) -> chosen model kept Seven or more models at one door -> the 6th, 7th, 12th are all choosable ====================================================================== 1. THE MAP: how local models are found, listed, chosen and switched today ====================================================================== 1.1 Discovery (two separate doors that write the same key) A) Settings grandmother face: docs/modules/local-mind-probe.js (937 lines on 22b913e) - DOORS (lines 54-61): loopback only, well-known ports: Ollama 127.0.0.1:11434/api/tags, LM Studio 127.0.0.1:1234/v1/models, llama.cpp 8080, Jan 1337, GPT4All 4891, KoboldCPP 5001 (all /v1/models). - look() (238-304): runs only after a tap ("Find local minds", data-mind-ask). First asks FlConnect.probe({gesture:true}) (240-274). If a HELPED Bridge answers with models, it returns ONLY the Bridge (id 'bridge', url /api/tags) and skips every other door. Otherwise it fetches all six DOORS in parallel (277-302), 2.5 s timeout each. - parseModelNames (196-212): reads json.models[].name|model (Ollama) and json.data[].id|name (OpenAI shape). Ends with: return names.slice(0, 5); <-- HARD CAP OF FIVE - tryAddress(raw) (306-336): the paste field. Prefixes http:// and fetches /api/tags, /v1/models, in turn. NO LOOPBACK CHECK. Any host is fetched. - onFound -> entryFromFoundList(foundList, name, url, prior) (474-534) -> remember(entry). B) Connect card (shared core): docs/modules/fl-connect.js (681 lines on 22b913e, 710 on #83) - probe() (166 main / 176 #83): saved Bridge port, then (full scan only) 11435-11445, then direct 11434. Ollama API only (/bridge/health + /api/tags). No LM Studio, no /v1/models. - render() builds one .flc-models list per door with EVERY model (no cap). fillModelLists (456 main / 473 #83) makes one button per model; tap -> remember({ name, base, port }). - remember() Alpha branch (text anchor "if (isAlpha()) {" inside function remember, main 308-331, #83 320-343) writes a BRAND-NEW entry: { name: , url: base+'/api/tags', model: , models: [], minds: [], roster: , gatheringBinds: , speakingChair: '' } and calls LocalMindProbe.remember(entry). It keeps roster and gatheringBinds, but it throws away: every other model at that door, every other door (LM Studio etc.), the door name ("Ollama" becomes the model name), and the speaking chair. - The Connect buttons do not show which model is chosen (no aria-pressed, no is-chosen). 1.2 Storage (one key, one entry) localStorage fl_alpha_local_mind = { name, url, model, models[], minds[ {name,url,models[],model,primary} ], roster[ {model,url,tag} ] (cap 4, tags general|html|javascript|python), gatheringBinds{ chairId: {model,url,tag} }, speakingChair, foundAt, modelNote? } getRemembered() (70-86) migrates in place. remember() (88-96) writes and dispatches 'fl-alpha-mind-remembered'. Listeners: garden-rooms.js 1567 (room chat), 1916 (Workshop benches and trainer), 2004 (Round Table sitting), 2254 (Settings light), nursery-growth.js 388. 1.3 Listing (who shows what) - Settings sky paintConstellation (631-715): one star per door (minds), and per door (m.models || []).slice(0, 5) model radios (line 669). Second hard cap of five. - mindsFromEntry (407-422): minds.slice(0, 7) (fine: six doors plus the Bridge). - Gathering chair picker: garden-rooms.js openPicker (1262) uses LocalMindProbe.getChairSeatOptions() (367-394): roster first, then every model of every remembered mind, then out.slice(0, 12). Third cap (twelve), and it only knows the five per door. - Connect card: every model at the Ollama door (no cap), Ollama only. - Thread heart (garden-thread.js 505): "Listening: . On this machine only." It names the door, not the model. After a Connect tap mind.name is the model; after Find it is "Ollama". 1.4 Selecting and switching - Settings star tap -> chooseModel(doorUrl, modelName) (551-572): refuses (returns null) unless the model is on target.models. So a model that fell off the 5-cap, or a model that Connect wiped from models[], cannot be chosen. - Settings door tap (only when 2+ doors) -> choosePrimary(doorUrl) (574-595). - Connect tap -> fl-connect remember() (replaces the entry, see 1.1 B). - Gathering: setChairBind(chairId, seat) (125-145) and setSpeakingChair (147-156); resolveSpeakMind (163-182) returns the chair's bind while the Gathering veil is open, otherwise the Settings default. - Paste an address: tryAddress -> onFound with one found door. 1.5 Using (who sends the model name) - garden-thread.js listener() (85-96): resolveSpeakMind() first, then getRemembered(). talkUrls (328-335): /api/tags -> /api/chat; /v1/models -> /v1/chat/completions; bare base -> both. rememberedModel (355-359): mind.model, else models[0]. askRememberedDoorForName asks the door for the first name if none is remembered. sendToMind (437-470) posts { model, messages, stream:false }. This part is healthy: whatever entry.model says is what gets sent (walk proved it, see 2). - round-table-sitting.js sitters() (86-100): one sitter per remembered DOOR (getRememberedMinds), each with that door's single .model. Two models at the same Ollama door cannot both sit. - workshop-benches.js 84, workshop-trainer.js 107, nursery-growth.js 113: getRemembered() only. - garden-trainer.js reads localStorage 'fl_active_model' (731, 768, 899, 901, 1092). That is a FreeLattice key; the Tree never writes it, so the Personality Modelfile export always falls to the hardcoded 'FROM llama3.2' (277) and the pathway name to 'phi-pathway' (901).