Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
139 commits
Select commit Hold shift + click to select a range
c55887e
th-f30175: scaffold smooth-daemon + vendor smooth-operator-core (path…
brentrager Jun 22, 2026
aeee542
th-64fbe8: Phase 1a — wire protocol + AgentEvent mapping + SessionRun…
brentrager Jun 22, 2026
c87d049
th-64fbe8: Phase 1b — axum daemon server + in-process agent runner
brentrager Jun 22, 2026
53649c0
th-64fbe8: Phase 1c — durable /api/event SSE with cursor resume
brentrager Jun 22, 2026
d0fc55a
th-64fbe8: Phase 1d — SessionStore + /api/session REST surface
brentrager Jun 22, 2026
7373fe7
th-64fbe8: Phase 1e — runnable smooth-daemon binary + graceful shutdown
brentrager Jun 22, 2026
8d141ac
th-64fbe8: Phase 1f — resolve LLM creds from providers.json (daemon i…
brentrager Jun 22, 2026
92c01b4
th-ed6604: smooth-tools crate + read-only tools wired into the daemon…
brentrager Jun 23, 2026
3e2c966
th-ed6604: smooth-tools Slice B — write_file + edit_file (workspace-c…
brentrager Jun 23, 2026
0c0b37f
th-ed6604: smooth-tools Slice C — bash tool + tool-aware system promp…
brentrager Jun 23, 2026
3f8b52d
th-64fbe8: th daemon command + th service --daemon + point th code TU…
brentrager Jun 23, 2026
5d78ef8
th-bd0e22: Phase 2 — durable SQLite persistence (state survives daemo…
brentrager Jun 23, 2026
e9a9c40
th-bd0e22: Phase 2 Slice 2 — durable conversation resume across restart
brentrager Jun 23, 2026
99ee7f1
th-08e05a: Phase 3 Slice 1a — auto-mode permission engine (Gate 1)
brentrager Jun 23, 2026
9da3633
th-08e05a: Phase 3 Slice 1b — permission ToolHook + interactive appro…
brentrager Jun 23, 2026
0214730
th-08e05a: Phase 3 Slice 2 — kernel OS-sandbox for bash (macOS Seatbe…
brentrager Jun 23, 2026
71ffcad
th-bd0def: Phase 4 Slice 1 — daemon serves a reimagined React control…
brentrager Jun 23, 2026
8bea772
th-bd0def: Phase 4 Slice 2 — session history endpoint + resume-in-UI
brentrager Jun 23, 2026
53a74ef
th-bd0def: Phase 4 Slice 3 — /api/status + chat polish
brentrager Jun 23, 2026
c97cc05
th-bd0def: Phase 4 Slice 4 — runtime permission-mode switching
brentrager Jun 23, 2026
2cd070d
th-bd0def: Phase 4 Slice 5 — cancel a running task from the UI
brentrager Jun 23, 2026
f24456b
th-bd0def: Phase 4 Slice 6 — bearer-token auth + bind hardening
brentrager Jun 23, 2026
a113133
th-08e05a: harden Seatbelt sandbox — deny .git/config writes + more c…
brentrager Jun 23, 2026
3f04275
th-08e05a: Seatbelt — deny sandboxed reads of the daemon's own ~/.smo…
brentrager Jun 23, 2026
8a25f32
th-08e05a: scrub secret env vars from sandboxed shells
brentrager Jun 23, 2026
93db8a2
th-08e05a: broaden RCE circuit-breakers to any download|interpreter
brentrager Jun 23, 2026
24869ed
th-92dac3: fix find_native_operative test for cargo-bin install path
brentrager Jun 23, 2026
c725e02
th-08e05a: egress allowlist core — exact-host + strict hostname parser
brentrager Jun 23, 2026
eece70b
th-08e05a: egress proxy decides via in-process EgressAllowlist (no Wonk)
brentrager Jun 23, 2026
ce235a4
th-08e05a: route sandbox egress through proxy + deny direct bypass
brentrager Jun 23, 2026
7fb76d9
th-08e05a: bash tool gains optional egress proxy (injection point)
brentrager Jun 23, 2026
405bbb4
th-08e05a: daemon egress capstone — start goalie proxy + route bash e…
brentrager Jun 23, 2026
9f149c8
docs: document the always-on daemon's security model (EPIC th-c89c2a)
brentrager Jun 23, 2026
3a3b9a1
th-08e05a: curated default egress allowlist (defaults token)
brentrager Jun 23, 2026
71a5717
th-bd0def: surface egress-boundary status in /api/status + UI
brentrager Jun 23, 2026
c21bd30
th-bd0e22: durable SQLite-backed agent memory (Memory trait impl)
brentrager Jun 23, 2026
56bf763
th-bd0e22: wire durable memory into the agent loop
brentrager Jun 23, 2026
286c360
th-bd0e22: close the memory loop — add the 'remember' tool
brentrager Jun 23, 2026
6b80391
th-bd0def: memory browser — /api/memory search + control-surface panel
brentrager Jun 23, 2026
2b82175
docs: add Always-On-Daemon architecture overview (EPIC th-c89c2a)
brentrager Jun 23, 2026
08b9c60
th-bd0def: auto-title sessions from the first message
brentrager Jun 23, 2026
4bfe3f2
th-bd0def: surface daemon uptime in /api/status + header
brentrager Jun 23, 2026
6c85d4e
th-bd0def: add 'th daemon status' + fix th daemon not starting egress
brentrager Jun 23, 2026
edf4767
th-bd0def: add 'th daemon audit' — tail egress allow/block decisions
brentrager Jun 23, 2026
7f14fc3
th-bd0def: scheduler core — schedule model + next-fire-time computation
brentrager Jun 23, 2026
acd5acb
th-bd0def: durable schedule store (ScheduleStore + SQLite)
brentrager Jun 23, 2026
7203e52
th-bd0def: scheduler tick loop + dispatch — proactive scheduled tasks
brentrager Jun 23, 2026
4eaffbf
th-bd0def: schedule management API (GET/POST/DELETE /api/schedule)
brentrager Jun 23, 2026
8e2ead9
th-bd0def: 'th daemon schedule' CLI (list/add/rm proactive tasks)
brentrager Jun 23, 2026
330557e
th-bd0def: control-surface schedule panel (list/add/remove)
brentrager Jun 23, 2026
7bd196e
docs: sync Always-On-Daemon overview with memory + scheduler
brentrager Jun 23, 2026
f3a94e9
th-c89c2a: daemon hosts the operator local flavor (th daemon operator)
brentrager Jun 24, 2026
5cd7ac6
th-c89c2a: wire kernel-sandboxed tools into the operator local flavor
brentrager Jun 24, 2026
c55a1ca
th-c89c2a: th daemon subcommands log to stderr (closes th-9eb87d)
brentrager Jun 24, 2026
94a22cd
th-c89c2a: th daemon operator serves the official widget at /
brentrager Jun 24, 2026
8f0aa97
th-c89c2a: feed sandboxed tools via the operator's #68 ToolProvider seam
brentrager Jun 25, 2026
ad7af81
th-c89c2a: repoint operator path-deps to canonical main (closes th-84…
brentrager Jun 25, 2026
4ff9be0
th-c89c2a: document the local flavor's inherited write-confirmation HITL
brentrager Jun 25, 2026
8c087a9
th-c89c2a: live-LLM E2E + integration tests for the local flavor
brentrager Jun 26, 2026
da23327
th-c89c2a: local flavor enables strict-auth (closes th-6d1863)
brentrager Jun 26, 2026
2618f0a
th-c89c2a: bash circuit-breaker guard (closes th-1f694a)
brentrager Jun 26, 2026
224f023
th-c89c2a: split the daemon/operator runtime out of the `th` CLI
brentrager Jun 26, 2026
e1825fb
th-c89c2a: th code speaks the operator canonical protocol (off bespok…
brentrager Jun 27, 2026
b6ddec0
th-c89c2a: 'Smooth Flow' visual glow-up for the th CLI + th code TUI
brentrager Jun 27, 2026
4bd1bb2
th-c89c2a: 'Smooth Flow' pass 2 — make the glow-up actually visible
brentrager Jun 27, 2026
5f1efeb
th-c89c2a: 'Smooth Flow' pass 3 — glow up the th code splash
brentrager Jun 27, 2026
35fdf80
th-c89c2a: status bar shows the real model, not the smooth-* slot alias
brentrager Jun 27, 2026
b4677e5
th-c89c2a: decouple th code from the bespoke :4400 Big Smooth
brentrager Jun 27, 2026
713e2f0
th-c89c2a: operator sources its LLM key from providers.json — th code…
brentrager Jun 28, 2026
ce69d5d
th-c89c2a: nuke :4400 stage 1 — th code fully off the bespoke surface
brentrager Jun 28, 2026
2abf0e9
th-c89c2a: nuke :4400 stage 2 — th drops the 4 bespoke crates
brentrager Jun 28, 2026
d8af98b
th-c89c2a: nuke :4400 stage 4 — delete the 10 microVM crates
brentrager Jun 28, 2026
b04bc03
th-c89c2a: nuke :4400 stage 5 — remove dead microVM commands from th
brentrager Jun 28, 2026
3811e1c
th-c89c2a convergence 1/4: durable storage for the operator daemon (t…
brentrager Jun 29, 2026
397ac67
th-c89c2a convergence 4/4 (pivot): th daemon runs the operator
brentrager Jun 29, 2026
d8a0cbf
th-c89c2a convergence 4/4 (finish): delete serve_persistent + the bes…
brentrager Jun 29, 2026
f3cfaa6
th-c89c2a: fix stale Run help — smooth-daemon default IS the operator
brentrager Jun 29, 2026
6046c54
th-c89c2a: delete BigSmoothClient — the last bespoke :4400 client in …
brentrager Jun 29, 2026
ca898d1
th-c89c2a: drop th access + point model/doctor health at the operator
brentrager Jun 29, 2026
54f987e
th-c89c2a: delete orphaned smooth-credential-helper + smooth-policy :…
brentrager Jun 29, 2026
ca0ee74
th-c89c2a: cut vestigial smooth-web deps from th + the daemon
brentrager Jun 29, 2026
072eeb5
th-c89c2a (th-1ea4f6): OperatorClient HITL protocol — write_confirmat…
brentrager Jun 29, 2026
f36bbb4
th-c89c2a (th-1ea4f6): TUI HITL UX — approve/deny parked write-tools
brentrager Jun 29, 2026
0668f74
th-c89c2a: changesets for daemon convergence, :4400 cleanup, HITL app…
brentrager Jun 29, 2026
8f6166d
th-c89c2a (th-2ff975): restore schedule model — scheduler foundation
brentrager Jun 29, 2026
958bb2c
th-c89c2a (th-2ff975): durable SqliteScheduleStore — schedules surviv…
brentrager Jun 29, 2026
857ebca
th-c89c2a (th-2ff975): scheduler tick loop + TurnDriver abstraction
brentrager Jun 29, 2026
ef60de0
th-c89c2a (th-2ff975): OperatorTurnDriver + arm the scheduler in the …
brentrager Jun 29, 2026
71901f8
th-c89c2a (th-2ff975): schedule add/list/remove CLI — proactivity is …
brentrager Jun 29, 2026
a8898be
th-c89c2a (th-515a13): Gate 1 permission rule model — deny/ask/allow
brentrager Jun 29, 2026
d01324a
th-c89c2a (th-515a13): Gate 1 — bash compound-split + token-prefix ma…
brentrager Jun 29, 2026
797812a
th-c89c2a (th-515a13): Gate 1 — PermissionRules::from_toml config loader
brentrager Jun 29, 2026
9c08a53
th-c89c2a (th-515a13): enforce Gate 1 deny at the bash tool boundary
brentrager Jun 29, 2026
95ce0bc
th-c89c2a (th-515a13): extend Gate 1 deny to write_file/edit_file
brentrager Jun 29, 2026
c200674
th-c89c2a (th-515a13): permissions check CLI — inspect Gate-1 verdicts
brentrager Jun 29, 2026
492916b
th-c89c2a (th-515a13): extend Gate 1 deny to the read tool
brentrager Jun 29, 2026
9cab1b1
th-c89c2a: update CLAUDE.md §1 — crate list reflects the operator daemon
brentrager Jun 29, 2026
4c257c7
th-c89c2a: rewrite CLAUDE.md §4/Dispatch/Security for the operator da…
brentrager Jun 29, 2026
3bb2a14
th-c89c2a: fix CLAUDE.md Project Overview — operator daemon, not micr…
brentrager Jun 29, 2026
1225036
th-c89c2a: workspace quality gate — fmt + clippy clean
brentrager Jun 29, 2026
12c91f6
th-c89c2a (th-f1a1f0): smooth-web reimagined as the Presence control …
brentrager Jun 29, 2026
3c16c13
th-c89c2a (th-f1a1f0): parked tool chip reads 'awaiting your okay', n…
brentrager Jun 29, 2026
39e0fd3
th-c89c2a (th-f1a1f0): awake status dot is green (alive), amber reser…
brentrager Jun 29, 2026
0591968
th-833b5f (th-f1a1f0): frontend-design glow-up — the face becomes the…
brentrager Jun 29, 2026
aca3fa9
th-c89c2a: daemon reachability + persona — same-origin serve, tailsca…
brentrager Jun 29, 2026
d5893de
th-c89c2a: changeset — daemon reachability (same-origin + tailscale) …
brentrager Jun 29, 2026
2820922
smooth-web: render reasoning as a collapsible 'thinking', not the ans…
brentrager Jun 29, 2026
da05032
th-4d8682: changeset — reasoning shown as collapsible thinking, answe…
brentrager Jun 29, 2026
dc3d7e5
th-c89c2a: fix SMOOTH_AGENT_MODEL override + add SMOOTH_FAST_MODE (Gr…
brentrager Jun 29, 2026
4abf6fe
th-c89c2a: changeset — fast mode + model override
brentrager Jun 29, 2026
c2510fd
smooth-tools: prune VCS/build dirs from the ripgrep walk + bound list…
brentrager Jun 29, 2026
1b64bf1
th-c89c2a: Smooth Modes — /smooth-mode + always-on cost, unified web …
brentrager Jun 30, 2026
51f1584
th-c89c2a: TUI reads cost at data.data.usage.costUsd (the real eventu…
brentrager Jun 30, 2026
f40be71
th-58b5fe: @ mention search in smooth-web, unified with the TUI
brentrager Jun 30, 2026
a1c3443
th-c435fd: smoo-hub deploy — SMOOTH_ADDR bind port + configurable/coe…
brentrager Jun 30, 2026
e2d125e
th-c435fd: th service — --env vars, self-update, and an updater timer
brentrager Jun 30, 2026
a34db8b
th-833b5f: smooth-web brand icon (th) + PWA force-update modal
brentrager Jun 30, 2026
064c17c
th-833b5f: wordmark in the official Smooth lockup — Smoo orange→red, …
brentrager Jun 30, 2026
12ad98c
th-833b5f: bulletproof PWA force-refresh — unregister SW + clear cach…
brentrager Jun 30, 2026
0eb3b3c
th-c89c2a: Web Push — Big Smooth notifies your phone (PWA, tab closed)
brentrager Jun 30, 2026
add8beb
th-c89c2a: cargo fmt push.rs
brentrager Jun 30, 2026
f06b533
th-3be564: multimodal + mobile scroll-lock in the daemon SPA
brentrager Jul 5, 2026
6458b4a
th-3be564: downscale images before send — fix gateway 524 on large ph…
brentrager Jul 5, 2026
260ac55
th-c89c2a: default Flash mode to gemini-2.5-flash (was deepseek-v4-fl…
brentrager Jul 6, 2026
1003e77
th-c89c2a: fs tools accept absolute paths inside the workspace
brentrager Jul 6, 2026
32cf681
th-c89c2a: list_files roots the walk at the glob's literal prefix + a…
brentrager Jul 6, 2026
9ffdc50
th-4b1867: daemon chat — assistant-grade token/iteration headroom
brentrager Jul 7, 2026
01d68ea
th-c89c2a: guard WebGL init in BigSmoothFace (headless/GPU-blocklist …
brentrager Jul 7, 2026
2212f3d
th-4b1867: changeset for daemon token/iteration headroom
brentrager Jul 8, 2026
11885ea
th-c89c2a: drag-and-drop files anywhere on the PWA (not just the comp…
brentrager Jul 8, 2026
21f7689
th-c89c2a: tool chips resolve + interleave prose with tools in stream…
brentrager Jul 8, 2026
bdcb00e
th-d5b446: conversation sidebar + resume + new-chat in daemon PWA (#181)
brentrager Jul 9, 2026
4e5584d
th-d5b446: fix resumed-history mapper to real message shape
brentrager Jul 9, 2026
3b8f2f9
th-d5b446: rename conversations from the daemon PWA sidebar (#183)
brentrager Jul 9, 2026
9eb4c00
th-c89c2a: Flash mode → deepseek-v4-flash (drop gemini-2.5-flash)
brentrager Jul 9, 2026
3d57bab
th-23329e Phase 1: add `th ext` CLI to the epic (SEP extensions on sm…
brentrager Jul 15, 2026
535ac06
th-37c9f5 th search + crawl + knowledge retrieval on the epic (first …
brentrager Jul 15, 2026
20f4239
th-494611 Smoo login in the Big Smooth chat UI (th CLI OAuth + PKCE)
brentrager Jul 15, 2026
fcd9ee7
th-8e0392 README: sales-funnel rewrite for th + the new Big Smooth
brentrager Jul 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
12 changes: 12 additions & 0 deletions .changeset/at-mention-search.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
'smooai-smooth-daemon': minor
'smooai-smooth-web': minor
---

`@` mention search in the smooth-web composer, mirroring the th code TUI (th-58b5fe).
Typing `@` opens an autocomplete popup (files + path expansion from the workspace),
backed by a new ungated `GET /search?q=` endpoint on the daemon (workspace files via
the pruned ripgrep walk, bounded by a walk budget). The endpoint is mounted via a new
`LocalServer.serve_routes()` seam. `@` and the `/smooth-mode` slash popup coexist —
exactly one shows, decided by which token the caret sits in. Pearls in mentions are a
documented follow-up (the `kind` field already accepts "pearl").
11 changes: 11 additions & 0 deletions .changeset/daemon-converges-on-operator.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'smooai-smooth-daemon': patch
---

EPIC th-c89c2a: the daemon converges fully on the operator — no second agent loop.
`th daemon` (default and `operator`) now runs only smooth-operator's local flavor,
made durable by a new sqlite `StorageAdapter` (survives restart, no Postgres) wired
through the operator's `.storage()` seam. Deleted the bespoke `serve_persistent`
path and its 13 modules (server/wire/runner/coordinator/scheduler/permission/
sqlite/approval/event/hook/session/messages) plus the dead `:4400` bind. The daemon
is now just config (egress + LLM creds) + operator + durable storage.
18 changes: 18 additions & 0 deletions .changeset/daemon-conversation-rename.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
"@smooai/smooth": patch
---

feat: rename conversations from the Big Smooth daemon PWA sidebar

Each sidebar row gains a rename affordance (a hover pencil icon, or double-click
the row) that opens an inline text input in place of the title. Enter commits,
Esc (or blur) cancels. The rename is applied optimistically to the row, then the
server's canonical (sanitized) title is reconciled onto it from the
`rename_conversation` reply.

Wires a new `renameConversation(id, title)` into the `useOperator` hook, which
sends the server's `rename_conversation` WS action
(`{action, requestId, conversationId, title}`) and reconciles the echoed
`{conversationId, title}`. Pairs with the server-side auto-title + rename
(pearl th-d5b446): auto-generated titles now appear in the sidebar, and users can
override them.
27 changes: 27 additions & 0 deletions .changeset/daemon-conversation-sidebar.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
"@smooai/smooth": minor
---

feat: conversation sidebar + resume + new-chat in the Big Smooth daemon PWA

The smooth-web SPA (`crates/smooth-web/web`) was a single, ephemeral chat — one
fresh session per load, no history. It now has a toggleable slide-in sidebar
that lists your recent conversations and lets you jump between them. Pearl
th-d5b446.

- **operator.ts** speaks three more actions of the smooth-operator WS protocol:
`list_conversations` (populates `conversations` for the sidebar, refreshed
after every turn), `create_conversation_session` with a `conversationId` (to
**resume**), and `get_conversation_messages` (loads a resumed conversation's
history into `messages`). New hook surface: `conversations`,
`activeConversationId`, `refreshConversations()`, `resumeConversation(id)`,
`newConversation()`.
- **App.tsx** gains a menu-toggle + Aurora-Glass `Sidebar`: overlays with a
backdrop on mobile, docks on desktop, highlights the active conversation, and
carries a prominent "New chat" button. The Smooth brand mark moved into the
sidebar header. No sidebar interaction leaves the current single-chat
behaviour unchanged.

Back-compat: history is rendered as text-only (past tool chips aren't
reconstructed), and the message/`updatedAt` shapes are read defensively pending
final reconciliation with the server-side action.
17 changes: 17 additions & 0 deletions .changeset/daemon-embed-operator-local-flavor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
'smooai-smooth-daemon': minor
'smooai-smooth-cli': patch
---

EPIC th-c89c2a: the daemon can host the OPERATOR's local deployment flavor
in-process. New `smooth_daemon::serve_local_flavor(addr)` boots
smooth-operator's `LocalServer` (lean build — `default-features = false` drops
all cloud adapters: AWS SDK / tokio-postgres / redis / nats; in-memory storage +
backplane), gated by an auto-provisioned local token (`SMOOTH_LOCAL_TOKEN` env →
`~/.smooth/operator-token` mode 600, generated on first run). Because the daemon
*runs the operator*, it speaks the canonical schema-driven WS protocol by
construction — the official widget and the polyglot SDK clients work natively.
Exposed as `th daemon operator [--addr 127.0.0.1:8787]`. Additive: runs
alongside the bespoke `/ws` path while the embed is validated; that bespoke
surface retires once parity lands. (Depends on two local-flavor seams added
upstream in smooth-operator: `LocalTokenVerifier` + `LocalServerBuilder::auth`.)
15 changes: 15 additions & 0 deletions .changeset/daemon-live-operator-e2e.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
'smooai-smooth-daemon': minor
---

EPIC th-c89c2a: integration + live-LLM E2E for the operator local flavor
(`tests/live_operator_e2e.rs`). Boots the local flavor in-process the way
`serve_local_flavor` does (LocalTokenVerifier + the exposed `local_tool_provider`
+ a real gateway config) and drives the canonical WS protocol with a real
client. The gated test (`SMOOTH_AGENT_E2E=1` + `SMOOAI_GATEWAY_KEY`) runs a real
LLM turn that makes the agent call the kernel-sandboxed `bash` tool and round-trips
its output back — proving protocol + agent loop + sandboxed tool execution + the
live gateway end-to-end. The always-on test documents a finding: the operator's
`/ws` degrades a missing/invalid token to an **anonymous** connection rather than
rejecting it, so `LocalTokenVerifier` does NOT gate connections (only ACL scope) —
the loopback bind is the real gate today. Module docs corrected accordingly.
10 changes: 10 additions & 0 deletions .changeset/daemon-logs-to-stderr.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
'smooai-smooth-cli': patch
---

`th daemon` subcommands (including `th daemon operator`) now log to **stderr**
instead of the TUI's `~/.smooth/log/th.log`. Daemon subcommands are
long-running services, so their tracing output should be visible in the
foreground and captured by the service supervisor (launchd/systemd via
`th service`) — not buried in the file the TUI shares. (EPIC th-c89c2a; closes
th-9eb87d — the operator's info logs were never silent, just file-routed.)
23 changes: 23 additions & 0 deletions .changeset/daemon-reachability-and-presence.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
'smooai-smooth-daemon': minor
'smooai-smooth-web': minor
---

EPIC th-c89c2a: make the daemon trivially reachable and give it a face + a voice.

- **Same-origin serve (th-a28904):** the daemon serves the smooth-web SPA at its
own origin via a new `LocalServer.serve_spa()` seam, injecting the auth token
into `index.html` (`window.__SMOOTH_TOKEN__`, read first by `operator.ts`), so
`http://127.0.0.1:8787/` works with no `?api`/`?token` query string.
- **Tailscale auto-serve (th-ce286d):** on startup, when Tailscale is present and
the node is up, the daemon exposes itself over the *tailnet* via `tailscale
serve` (never `funnel` — tailnet-private), with a `SMOOTH_TAILSCALE_SERVE=0`
opt-out and shutdown teardown.
- **Big Smooth persona (th-5f059b):** the daemon installs a personal-assistant
system prompt via the operator's new `.persona()` seam, replacing the stock
customer-support prompt.
- **smooth-web Presence glow-up (th-f1a1f0, th-833b5f):** the reactive Big Smooth
face is now the room — a haloed greeting on the empty state, a sticky presence
bar in conversation, the approval HITL emanating from him in amber, the
Bricolage Grotesque wordmark, a green liveness dot, and parked tools reading
"awaiting your okay".
11 changes: 11 additions & 0 deletions .changeset/daemon-repoint-operator-main.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'smooai-smooth-daemon': patch
---

EPIC th-c89c2a: the local-flavor seams landed on smooth-operator `main` (#108),
so the daemon's operator path-deps (`smooth-operator-server`,
`smooth-operator-svc`) now point at the canonical `../smooth-operator` checkout
instead of the temporary `smooth-local-flavor` worktree (now removed). Same
local-dev two-repo path pattern as the engine dep. (Closes th-845d79; full
CI-mergeability still needs git-rev/published deps for the engine + operator —
th-d3537a.)
12 changes: 12 additions & 0 deletions .changeset/daemon-strict-auth.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
'smooai-smooth-daemon': minor
---

EPIC th-c89c2a: the local flavor now enables the operator's **strict-auth** mode
(`LocalServerBuilder::strict_auth(true)` in `serve_local_flavor`), so a `/ws`
connection with a missing/invalid token is **rejected (HTTP 401)** instead of
degrading to an anonymous connection. This closes the gap the live e2e surfaced
(th-6d1863): `LocalTokenVerifier` now genuinely gates connections — a stray local
process or tailnet peer can't drive the agent. The widget + SDK clients carry the
token, so they're unaffected. The e2e test now asserts tokenless `/ws` is rejected
and a valid token is accepted (and the live LLM turn still runs).
18 changes: 18 additions & 0 deletions .changeset/daemon-token-iteration-headroom.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
"@smooai/smooth": patch
---

fix(daemon): give Big Smooth chat assistant-grade token/iteration headroom

The daemon's chat path resolved config via `local_config()` →
`ServerConfig::from_env()`, silently inheriting the customer-support **chat
widget** defaults (`512` max_tokens / `6` max_iterations). A reasoning model
like `deepseek-v4-flash` spends its entire 512-token budget on
`reasoning_content` and gets cut off before emitting any `content` — the
"Big Smooth seems hung" empty reply — while 6 iterations makes any
read-a-few-files turn hit "Maximum iterations reached". `resolve_gateway_config`
now gives the daemon `32768` tokens / `50` iterations unless
`SMOOTH_AGENT_MAX_TOKENS` / `SMOOTH_AGENT_MAX_ITERATIONS` explicitly override.

Also guards `BigSmoothFace` WebGL init so a GPU-unavailable browser degrades
to no 3D face instead of crashing the whole SPA.
11 changes: 11 additions & 0 deletions .changeset/daemon-tool-provider-rebase.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'smooai-smooth-daemon': patch
---

EPIC th-c89c2a: the daemon now feeds its kernel-sandboxed tools to the operator
local flavor through the operator's `#68` `ToolProvider` seam instead of the
earlier bespoke `extra_tools` list (which collided with `#68` and has been
dropped upstream). `SandboxedToolProvider::tools_for` returns
`default_tools_with_proxy(workspace, proxy)` per turn; `serve_local_flavor`
installs it via `LocalServerBuilder::tools(provider)`. Tracks the rebase of the
`smooth-local-flavor` operator branch onto `main` (post-HITL, post-#68).
8 changes: 8 additions & 0 deletions .changeset/fast-mode-groq.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'smooai-smooth-daemon': minor
---

Fix the `SMOOTH_AGENT_MODEL` override (it was a no-op) and add `SMOOTH_FAST_MODE`
— a fast mode that points Big Smooth at `groq-gpt-oss-120b` (current, fast,
strong tool-caller, reasons on the harmony channel so thinking shows cleanly).
Model priority: `SMOOTH_AGENT_MODEL` > fast-mode pin > coding route.
13 changes: 13 additions & 0 deletions .changeset/fix-find-native-operative-test.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
'smooai-smooth-bigsmooth': patch
---

Fix `find_native_operative_finds_debug_or_release_build` to accept the
`cargo install`ed binary location. `find_native_operative_binary()`
deliberately falls back to `$CARGO_HOME/bin` / `~/.cargo/bin` (th-92dac3)
when a `target/<profile>/` build isn't found near the manifest — which is
exactly the case in a worktree using a shared target dir. The test
asserted the path must be under `target/release|debug`, so it failed in
that (valid) setup. The assertion now also accepts a `bin/` install dir
while keeping the guard that the path must not be the
`aarch64-unknown-linux-musl` cross-compile output.
12 changes: 12 additions & 0 deletions .changeset/gate1-bash-enforcement.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
'smooai-smooth-tools': patch
---

EPIC th-c89c2a (th-515a13): Gate 1 deny is now enforced at the bash tool boundary.
A new `permission` module loads deny/ask/allow rules from `~/.smooth/permissions.toml`
(override `SMOOTH_PERMISSIONS_FILE`, process-global, best-effort) and the `bash`
tool now blocks any command its **deny** rules match — compound-split, so
`ls && rm -rf ~` is caught on the `rm`. A configurable complement to the hardcoded
circuit-breaker; an unconfigured daemon is unchanged (empty rules never deny).
Per-call `Ask`→HITL needs an operator host-hook seam (filed separately); `Ask`/
`Allow` proceed for now, with the name-based operator HITL covering confirmation.
11 changes: 11 additions & 0 deletions .changeset/gate1-permission-model.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'smooai-smooth-policy': patch
---

EPIC th-c89c2a (th-515a13): Gate 1 — the deterministic deny/ask/allow permission
rule model. `Decision` (Deny/Ask/Allow), `Matcher` (Claude-Code `Tool(pattern)`
syntax with `:` as a word boundary, e.g. `Bash(rm:*)` ≡ `Bash(rm *)`), and
`PermissionRules` with **deny > ask > allow** precedence and a **fail-safe `Ask`
default** (an unmatched call never silently allows). Pure model + matcher,
exhaustively tested incl. adversarial inputs. The intent layer above the kernel
sandbox; wiring it as a ToolHook on the operator registry is a following slice.
15 changes: 15 additions & 0 deletions .changeset/local-flavor-sandboxed-tools.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
'smooai-smooth-daemon': minor
'smooai-smooth-tools': minor
---

EPIC th-c89c2a: the operator local flavor now runs with the daemon's
kernel-sandboxed tools. `serve_local_flavor` builds the workspace-confined
fs/grep set + an OS-sandboxed `bash` (egress routed through the goalie proxy
when `SMOOTH_EGRESS_ALLOWLIST` is set) and installs them via the operator's
`LocalServerBuilder::tools` seam — so the agent the operator runs per turn can
act on the workspace under the same kernel-enforced security the bespoke daemon
used. New `smooth_tools::default_tools_with_proxy(workspace, proxy) ->
Vec<Arc<dyn Tool>>` (the registry helper now shares it via `register_arc`); the
egress-proxy start is factored into a reusable `start_egress_proxy()`. Workspace
defaults to the daemon's cwd, overridable with `SMOOTH_WORKSPACE`.
12 changes: 12 additions & 0 deletions .changeset/nuke-bespoke-4400-glue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
'smooai-smooth-cli': patch
'smooai-smooth-code': patch
'smooai-smooth-policy': patch
---

EPIC th-c89c2a: scrub the last bespoke `:4400` glue now that `th daemon` is the
operator. Removed `BigSmoothClient` + the dead headless-capture/SSE paths from
smooth-code (kept the `ServerEvent`/`PriorMessage` wire types the operator client
maps onto); dropped `th access` and pointed `th model`/`th doctor` health checks at
the operator (`:8787`); deleted the orphaned `smooth-credential-helper` crate and
`smooth-policy`'s vestigial `AuthConfig.leader_url`. The tree is `:4400`-free.
10 changes: 10 additions & 0 deletions .changeset/operator-hitl-approvals.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
'smooai-smooth-code': patch
---

EPIC th-c89c2a (th-1ea4f6): write-tool approvals (HITL) on the operator path. When
the operator parks a turn on `write_confirmation_required` (opt-in via
`SMOOTH_AGENT_CONFIRM_TOOLS`), `th code` now surfaces a `⚠ Approve <tool>? — [y]es/
[n]o` prompt, and `y`/`n`/`Esc` resume or deny the parked turn via a new
`confirm_tool_action` reply. This is the "ask" half of the permission model atop the
operator's kernel-sandboxed tools — replacing the deleted bespoke `:4400` approval UI.
11 changes: 11 additions & 0 deletions .changeset/operator-serves-official-widget.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'smooai-smooth-daemon': minor
---

EPIC th-c89c2a: `th daemon operator` now serves the official
`@smooai/smooth-operator` widget at `/`. `serve_local_flavor` enables the
operator's `serve_widget` seam with the local token, so the browser loads the
widget host page (token injected same-origin) and connects to the operator's own
`/ws?token=…`. One process, one port: the canonical WS protocol **and** a usable
chat UI. Additive — the bespoke control surface stays until the widget reaches
parity (markdown / tool-confirm / session list, tracked upstream).
8 changes: 8 additions & 0 deletions .changeset/permissions-check-cli.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'smooai-smooth-daemon': patch
---

EPIC th-c89c2a (th-515a13): `smooth-daemon permissions check "<cmd>"` / `--write
<path>` / `permissions path` — inspect what verdict (DENY/ASK/ALLOW) the Gate-1
rules give a command or write, so users can author + verify `~/.smooth/
permissions.toml` before relying on it. Reachable as `th daemon permissions …`.
15 changes: 15 additions & 0 deletions .changeset/phase2-remember-tool.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
'smooai-smooth-tools': patch
'smooai-smooth-daemon': patch
---

Phase 2 (EPIC th-c89c2a): close the memory loop with a `remember` tool. The
agent can now persist its own salient facts (`RememberTool` in smooth-tools)
— stable operator preferences, confirmed approaches, current project state,
external references — choosing the `MemoryType` so recall can apply the right
freshness treatment. The daemon registers it on every turn pointed at the same
`Memory` backend the engine recalls from, so a fact the agent remembers is
auto-surfaced on later turns and across restarts. The system prompt now tells
the agent to use it. `run_task`'s tool wiring is extracted into a
`build_tool_registry` helper. Tested: store→recall round-trip, type parsing,
and required-content validation.
15 changes: 15 additions & 0 deletions .changeset/phase2-sqlite-memory.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
'smooai-smooth-daemon': patch
---

Phase 2 (EPIC th-c89c2a): add durable, cross-session agent memory. A new
`SqliteMemory` implements the engine's synchronous `Memory` trait against a
`memories` table (sharing the daemon's existing SQLite connection), so an
always-on agent's recall survives restarts — the hermes-style memory the
in-memory engine backend can't persist. `store`/`forget` are direct
row ops; `recall` mirrors `InMemoryMemory`'s keyword scoring (fraction of
query words found in the content, highest first), with `MemoryType` +
metadata round-tripped as JSON. Exposed on `Stores.memory`. Wiring it into
the agent loop (`AgentConfig::with_memory`) is the next slice. Tested:
persist-across-reopen, keyword recall ordering, metadata round-trip, empty
query, and forget.
14 changes: 14 additions & 0 deletions .changeset/phase2-wire-memory-into-agent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
'smooai-smooth-daemon': patch
---

Phase 2 (EPIC th-c89c2a): wire durable memory into the agent loop. `AppState`
now carries an `Arc<dyn Memory>` (the SQLite-backed store in `persistent`,
in-memory in `new`), threaded into `run_task` and attached via
`AgentConfig::with_memory`. The engine then auto-recalls relevant entries for
each user message and injects them (with a freshness nudge for
Project/Reference types) ahead of the prompt — so a cross-session fact stored
once is recalled on later turns and across restarts. `run_task`'s growing
parameter list is bundled into a `RunDeps` struct. Follow-up: a `remember`
tool / extraction step so the agent populates its own memory. Tested:
persistent state carries durable, recallable memory across a restart.
12 changes: 12 additions & 0 deletions .changeset/phase3-bash-tool-egress-proxy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
'smooai-smooth-tools': patch
---

Phase 3 (EPIC th-c89c2a): give the `bash` tool an optional egress proxy.
`BashTool` gains a `proxy: Option<String>` field, and a new
`register_default_tools_with_proxy(registry, workspace, proxy)` installs the
default tool set with the shell's egress routed through a loopback proxy
(`SandboxPolicy::with_proxy`) — direct off-box network kernel-denied, so the
proxy's exact-host allowlist is the only way out. `register_default_tools`
is unchanged (egress unrestricted). This is the injection point the daemon
uses to wire its goalie proxy into agent shell commands.
17 changes: 17 additions & 0 deletions .changeset/phase3-daemon-egress-capstone.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
'smooai-smooth-daemon': patch
'smooai-smooth-goalie': patch
---

Phase 3 (EPIC th-c89c2a): wire the egress boundary into the daemon
end-to-end. New `config::resolve_egress()` reads `SMOOTH_EGRESS_ALLOWLIST`
(comma/space-separated exact hosts; opt-in like auth/sandbox) and
`SMOOTH_EGRESS_PROXY_ADDR`. On startup the daemon spawns goalie's
`run_proxy_local` on a loopback port, threads the proxy address onto
`AppState`, and the runner registers tools via
`register_default_tools_with_proxy` — so agent `bash` egress is forced
through the proxy's allowlist (direct off-box network kernel-denied). goalie
re-exports `run_proxy_local`/`run_proxy_with`/`NetworkDecider`. Invalid
allowlist entries are dropped and logged. Verified live: with an allowlist
set, the daemon logs `egress boundary ON`, the proxy listens, and a request
to an unlisted host returns 403.
12 changes: 12 additions & 0 deletions .changeset/phase3-deny-own-smooth-creds.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
'smooai-smooth-tools': patch
---

Phase 3 hardening (th-08e05a / EPIC th-c89c2a): the macOS Seatbelt bash
sandbox now also kernel-denies reads of the daemon's *own* credentials in
`~/.smooth` — `providers.json` (the LLM API key) and the `auth/` directory
(the auth JWT). Previously a sandboxed shell tool could `cat
~/.smooth/providers.json` and exfil exactly the secret that drives the
agent. Project-scoped `<workspace>/.smooth` pearls stay readable (different
path). Adds an adversarial test that plants a sentinel under `~/.smooth/auth`
and proves the sandbox can't read it.
Loading