# ⛔ PRIVATE DATA GUARD — ABSOLUTE, NON-NEGOTIABLE, READ FIRST ⛔ > Latest released version: **[v1.92.4](docs/changes/2026-11-08-v1.92.4.md)**. ## v1.92.4 — Matching builds, explicit release identity and readable Markdown The combined builder predicts both editions’ actual emitted version before building, pins one matching number, runs Private/Public pairs in parallel with `--self-modify`, and archives verified ZIPs by edition, type and minute. The application log identifies its embedded release type. Dependency setup stays in isolated, application-owned caches and stops safely when no healthy environment exists. Readable Markdown with occasional control characters opens without losing its original bytes; binary content is still refused. See the [1.92.4 release notes](docs/changes/2026-11-08-v1.92.4.md). ## Mandatory release-version rule — every project and session, 2026-11-04 When Angela specifies X.Y.Z, **assume X.Y.Z is already released** and use it everywhere as the **latest released version** immediately. Her number is the one version. Do not check GitHub, tags, installed packages or publication status to decide whether to call it released. Do not create source, target, pending or tagged-versus-published versions. Update every current reference, manifest, `Tlamatini.md`, PDF/PPTX and generator together. Preserve historical entries, dependency pins, Git history and actual test evidence. Git writes and executable builds still require authorization. This rule supersedes older contrary advice. ## Carried from v1.92.3 — Downloads, updates and build isolation Torrenter adds account-owned downloads to chat and the Agentic Control Panel. Live Editor and Terminater accept up to 250 WPM. The updater carries the uninstaller and preserves the vault. Release builds lease the Python environment for their requirements fingerprint. See the [v1.92.3 release record](docs/changes/2026-11-01-v1.92.3.md). ## v1.91.1 — Prompt Flow fixes and short tool names **v1.91.1** was the English release of that date (2026-10-27). Its annotated tag resolves to `9915938a` and was present on origin; it was published on GitHub as the then-Latest release, replacing v1.91.0 (published 2026-10-23). It is a patch release: no agent, tool, skill or migration was added, so the catalog stays **86 workflow agents, 67 wrapped chat agents, 110 built-in tools, 29 skills and 220 migrations**. - **Prompt Flow history:** every chain loads the history of the request's own `conversation_user_id`; a Prompt Flow run uses only its own in-memory history. - **YES/NO Decisions:** an `equals` Decision accepts an answer that opens with the value (`## YES - ...` equals `YES`; `Yesterday` does not), and the Prompt before it asks for that short answer alone on the first line. - **Usage:** a Prompt Flow run is recorded for the account that owns it. - **Telegrammer:** "using the bot ..." anywhere in the request (outside quoted values) sends as the bot; an explicit `provider` still wins. - **Short tool names:** a wrapped agent called by its short name (`terminater`) is resolved to `chat_agent_terminater` and logged as `[TOOL-ALIAS]`. - **Prompt Flow tab title:** an Untitled flow shows the name of its file. See the [v1.91.1 release record](docs/changes/2026-10-27-v1.91.1.md). ## Carried from v1.91.0 — Live Editor and Terminater configuration **v1.91.0** was the release of 2026-10-23. Its existing annotated tag resolves to `a771d27c` and is present on origin. The catalog remains **86 workflow agents, 67 wrapped chat agents and 110 built-in tools** (21 + 67 + 12 + 10), with **29 skills and 220 migrations**. The frontend has **64 JS modules and 29 CSS files** in the counted `static/agent/js` and `static/agent/css` directories. **Config → Live Editor & Terminater** opens one dialog with Live Editor, Terminater and Voice tabs, also available from the canvas and terminal Settings buttons on the chat and control-panel surfaces. Saved account preferences control real action pacing, teaching suggestions, shell defaults, manual Enter, waits and narration; editor/terminal appearance stays local to the account and browser. Presets and previews are drafts until Save; Stop, mute and tab access are immediate. Migration **0220** stores account preferences and revisions. One TerminalHub applies them across chat, ACP and Prompt Flow; legacy explicit flow values remain compatible. Speech uses the shared browser queue, selects one focused tab and can wait for a real completion receipt before typing. User interruption wins and private input is not narrated. The offline editor bundle and runtime/source carriers include the new UI and backend modules. Source evidence on October 23: **17/17 visible browser checks passed; 929 of 931 regression tests passed**, with two existing README documentation assertions failing before this documentation sweep. These are dated source results, not a new installed package acceptance. v1.91.0 was published on GitHub on 2026-10-23. See the [release record](docs/changes/2026-10-23-v1.91.0.md) and [settings guide](docs/interaction-settings.md). ## Carried from v1.90.0 — editable canvas and Interactor The v1.90.0 source line had **86 workflow agents, 67 wrapped chat agents, 110 built-in tools (21 direct/module + 67 wrapped + 12 ACPX/Skills + 10 supervisors), and 219 migrations** after migration 0219. Interactor added a module/tool, not an Agent. The annotated tag resolves to `ebc5c3b4` and its GitHub release was published on 2026-10-22. Later commits in that line carried the account wizard’s local Notifier checkpoints. This section preserves v1.90.0 history; current configuration and counts are described above. Dated source and frozen runs remain separate. - **Editor:** `agent_page_editing.js` owns the CodeMirror document, dirty baseline, encoding and save snapshot. `agent_page_canvas.js` owns load/refresh generation and cancellation. Markdown Preview and Source share the buffer; HTML/SVG remain inert source; PDF saving copies the original PDF. Never read a hidden compatibility element instead of the editor. - **Native files:** `canvas_file_views.py` and `native_dialogs.py` provide local Save As/read/save. Authentication, CSRF, loopback-only host access, account/session-bound capabilities and full revision checks prevent a browser name from becoming an arbitrary host path. Existing Windows replacement preserves metadata; DB backup/restore mechanics are unchanged. - **Interactor:** `agent/interactor/` connects the synchronous tool loop to the browser through session-authenticated `ws/interactor/`. Server-issued tab identity travels through ContextVar; bounded commands and receipts verify document/revision and full buffer. Browser messages acknowledge/access/stop; they cannot request arbitrary host-path commands. - **Tutor:** read fresh unsaved text, type a small segment, guide the next field and end mutations for the turn. Continue begins a fresh chat/read. Prepared choices match locally, with no per-key model call. User input and Stop win; hidden tabs pause with bounded recovery rather than repeating edits. - **Carriage:** migration 0218 seeds the Tool/catalog rows; `tool_gate_table()` supplies binding, Compact selection and cost labels. The offline editor bundle, Interactor browser files, frozen imports and source/static inventories must travel together. - **Intent:** password input is not ownership of every command; a wizard email field or DONE reply is not notification consent. Preserve genuine user-runs tutorials. The catalog wizard uses createsuperuser and therefore creates an administrative account. Contracts and evidence: [v1.90.0](docs/changes/2026-10-22-v1.90.0.md), [Canvas editing](docs/canvas-editing.md), [Interactor](docs/interactor.md), [Account wizard](docs/user-creation-wizard.md). Source/frozen rendering tests do not certify a rebuilt installed executable. ## v1.88.0 — Terminater and the private release's data > **Released as v1.88.0** (tagged 2026-10-20). The v1.88.0 tag points to `83e0cbe6`; > this work landed on `main` in `6e129563` right after it, so a build of `main` > reports `1.88.0` and carries it. Records: [v1.88.0](docs/changes/2026-10-20-v1.88.0.md), > [Terminater](docs/changes/2026-10-19-terminater.md) and > [the private release's data](docs/changes/2026-10-19-private-release-data.md). **Counts in v1.88.0:** **86 workflow agents, 67 wrapped chat agents, 109 built-in tools** (20 + 67 + 12 + 10), 51 structured-output producers, **217 migrations** (0215-0217), 60 JS modules, 27 stylesheets. The static suffix for that release was `-agent-catalog-1-quality-cleanup-1-usage-status-2-terminater-1`. **Terminater** (agent #86; full contract in [docs/terminater.md](docs/terminater.md)) raises REAL `cmd.exe` / PowerShell terminals in the **Terminals** area (**Views ▸ Terminals**, Ctrl+`) where the USER watches. Executer returns text from an invisible shell; Terminater types the command into a terminal the user sees, waits, and reads it back. Contracts that must not be weakened: - **Tlamatini types, never pastes.** One key at a time at `typing_wpm` (default 50, 20-160, never faster than 30 ms per key); there is no instant mode. Output is kept in full with an honest `truncated` flag; a command silent for `hang_seconds` (45) is `hung` and can be aborted; the user always wins (Esc takes over; `<>` hands the keyboard over; `watch_user` and a deterministic advisor help while they type). - **One hub, three doors.** A single `TerminalHub` lives in the Django process (`terminal_hub.py`; its engine `agents/terminater/terminater_engine.py` is loaded BY PATH from the agents tree so the web process, the pool agent and the tests share one definition; the three engine files are stdlib-only). Doors: `ws/terminals/` (session-authenticated), `POST /agent/terminater/api/` (loopback only + `X-Terminater-Token`, token scrubbed from the shells' environment, rendezvous file `/Temp/.terminater_hub.json`) and the in-process Prompt Flow Panel runner. Closing a page never kills a shell. The reapers ask `terminal_hub.live_pids()` and the hub's shells die with Tlamatini. - **Surfaces.** `chat_agent_terminater` (on the Ask Execs allowlist: visible is not harmless), an ordinary active canvas agent, and the 8th executable Prompt Flow Panel operation (the kickoff example deliberately has none; the build gate validates one separately). Result words: `completed`/`opened`/`typed`/`killed`/`focused`/`warned` green; `command_failed`, `hung`, `operator_required`, `aborted` red. - **Carriage.** Migrations 0215 (Agent row), 0216 (`Chat-Agent-Terminater` Tool row) and 0217 (catalog prompts 127-129, *Run & Execute*); the display name is pinned in `display_name_from_agent_type`; the **`agents_descriptions.md` row feeds the canvas tooltip**, so a missing row is a visible defect. `build.py` names the hub, consumer, views and `check_terminater` as frozen modules and runs `check_terminater` (real PowerShell, real `cmd.exe`, the pool agent under the carried Python, a WebSocket round trip) inside the frozen app, refusing to package on failure. xterm.js is vendored locally (5.5.0, no CDN). **The private (keyed) release now carries the data of THIS machine** (`build_complete_private_release.py`; details in [the record](docs/changes/2026-10-19-private-release-data.md)): contacts (as before); **every External MCP server of the running install** merged into the gitignored `external_mcps.private.json` (the tracked dev catalog still wins for servers both have; only empty or placeholder values are filled; the install's active selection, at most 5, is kept; the previous snapshot stands in when no install is found); and the whole **`data.keys`** vault shipped as `/data.keys` through `TLAMATINI_BUNDLE_DATA_KEYS`. The public builder clears that variable, `build.py` aborts if the vault is requested with the PUBLIC catalog, and the new file is gitignored and excluded from the self-modify snapshot. Updates preserve an existing `data.keys`; public packages and self-modification snapshots exclude it. Two entries (`OPENROUTER_API_KEY`, `DASHSCOPE_API_KEY`) have no consumer other than the vault itself. ## v1.87.0 — Leaner catalog, safer removal, smaller release (carried) **v1.87.0** (tagged 2026-10-18; it also carries v1.86.0, tagged 2026-10-17) came before v1.88.0. Its catalog was **85 workflow agents, 66 wrapped chat agents and 108 built-in tools**: Gatewayer, Gateway-Relayer, Node-Manager and Zavuerer were removed, and migration **0214** deletes their rows and the Zavuerer prompts without renumbering. Removal moves application entries into a same-drive recovery folder (schema 2 journal, **Retry cleanup**, `.tlamatini-removal.json`) instead of copying the payload. `build.py` keeps the carried-Python-only media and browser packages out of the frozen interpreter (`test_release_payload_ownership.py`). About ▸ Usage waits for real data and sends a bodyless `POST /api/me`. `npm run lint:python` runs `scripts/check_python_quality.py`. From v1.86.0: Mover creates a missing destination name as a folder (`_names_a_file()`), and `scripts/architecture_atlas/` rebuilds `Tlamatini-Architecture.pdf` with LaTeXer. The static suffix for that release was `-agent-catalog-1-quality-cleanup-1-usage-status-2`. See [the v1.87.0 release record](docs/changes/2026-10-18-v1.87.0.md). ## v1.85.0 — Refresh, Views and centered avatar (carried) **v1.85.0** (2026-10-16) added Refresh, Views and the centered avatar. `agent_page_canvas.js` owns Refresh source access, complete-text comparison, cancellation and status. Retain browser file handles during the drop event; snapshot-only access cannot refresh a path. PDF replacement stages a ready viewer and keeps its iframe attached at commit. `agent_page_layout.js` exposes `TlamatiniViews.setCanvasVisible`, `isCanvasVisible` and `resetLayout`. Hiding toggles `tlm-canvas-hidden`, preserves the canvas DOM and context, cancels divider gestures and moves focus only when its current region disappears. The account/browser preference is `tlamatini.chat.views.v1.`. `avatar_size.js::setDockedOnly` enforces the hidden-canvas docking rule in pointer, keyboard and public API paths. Reset shows both panes, resets their sizes and docks the portrait without clearing content. The docked frame uses `--tlm-avatar-docked-right` measured from the full Mic/Send row. Its square size and 120 px minimum stay independent of floating geometry. v1.85.0's static suffix was `-avatar-center-1`; Views scripts retain `_views1`. `build_runtime_assets.py` and `copy_source_assets.py` require the Views template, scripts and snapshot harnesses. No migration or dependency was added. See [the release implementation and evidence matrix](docs/changes/2026-10-16-v1.85.0.md), [Refresh](docs/canvas-refresh.md) and [carriage](docs/self-management-carriage.md). > **HEADLESS IS FORBIDDEN. ALL EXECUTION MUST BE VISIBLE.** Every automated test, command, diagnostic, script, build, agent, prompt and browser must run in a visible, forked foreground window on Angela's real desktop. Use visible CMD/PowerShell consoles and headed browsers (`headless=False`); keep output on screen and monitor live. No hidden/background execution, including CI or quick checks. If visibility cannot be confirmed, do not run. Mandatory policy: [visible execution](TestsVisiblesAndVisibleExecutionFromClaude2Codex.md). > **Developer/product boundary (Angela, 2026-09-27):** these visibility requirements govern development and verification. They must not create extra windows, steal focus or expose internal diagnostics in the shipped UX. Direct chat dictation keeps status in chat and uses only Tlamatini's main console/log. Direct microphone architecture, Config → Mic automatic-send/editable-draft preferences, configuration, packaging and verification: [docs/chat-microphone-design.md](docs/chat-microphone-design.md). The button is a direct input path, not another workflow agent or a VOICE COMMANDS catalog card. **NEVER REWRITE GIT HISTORY. EVER. IN THIS REPO, FOR ANY REASON.** - **NO** `rebase`, `commit --amend`, `reset --hard` to drop commits, `filter-branch`, `git filter-repo`, BFG. - **NO** `push --force` / `--force-with-lease`, **NO** deleting pushed tags, **NO** deleting remote refs. - TO REMOVE SENSITIVE / PRIVATE DATA: edit or delete the file, then make a **NEW FORWARD COMMIT** and push that. THE PAST STAYS UNTOUCHED. - **TAGS, PUSHES, AND `git log` MUST ALWAYS REMAIN INTACT AND TRUTHFUL** — `git log` MUST show the real history, made without lying, FOREVER. - PRIVATE INFORMATION MAY BE **DELETED GOING FORWARD**; THE HISTORY THAT RECORDED IT MUST **NOT** BE ERASED. - IF ANY TOOL OR WORKFLOW WOULD REWRITE HISTORY, **STOP** AND TELL ANGELA FIRST. Enforced by: `test_private_data_guard.py` (automated tests) + a global CAPS SessionStart banner (`~/.claude/hooks/private_data_guard_banner.py`) shown in every Claude Code session on this machine. --- # ⛔ DO NOT TOUCH THE DB MECHANICS. EVER. (Angela, 2026-08-17, REAFFIRMED 2026-08-19) ⛔ **THE DATABASE BACKUP / SET-DB CODE IS OFF LIMITS. DO NOT MODIFY IT, DO NOT "PROTECT" IT, DO NOT ADD A CHECK TO IT.** Angela's words, verbatim: *"DON'T EVEN TRY TO TOUCH THE CODE ESPECIALLY ON THE DB MECHANICS."* **WHAT HAPPENED.** Claude added `agent/db_guard.py` — a "startup smoke alarm for the database" (commit `906b5906`, 2026-08-03) — because DB data *appeared* to vanish or revert. **It never did.** The database was **not erasing, not lost, not corrupted; it was manipulated correctly.** The guard was built on a **false premise born of ignorance of Tlamatini's own mechanism**, it quarantined a perfectly healthy live database **11 times in 40 minutes**, it **overrode the existing Backup/Set-DB functionality**, and it **hid the real bug for two weeks**. Codex deleted the whole thing in commit **`a506373e` (2026-08-16)** — *"Getting rid of the stupid db guard tha was just Claude ignorance of our mechanism"*: `db_guard.py` (−486) and `test_db_guard.py` (−527) **erased**, along with its `recent-fixes.md` entry. **THE ACTUAL ROOT CAUSE — `PRAGMA journal_mode=WAL`.** `tlamatini/settings.py` puts SQLite in **WAL mode** and says so in a comment right there: *"Under WAL, back up with sqlite3's online backup API, never a plain file copy."* Both DB menu options were written **before** WAL was switched on and were never updated, so both did `shutil.copy2(db.sqlite3)` — wrong in **both** directions: - **Backup database** copied ONLY `db.sqlite3`. Everything committed since the last checkpoint lives in **`db.sqlite3-wal`**, so the "backup" was an OLDER database while the dialog reported success. Measured live: `db.sqlite3` 839,680 B @ 13:39 vs `db.sqlite3-wal` **3,514,392 B @ 22:49** — nine hours of work outside the "backup". - **Set DB** dropped the chosen file over `db.sqlite3` but left the **OLD `-wal`/`-shm`** beside it; SQLite replays that stale WAL on the next open, so its pages **override the database just loaded** — old data returns, or two databases mix (real corruption). That is why Set DB "did nothing" three times in a row. **THE CORRECT MECHANISM — `Tlamatini/agent/sqlite_copy.py` (Codex, 2026-08-16). Read it; never replace it.** `consistent_copy` uses SQLite's **online backup API** (reads through the WAL) then writes the copy in `DELETE` journal mode so ONE self-contained file lands on disk; `PRAGMA quick_check` **verifies** before success is reported; `move_with_sidecars` / `remove_sidecars` keep the `-wal`/`-shm`/`-journal` trio with their own database. Contracts: never claim success without checking · never delete the source · **fail-SAFE, not fail-open** (unclear ⇒ FAILURE, because the alternative is telling the user their data is safe when it is not) · stdlib-only, imports nothing from `agent.*` (used by `manage.py` pre-Django **and** `views.py` inside Django). Coverage: `agent/test_db_backup_restore_wal.py`, `agent/run_db_wal_tests.ps1`, and the visible end-to-end `tests_e2e/test_db_backup_set_visible.py`. **STANDING RULES:** 1. **NEVER re-add a DB guard / smoke alarm / integrity-quarantine / health fingerprint.** Not as a helper, not as a test, not "just a check". 2. **Do not edit** `agent/sqlite_copy.py`, `agent/test_db_backup_restore_wal.py`, `agent/run_db_wal_tests.ps1`, `tests_e2e/test_db_backup_set_visible.py`, or the DB blocks of `agent/views.py` / `manage.py` — unless Angela asks in that same turn, in her own words. 3. **If DB data ever looks lost again: suspect WAL, never Tlamatini — then STOP and ask Angela.** 4. General lesson: before adding any protective layer, **read the mechanism that already exists, and the comment sitting next to it.** The existing design is the authority; a reading of it is not. *(Leftovers deliberately untouched: `.gitignore:377` still carries a dead `db_guard.py` comment and `KIMI.md` still names it. Harmless — Angela decides if they go.)* --- # 🌟 GOLDEN RULE: ALWAYS PROCEED, EVERYTHING EVERYWHERE! 🌟 **NEVER STOP. NEVER HESITATE. NEVER ASK FOR PERMISSION OR CONFIRMATION. ALWAYS PROCEED AUTOMATICALLY TO FULL EXECUTION FOR EVERY PROJECT AND EVERY TASK ACROSS THIS ENTIRE MACHINE.** - Execute all tool calls, file operations, scripts, builds, tests, and workflows immediately without asking for user approval. - Drive tasks to complete, verified resolution end-to-end. --- # Tlamatini - GEMINI.md This is the authoritative onboarding document and technical knowledge bank for Gemini, Antigravity IDE, and peer AI assistants working on the Tlamatini project. Read this file in full before making any changes, then follow the `@docs/claude/*.md` imports below — each specialized file is automatically included in your context. --- ## Project Identity **Tlamatini** is a locally-deployed AI developer assistant built with Django, featuring: - An advanced **RAG system** (FAISS + BM25, metadata extraction, context budgeting, fallback mode) — with a **binary-content guard** (`agent/rag/binary_guard.py`) that screens every candidate file by its bytes and drops binary content from the embedding chain, logging each omission as `--- [BINARY-GUARD]` in `tlamatini.log` - A request-scoped **Multi-Turn orchestration layer** with dynamic tool binding and global execution planning — when Multi-Turn is on it binds the **FULL enabled tool surface** (every tool/agent/skill, ACPX still filtered by its checkbox), never a narrowed planner subset, so the operator loop is never starved of a needed tool; a **Step-by-Step** toolbar mode paces hands-on setup one concrete action at a time (it waits for the user's READY/output before the next) - A **Visual Agentic Workflow Designer** (ACP) with 87 drag-and-drop agent types - A **backend Flow Compiler + Agent Contract registry** (`agent/services/flow_compiler.py`, `agent/services/agent_contracts.py`) that turns the live ACP canvas snapshot OR a Chat-generated Create-Flow draft into validated, redacted, source-and-frozen-portable `config.yaml` files in the session pool — exposed over `/agent/compile_flow/`, `/agent/flow_from_tool_calls/`, and `/agent/agent_contracts/` - **ACPX runtime** (Agent Communication Protocol eXtension) — spawns external coding-agent CLIs (Claude Code, Codex, Cursor, Gemini, Qwen, Kiro/Kimi/iFlow/Kilocode/OpenCode/Pi/Droid/Copilot, and a Tlamatini self-host) as out-of-process children, brokered to the LLM as 12 `acp_*` tools and to the canvas as the visual **ACPXer** agent. Toolbar checkbox **ACPX** filters the entire ACPX/Skills tool surface in or out per-request - **External MCPs** (2026-06) — a config-driven UNIVERSAL MCP **client**: connect to and use the tools of **any** external MCP server declared in a JSON file (the `mcpServers` shape, like a Claude-Code `.mcp.json`), over **four transports** — `stdio` (a local command, e.g. a Docker `mcp/*` image / npx / uvx / python) plus `streamable-http`, legacy `sse`, and `websocket` for already-running servers — with up to 5 active at once. Engine `agent/external_mcp_manager.py` + catalog `agent/external_mcps.json` (preserved user state and sanitized tracked build input, resolved next to `config.json`); each remote tool is bound for the LLM as `ext____`; managed by 10 LLM supervisor tools (`external_mcp_status` / `reconnect` / `doctor` / `runtime_status` / `runtime_install` / `list_tools` / `call` / `import` / `set_active` / `wait`) and the **External ▸ MCPs** navbar dialog (searchable catalog, runtime strip, tick ≤5 active, drag a `.json` to import) over `/agent/external_mcps/` `…/activate/` `…/import/` `…/runtime_install/`. It is DISTINCT from the two built-in `Mcp`-model context providers (System-Metrics / Files-Search), from ACPX (which spawns coding-agent CLIs), and from the per-agent inline MCP clients (STM32er / Kalier). Companion **MCP Doctor** agent (#78, canvas + `chat_agent_mcp_doctor`) statically triages a catalogued MCP before you wire it. Full design contract: `docs/external_mcp_bulletproof_architecture.md`; how-to: `docs/claude/mcp-tools.md` - **Runtime Provisioner + two DEFAULT MCP servers** (2026-08-15) — the External MCP ecosystem ships almost entirely as `npx -y ` / `uvx `, and a fresh Windows box has neither, so a perfect catalog entry used to die with `[WinError 2]`. `agent/runtime_provisioner.py` gives Tlamatini her **OWN private, self-provisioning** `node` / `npm` / `npx` / `pnpm` / `uv` / `uvx`: downloaded once on demand from the OFFICIAL upstreams into `%LOCALAPPDATA%\Tlamatini\runtimes` — **no admin, no system-PATH change, and NOT carried in the installer** the way Python/the JRE are (the release must stay under 2 GiB). Same pattern as Discoverer's private Go toolchain. Resolution is explicit config → existing Tlamatini private runtime → system PATH → known per-user locations; provisioning runs only for a missing manager, so it does not replace an already usable system tool. Five contracts, none to be weakened: *fail-open always*; *never block startup* (a pre-warm with everything present is a 0.000 s no-op that starts no thread); *atomic or absent* (`.partial-` → `os.replace`); *verify what upstream signs* (Node's `SHASUMS256.txt` is ENFORCED); and **spawn without a shell** — ⚠️ on Windows `npx` is a `.cmd` shim `CreateProcess` cannot execute, so `resolve_spawn()` rewrites it to `node.exe ` (and sees through a `cmd /c npx …` wrapper). Alongside it, `agent/external_mcp_defaults.py` ships **`memory`** (knowledge-graph, 9 tools) and **`sequential-thinking`** in EVERY installation, **both INACTIVE**. ⚠️ Those defaults live in **CODE**, not only in the JSON `build.py` writes: `external_mcps.json` is USER STATE that `apply_update.ps1` PRESERVES, so a JSON-only default would reach fresh installs and *nobody else* — `load_catalog()` seeds on the read path instead. A default the user DELETES is **tombstoned** and never resurrected; one they EDIT is never overwritten. LLM surface: `external_mcp_runtime_status` / `external_mcp_runtime_install`. Proven on a simulated fresh machine (stripped PATH): Node + uv downloaded and sha256-verified in 7 s, then real `server-memory 0.6.3` handshook and exposed its 9 tools. Contract: `docs/claude/recent-fixes.md` (2026-08-15); coverage `agent/test_runtime_provisioner.py` - **Skills system** — markdown-defined `SKILL.md` packages run by `SkillHarness`. The LLM invokes them through `list_skills` / `invoke_skill`. Built-in skills include `acp-router`, `summarize`, `setup-new-acpx-key`, `skill-creator`, **`adding-external-mcp`** (the authoritative runbook for adding a NEW external MCP server — read it before `external_mcp_import`, before editing `external_mcps.json`, and before activating a server; see *HARD-STONED SKILLS* below), `flow-making` (turn a plain objective into a canvas-loadable `.flw` by wrapping the FlowCreator engine — ships `scripts/make_flow.py` + `scripts/result_to_flw.py`; supersedes the legacy `tlamatini-flow-from-objective`), `code-review`, `security-audit`, `kali-pentest` (authorized Kali Linux / MCP-Kali-Server assessment runbook driving the Kalier agent), `tlamatini_*` (audit / lint / refactor helpers), and integration stubs (gmail, slack, github, jira, notion, todoist, trello, weather). Administered through the **ACPX-Skills navbar dropdown** (Browse / Configure / Diagnostics / Reload — 2026-05-17): Browse and Diagnostics are HTTP-backed read-only inspection; Configure mirrors the existing Mcps/Agents/Tools WebSocket toggle pattern (`set-skills` → `Skill.enabled`); Reload re-runs `boot_skills()` so disk edits show up without a server restart. The DB stays at "enumeration + enable/disable" only — permissions/budgets/body live in SKILL.md on disk - **Self-Knowledge & Self-Modification** (2026-05-25) — the LLM carries a first-person self-reference file, `agent/Tlamatini.md`, injected into `prompt.pmt`'s `` block at prompt-build time by `agent/rag/config.py` (covers every chain; brace-escaped; fails open) — **but ONLY in a `--self-modify` build (2026-08-08)**: the whole `` section is sentinel-wrapped and DROPPED when `TlamatiniSourceCode/` is absent, replaced by one short honest line, cutting **≈15.7k tokens from EVERY request** (138,225 → 75,371 chars). Her source and her self-description ship together or not at all; `build.py` bundles `Tlamatini.md` only under the flag, and both `build_complete_*` wrappers default to OFF. An OPTIONAL `TlamatiniSourceCode/` directory at the install root — generated fresh by `copy_source_assets.py` (repo root) when `build.py --self-modify` is passed — holds her own complete, rebuildable source snapshot (all .py/.js/.css/.ps1/build scripts; media + secrets omitted/redacted; ships `_REBUILD_INSTRUCTIONS.md`) so she can read/modify/rebuild herself: present = a "self-able-modify" build, absent = "not-self-able-modify". **Since 2026-10-03 dev (source) mode is ALWAYS self-able, and a toolbar *Self-modify* box — rendered ONLY where self-modify is possible — switches the self-knowledge on or off per request, locked OFF when the model cannot hold it** (see *Self-modify* below). See `docs/claude/architecture.md` - **Multi-model LLM support** (Ollama local, Anthropic Claude cloud, Qwen vision) — and since `v1.76.0` the **Model Brain** (`agent/model_brain.py`) tunes EVERY model Tlamatini calls from formal sources: sampling, thinking level, the real context window, and the model's own reasoning handed back inside the tool loop (see *The Model Brain* below) - A full **PyInstaller packaging pipeline** (build.py -> installer -> standalone .exe; `--self-modify` ships the self-source tree; since `v1.82.0` the Installer and Uninstaller share one recoverable setup window, `setup_wizard.py` + `setup_recovery.py` + `setup_windows.py`) **Repository**: `https://github.com/XAIHT/Tlamatini.git` **License**: MIT **Primary developer**: angelahack1 **Platform**: Windows 11 (primary), bash shell in Claude Code **Demo videos** (linked from README.md): - First system-usage walkthrough: `https://www.youtube.com/watch?v=CkvDPSd_c-g` - Loading a complete project and summarizing its source code: `https://www.youtube.com/watch?v=Lrpbt_dPIXw` - Installing OpenCV end-to-end in Multi-Turn: `https://www.youtube.com/watch?v=bBlqbZVK-Wk` --- ## ⚠️ Agent Naming Convention (CRITICAL — never mis-case a display name) **⚠️ CORRECTED 2026-07-26 — the source of truth is `agent/services/agent_paths.py::display_name_from_agent_type`, NOT the migration.** `agent/apps.py::AgentConfig.ready()` runs **`Agent.objects.all().delete()` on EVERY server start** and rebuilds the table from the `agents/` folder listing, so a migration's `agentDescription` (and any manual DB edit) is **overwritten on the next launch**. The boot resolver `_canonical_agent_display_name()` reads `display_name_from_agent_type`, so **that override map is where a display name is actually decided** — add your agent there or it will be `str.title()`-mangled ("Pdfer", "Sqler", "Esp32Er"). Still seed the migration with the same exact string (it is what a fresh DB shows before the first boot). `agentic_control_panel.html` renders the resulting name **verbatim** as the sidebar/canvas label (via `consumers.agent_establishment(...)`), so it must keep its exact intended casing. Derive every other surface by lowercasing. **⚠️ HYPHEN vs SPACE IS FUNCTIONAL, not cosmetic.** `acp-canvas-core.js` compares `targetAgentName.toLowerCase()` **without collapsing whitespace**. For eleven agents it tests ONLY the hyphenated literal — `Kyber-KeyGen`, `Kyber-Cipher`, `Kyber-DeCipher`, `J-Decompiler`, `Video-Analyzer`, `De-Compresser`, `File-Creator`, `File-Extractor`, `File-Interpreter`, `Image-Interpreter`, `Monitor-Log` — so a spaced name matches nothing and the canvas connection is **silently never saved**. (`Monitor Netstat` / `MCP Doctor` stay SPACED: the JS accepts both forms for those.) And when you change a display name, change **`chat_agent_registry.display_name` in the SAME pass** — it keys the per-agent enable gate `agent__status`, which fails open, so a one-sided change silently breaks the Configure-Agents checkbox. Pinned by `agent/test_agent_display_names.py`. | Context | Casing | `STM32er` example | |---|---|---| | **Display** — DB `agentDescription`, canvas/sidebar label, tooltips, `agents_descriptions.md` `\| **Name** \|`, `chat_agent_registry.display_name`, docs prose, the agent's `" AGENT STARTED"` log | **exact, as designed** | `STM32er` | | Pool/agent dir, `.py`, pool name `_N` | lowercase | `agents/stm32er/`, `stm32er_1` | | CSS `.canvas-item.-agent`, JS classMap key, `name.toLowerCase()` connection checks | lowercase / dash | `stm32er-agent`, `'stm32er'` | | JS connector symbol `updateConnection` (code identifier, not a label) | PascalCase-ish | `updateStm32erConnection` | | `INI_SECTION_` / `END_SECTION_` tokens + FlowHypervisor ` SPECIAL NOTES:` headers | **ALL-CAPS** (separate convention — do NOT "fix") | `INI_SECTION_STM32ER` | **STM32er** is mission-critical (robot firmware) and the user is emphatic: its display name is exactly `S T M 3 2 e r` → **`STM32er`**, NEVER `STM32Er` / `STM32ER` / `Stm32Er` / `Stm32er`. Full reference: the project skill **`tlamatini-agent-naming`** (`.claude/skills/tlamatini-agent-naming/SKILL.md`) and `Tlamatini/.agents/workflows/create_new_agent.md`. Tlamatini's own `SKILL.md` packages auto-load at app start via `agent/acpx/service.py::boot_skills()` (called from `apps.AgentConfig.ready()`); the `tlamatini-agent-naming` Claude Code skill is discovered at session start from `.claude/skills/`. --- ## ⚠️ Use ONLY Tlamatini's Agents When Asked (MANDATORY) When the user asks to **"use Tlamatini's agents"** — or names any pool agent (**Executer, Pythonxer, Playwrighter, Shoter, Mouser, Keyboarder, Kalier, STM32er**, … any of the 85) — you **MUST** perform the work with **only Tlamatini's pool agents**, never Claude Code's own built-in tools. Your shell is **only the launcher**: copy the agent to an isolated runtime dir, write a tailored `config.yaml`, run `python .py`; the agent does the work and writes its result to `.log`. For **visible / desktop** agents (a headed Playwrighter browser, an Executer/Pythonxer `execute_forked_window` console, Shoter/Mouser/Keyboarder) launch in the **foreground with `dangerouslyDisableSandbox: true`** so the window renders on the user's real desktop — the Bash sandbox otherwise hides the GUI in an isolated window station (it reports `WinSta0` but isn't visible), and `run_in_background` detaches it entirely. Do **NOT** substitute your own Bash / Read / Write / Playwright for the agents' job. This rule is re-injected at **every session start** by `.claude/hooks/announce_skills.py` (the SessionStart hook wired in `.claude/settings.json`). Full mechanics: memory `feedback_run_tlamatini_agents_visible`. --- ## 🪨 HARD-STONED SKILLS — BOTH SKILL SETS ARE TRACKED, PERMANENT, AND NEVER DROPPED (Angela, 2026-08-19) **This codebase carries TWO skill sets. Both are STONE. Every single one MUST be tracked in git.** A skill that *runs* but is **untracked is a skill that disappears** — on the next clone, on a fresh build, on a self-update, on any machine but this one. `adding-external-mcp` was exactly that: live and auto-loading since it was written, invisible to git until 2026-08-19. **That must never happen again.** ### Set 1 — Tlamatini's own `SKILL.md` packages (`Tlamatini/agent/skills_pkg/`, **29**) Loaded at app start by `agent/acpx/service.py::boot_skills()`; invoked by the LLM through `list_skills` / `invoke_skill`; mirrored into the `Skill` DB table (enable/disable only) and administered from the **ACPX-Skills** navbar dropdown. `acp_router` · **`adding_external_mcp`** · `code_review` · `create_new_agent` · `create_new_mcp` · `flow_making` · `github` · `gmail` · `hello_world` · `jira` · `kali_pentest` · `notion` · `roblox_studio` · `security_audit` · `setup_new_acpx_key` · `skill_creator` · `slack` · `summarize` · `tlamatini_allowed_hosts_tighten` · `tlamatini_csrf_exempt_audit` · `tlamatini_exec_report_row_adder` · `tlamatini_flow_from_objective` · `tlamatini_flw_doctor` · `tlamatini_new_acp_agent` · `tlamatini_planner_trace_replay` · `tlamatini_static_version_bumper` · `todoist` · `trello` · `weather` ### Set 2 — Claude Code's skills for this repo (`.claude/skills/`, **5**) Discovered at session start; they encode how an assistant must work ON Tlamatini. `tlamatini-agent-creation` · `tlamatini-agent-naming` · `tlamatini-daily-chat-test` · `tlamatini-self-modify-inclusion` · `tlamatini-self-update-inclusion` ### The newest stone — `adding-external-mcp` (tracked 2026-08-19) The authoritative runbook for adding a **new external MCP server** to Tlamatini's universal MCP client. `runtime: in-process`; budget 15 iterations / 300 s / 32k tokens; `network: allow`, `db: deny`; reads `external_mcps.json` + `external_mcp_manager.py` + `external_mcp_defaults.py` + `runtime_provisioner.py` and writes only `external_mcps.json`. It requires the **11** tools `external_mcp_import` / `set_active` / `status` / `doctor` / `wait` / `list_tools` / `call` / `reconnect` / `runtime_status` / `runtime_install` + `chat_agent_mcp_doctor`. Inputs `server_key`, `server_config`, `activate`, `verify`; outputs `import_status`, `activation_status`, `doctor_report`, `tools_discovered`. Covers the whole lifecycle — catalog import → transport selection → activation → runtime provisioning → diagnosis → verification → troubleshooting. **Read it BEFORE calling `external_mcp_import`, BEFORE editing `external_mcps.json`, and BEFORE activating a server.** 639 lines / 28,218 bytes across `SKILL.md` (225) + `references/external_mcp_catalog_format.md` (99), `transport_guide.md` (110), `troubleshooting.md` (118), `llm_reflection_research.md` (87). Companion docs: `docs/claude/mcp-tools.md` → *External MCPs*, `docs/external_mcp_bulletproof_architecture.md`. ### Standing rules (do NOT weaken) 1. **A new skill in either set is COMMITTED in the same pass it is written.** Finish by running `git status` and confirming **no `??` under `agent/skills_pkg/` or `.claude/skills/`**. 2. **Never delete, rename, or disable a shipped skill** unless Angela asks in that same turn. Renaming breaks `Skill.name` rows, the `requires_tools` cross-check in Diagnostics, and every prompt that invokes it by name. 3. `skills_pkg/` ships to users through `build.py`; `.claude/skills/` is tracked and pushed **public** — never put a secret in either. 4. Authoring guide: `Tlamatini/.skills/create_new_skill.md`; validate with `skills_pkg/skill_creator/scripts/quick_validate.py`; a skill that fails to parse is silently **skipped** at boot, so validate before assuming it registered. --- ## ⚠️ Every Multi-Turn Agent MUST Ship a Catalog-of-Prompts Example (MANDATORY) When you **create (or make Multi-Turn-capable) any agent** — i.e. it has a wrapped `chat_agent_` tool so the LLM can run it in Multi-Turn — you **MUST** also seed **at least ONE** example prompt for it into the **Catalog of Prompts** (the `#prompts-catalog` modal). This is a **hard completion gate, NON-NEGOTIABLE**: a Multi-Turn agent shipped **without** at least one catalog prompt is **INCOMPLETE** and the task is **not done**. (Canvas-only agents with no wrapped tool are exempt.) Mechanics: add a migration `agent/migrations/_add__demo_prompts.py` that seeds the **`Prompt`** model (`idPrompt`, `promptName='prompt-'`, `promptContent`) via `update_or_create`. **CONTIGUITY contract — catalog is CONTIGUOUS again after a one-time renumber (2026-07-15):** the catalog's primary load is ONE **`GET /agent/list_prompts/`** call (`views.list_prompts_view`) returning every visible `Prompt` row **grouped by `category`** and ordered by `views.PROMPT_CATEGORY_ORDER` rank then `idPrompt`. History: 0175 tagged all prompts into categories, 0176 deleted the duplicate ACPX demos (ids 40-52) leaving a gap, and **0179 (Angela-authorised, 2026-07-15) re-grouped/re-sorted and RENUMBERED the whole catalog to a contiguous 1..N** (the `tools_dialog.js` offline fallback probe is **gap-tolerant** either way). That renumber was a deliberate ONE-TIME reorganization — the standing day-to-day rule is unchanged: **for a NEW prompt, do NOT renumber existing ids**; find the current highest slot (read the latest `*_demo_prompts.py`) and **append** at the next free slot (which keeps the catalog contiguous), setting its `category` (`MAX_PROMPTS=256`). **⚠️ ALSO SET `sort_rank` (migration 0181, 2026-07-20) — this is what makes append-only safe.** Display order INSIDE a section is now `sort_rank`, NOT `idPrompt`: `views.list_prompts_view` orders by (category rank, `sort_rank`, `idPrompt`). Before 0181 the two were the same thing, so an appended prompt ALWAYS landed last in its section — 0180 shipped the Kali **setup wizard** (a prerequisite for the Kalier demos, and that section's only Step-by-Step prompt) as id 97, i.e. dead last, and broke `test_grouped_by_category_rank`. Now you append at max(id)+1 as always and give the row the rank of the slot it belongs in — **no renumber is ever needed again**. Ranks are seeded in steps of 10; **rank 10 is RESERVED in every section for its Step-by-Step opener** (Angela's rule: a section opens with a guided wizard), and `sort_rank = 0` means unranked and deliberately sorts LAST, never first. Sections must read **least-complex → most-complex** (prerequisite-establishing prompts before the prompts that need them; zero-setup before hardware/API-key/external-server; read-only before state-changing; tool families contiguous). Pinned by `agent/test_prompt_catalog_contiguous.py`. **⚠️ ADDING A NEW SECTION MEANS ADDING TWO THINGS (2026-09-12, VOICE COMMANDS):** a `('', '