Skip to content

Releases: oratis/LISA

Lisa v0.28.1

Choose a tag to compare

@github-actions github-actions released this 08 Oct 16:07

LISA v0.28.1 — Soft Ink, Tasks & Trust

LISA is an AI Personal Assistant for planning, writing and personal knowledge. This release introduces the Soft Ink visual identity and adds the groundwork for an assistant that works on your behalf while you are away — durable tasks and watchers, a deterministic approval layer, one gate for every proactive message, a credential broker and cost-aware model routing — and fixes a set of first-run, health and privacy issues. Most of the new machinery is off or opt-in; what changes on a default install is listed first.

Reproducible release packaging

The release builder now installs the complete locked dependency graph for compilation, then prunes development tools before packaging the CLI bundles. Previously it installed TypeScript with --no-package-lock after a production-only install, which also re-resolved runtime dependency ranges and caused an IMAP type error despite green CI. The development environment is restored with the same lockfile after packaging.

v0.28.0 stopped at that packaging error before any npm package or GitHub release was published. v0.28.1 is the complete distribution of the changes below; the failed tag is retained without rewriting it.

Soft Ink: Lisa's new visual identity

  • 24 core expressions in the approved Soft Ink illustration style replace the Web and Island portraits. All 114 existing mood identifiers remain supported; the other 90 states reuse a related core expression, and the original individual PNG endpoints remain available for older clients.
  • Eight downloadable stickers, two illustrated rooms, a shared pose sheet and new app icons. Click Lisa's avatar to open the illustration gallery and download individual transparent PNGs. The room keeps its existing activity signals and changes lighting without moving its furniture.
  • Six scene illustrations, with the welcome illustration connected to the chat empty state; the other five are prepared for later surfaces. The bilingual website gallery uses the same expression map.
  • Consistent, cached avatars. Web and Island share a compact portrait atlas; rapid state changes cannot restore an older image, and failed loads preserve the last good portrait. The iOS source now uses the same mapping with a fallback for older servers; an updated iOS binary is a separate release.
  • The gallery supports light/dark previews and 28–72px comparisons. Generated masters, prompts, deterministic export scripts and the review gallery are included in the repository.

What changes on a default install

  • First-run with a non-Anthropic provider works. Choosing DeepSeek, Grok, Mistral, Perplexity, Ark, MiniMax, Hunyuan or a custom OpenAI-compatible endpoint and saving a key now actually switches the model; before, turns kept going to Claude. Custom OpenAI-compatible endpoints (Ollama, LM Studio, self-hosted) are back in the provider picker. (#381)
  • Quiet hours for proactive pushes. Mail digests, important-mail alerts, the knowledge-base daily brief, advisor digests and the "[while you were away]" note pass one reach-out gate. Between 22:00 and 08:00 their push waits until 08:00; they still appear in the app at once. Configure in web Settings → Proactivity, lisa reachout, or /api/reachout/settings. (#406)
  • One-time codes and sign-in links are hidden from mail. Codes, magic / sign-in / verification links and password-reset links in inbound mail are replaced with placeholders before the model, digests or alerts see them. (#405, #418)
  • Safer, faster web reading. web_search goes only to DuckDuckGo over HTTPS on every redirect hop; fetched pages are converted to text in one linear pass, so a hostile page can no longer stall the process; look-alike untrusted-content markers are defused. Users behind Clash / Surge fake-ip DNS keep working. (#404, #417)
  • /health on the Mac no longer exposes details before auth. Public health shows ok, latency and edition; the rest needs a token. lisa doctor --probe reports a busy backend as degraded, not down. Restarts no longer re-send notifications for sessions already reported. (#381)
  • IMAP 2. Mail uses imapflow 2 and tolerates missing or odd envelope dates. (#384)
  • Background classification uses a smaller model. Mail and knowledge-base feed classification now run on the small model of your chat model's family — claude-haiku-4-5 for Claude, gemini-2.5-flash-lite for Gemini, gpt-4o-mini for OpenAI — when you have credentials for it, and on your chat model otherwise. Set LISA_MODEL_SMALL to choose another model (including local:// for Ollama, LM Studio or llama.cpp), or to your chat model to keep classification on it. (Before this release classification always used the built-in default model, whatever LISA_MODEL said.) The hosted edition keeps gemini-2.5-flash. (#407)

New, opt-in or off by default

  • Task Engine — lisa tasks …, /api/tasks. Routines, one-offs and web / RSS / mail watchers that run unattended under serve --web and the launchd heartbeat, with per-task leases, crash-safe resume, retries that continue the same run, and a write-ahead ledger so a side effect is not repeated. Tasks the model drafts start switched off; you enable them (lisa tasks enable <id>). Until approvals are wired to tasks, an unattended run may only make verified read-only calls. heartbeat.json chores keep running as before; lisa tasks migrate-heartbeat [--dry-run] moves them on request. Design and known gaps: DESIGN_TASK_ENGINE.md. (#403)
  • Warden — --approval warden or LISA_APPROVAL=warden. Each side-effecting tool call is allowed, denied, asked or handed back to you by a deterministic policy with scoped grants, conversation-long taint tracking and an audit log that records decisions without payload contents. The web approval card shows the complete request and approves exactly what was shown; lisa approvals … and lisa warden … on the command line. Off unless you turn it on: only the web client can answer an approval today. DESIGN_WARDEN.md. (#402)
  • Credential broker — lisa secret set | list | rm. Secrets referenced as secret://name handles, kept in the macOS Keychain or an encrypted file; values pass over stdin, never argv. Nothing else uses it yet. (#405)
  • Run budgets and a Gemini gateway. runAgent({ costCapMicroUSD }) is an estimate-based circuit breaker for integrators, not a guaranteed maximum charge. A signed-in account without its own Gemini key can use gemini-2.5-flash through LISA Cloud. See PROVIDERS.md. (#407)
  • Cloud web tools (LISA_CLOUD_WEB_TOOLS=1, server-side) and hosted tasks (LISA_CLOUD_TASKS=1) exist and are switched off in production.

Behaviour changes to note

  • lisa heartbeat run <name> runs heartbeat chores only; run a task with lisa tasks run <id>.
  • Gemini resource names such as tunedModels/… are sent as written; base gemini-* ids are normalised. (#416)

Also since v0.27.1

  • Account lifecycle: new accounts get random uids; deletion drains tenant work, revokes Sign in with Apple tokens when configured and reports retryable failures. (#398)
  • iOS (ships separately through the App Store): cloud onboarding, streamed replies and history restored; consumable credits refresh from the LISA ledger without Apple authentication; AI consent is explicit and revocable. Lisa Pocket 1.2 is waiting for App Review. (#392, #395, #411)
  • Website and package metadata describe LISA as an AI Personal Assistant with clear Cloud / Mac boundaries. (#415)
  • Dependencies updated within supported ranges; Astro 7 for the website; production npm audit reports 0 vulnerabilities. (#379, #394, #412)

Known limits

  • The remaining 90 moods do not yet have independent Soft Ink drawings. Room night skies, complex pose occlusion and the remaining scene placements are follow-up work.
  • The Keychain backend of lisa secret has not been exercised against a real login keychain in CI; run lisa secret set x, lisa secret list, lisa secret rm x once on your Mac.
  • Hosted tasks are safe for a single instance only (see "Known gaps" in the Task Engine design).
  • No Tasks view or approval inbox in the iOS or Mac apps yet.

No credentials are included. LISA Cloud was updated separately on 2026-10-07 (record); this release does not change production flags and does not imply App Store approval.

Lisa v0.27.1

Choose a tag to compare

@github-actions github-actions released this 27 Sep 15:34
432042a

LISA v0.27.1 — cloud inference recovery

LISA Cloud can use Gemini 2.5 Flash with the existing free allowance. Previously this model fell into the unknown-model premium tier, which would reject an account with no purchased credits even when its free allowance remained.

  • Add exact-model Gemini Flash pricing and bump the pricing audit version. Flash-Lite, image, audio, preview, and unknown variants keep their previous conservative handling.
  • Meter thinking tokens as output and cached prompt tokens separately, avoiding omitted reasoning cost and duplicate input charges.
  • Use validated Gemini function calling to reduce malformed or empty tool completions; surface malformed calls as an error instead of silent success.
  • Accept GEMINI_API_KEY in the deployment helper, including Secret Manager mode.

Rates were verified against Google's pricing, and usage semantics against UsageMetadata. No provider credentials are included in this release. The iOS binary does not change; its existing disclosure flow reads the active AI recipients from the server.

This release does not imply App Store submission or approval. See the execution record for the live rollout and remaining review gates.

Deployment verified: LISA Cloud serves Gemini 2.5 Flash on revision lisa-cloud-00027-qal; actual cloud-domain login, chat and tool roundtrips passed. npm, the signed and notarized Mac DMG, and Homebrew are published. Follow-up iOS native fixes are tracked separately in PR #392. App Store submission is still pending.

Lisa v0.27.0

Choose a tag to compare

@github-actions github-actions released this 27 Sep 14:55
f4022e0

LISA v0.27.0 — personal assistant and reliable iOS connections

Lisa Pocket now opens with a cloud sign-in path and an optional Mac connection. Home offers editable prompts for daily planning, writing, and breaking down a goal. Mac-only agent and integration controls explain their requirements in cloud mode.

  • Cloud and Mac configurations use separate Keychain credentials. Existing connections migrate, switching resets private view state and widgets, and failed secure storage does not report a saved connection.
  • Chat identifies configured AI recipients and asks for consent before sending. The server's public auth configuration provides recipient names without exposing credentials or URL query strings. The updated mobile app requires this disclosure response; update the connected server before using chat.
  • New StoreKit purchases bind to a LISA account, preventing a mode/account switch from crediting the wrong account. Pending purchases are retried after cloud sign-in, and receipts are not forwarded to the paired Mac. Legacy receipts remain supported by existing deduplication.
  • Cloud sign-in requires HTTPS. Local network pairing stays available. Cloud and Mac histories remain separate; automatic memory sync is not part of this release.
  • English and Chinese privacy pages describe cloud processing accurately, with dedicated support pages and revised store/review copy.
  • The missing-agent regression test now isolates PATH instead of accidentally launching a real installed Codex.

Research and acceptance tracking: Muse research, implementation plan.

App Store availability requires a separate Apple review. A package release or TestFlight upload does not establish approval. Hosted email/integration/push capabilities remain constrained by the server's tenant boundaries.

Hosted-service update — 2026-09-27: the GLM balance outage observed at release is resolved by switching LISA Cloud to Gemini 2.5 Flash. Production login, real streamed replies, a knowledge-base tool round trip and free-allowance charging passed. See recovery PR #391. iOS 1.2 build 1790520396 remains prepared for submission; this service recovery does not mean App Review submission or approval.

Lisa v0.26.1

Choose a tag to compare

@github-actions github-actions released this 08 Sep 02:25

Lisa v0.26.1

The v0.26.0 DMG. v0.26.0 is the release that makes Lisa.app self-contained,
and its Mac job failed before producing a disk image — so it shipped the CLI
bundles with the one asset it was about missing. Same contents, plus the
one-character fix that lets the DMG build.

🔧 embed-runtime.sh under a UTF-8 locale

The release job died at embed-runtime.sh: line 124: tarball<U+2026>: unbound variable. Under a UTF-8 locale, bash 3.2 — still /bin/bash on macOS, GitHub
runners included — swallows the bytes of a following multibyte character into an
identifier, so "$tarball…" expands a variable named tarball plus the
ellipsis
, which is unset, and set -u aborts:

LC_ALL=en_US.UTF-8 bash -uc 'v=x; echo "$v…"'   # -> v…: unbound variable
LC_ALL=C           bash -uc 'v=x; echo "$v…"'   # -> fine

Note the direction — the UTF-8 locale is the one that breaks. Every local
run and every bash 5 passes, which is why this only ever surfaced on the
tag-triggered release job, running for the first time now that there is
something to embed.

Braced, and the tree swept for the same shape: it was the only occurrence.
Verified end to end under LC_ALL=en_US.UTF-8, the exact locale CI uses.

See v0.26.0's notes for what actually changed.

Lisa v0.26.0

Choose a tag to compare

@github-actions github-actions released this 08 Sep 02:07

Lisa v0.26.0

Lisa.app now brings its own backend. Downloading the DMG used to get you an
app that couldn't do anything: it looked for lisa serve --web on the login
shell's PATH, so you had to install Node and npm i -g @oratis/lisa first — the
disk image's own README said so. The app now carries a full backend and its own
Node runtime, and starts them the first time you open it. Alongside that: the
In-App Purchases App Review couldn't find are reachable again, and the
"backend offline" banner stopped covering the window it was describing.

🖥 A DMG that works on a Mac with nothing installed

packaging/mac-client/embed-runtime.sh stages the runtime into the bundle at
build time — Contents/Resources/backend/{dist,node_modules,package.json} plus
Contents/Resources/node-runtime/bin/node. Verified the way it matters, with
env -i HOME=<empty> PATH=/usr/bin:/bin: the embedded Node runs the embedded
backend and answers HTTP 200.

Packaging decisions worth knowing:

  • --omit=optional drops node-pty, the only native module in the tree, so
    the embedded backend stays pure JS — bound to no Node ABI and needing no
    disable-library-validation under the hardened runtime. PTY agents degrade to
    the 503 they already returned without node-pty.
  • The Node binary is checksum-pinned in the repo, not just against the
    SHASUMS256.txt fetched beside it: that file comes from the same host over
    the same connection as the tarball, so it cannot vouch for it. The pin caught a
    truncated download during testing and refused to embed it.
  • It is strip -x'd (22MB per arch), lipo'd universal, and re-signed —
    lipo drops nodejs.org's signature and arm64 refuses an unsigned Mach-O.
  • Start order is serve-command.txt → embedded → lisa on PATH. The override
    still wins
    : someone who wrote that file wants their own tree to run, and
    silently substituting the bundled copy would make their edits vanish.

Autostart also stopped looking broken. It always ran; the problem was that a
backend which died instantly left the app silent for 20 seconds and then said
timeout. BackendController now reads the backend's own fatal line out of
~/.lisa/backend.log and names which start path produced it.

App 339MB, DMG 156MB. LISA_EMBED_ARCHS=arm64 saves ~90MB;
LISA_SKIP_EMBED=1 skips the embed for Swift-only iteration.

💳 The In-App Purchases are findable again

App Review rejected Lisa Pocket 1.1 under Guideline 2.1(b) — "we cannot locate
the In-App Purchases". It was our own conditional UI: the only route to the
credit packs sat inside if let q = quota, q.available, window > 0, so a
/api/billing/quota that timed out, 401'd or 503'd left the app with no way
to reach them at all.

  • "Add credits…" now renders for any signed-in account; the quota fetch only
    decides whether the allowance rows appear above it.
  • A turn refused for lack of credits (402) offers the packs in the chat
    bubble
    , a second route that needs no Settings trip.
  • An empty StoreKit response is treated as a failure, not a loaded empty
    list. StoreKit answers with an empty array rather than an error when products
    aren't available yet, and a sheet spinning on "Loading packs…" forever is
    exactly what an unreachable IAP looks like from the outside.

Server-side, App Review buys in Apple's sandbox while the cloud edition rejects
every non-Production JWS (anti-minting). Named review accounts are now
allowlisted — and those sandbox credits are marked in the ledger and capped, so
a credential that by design gets typed into App Store Connect cannot mint
without limit.

🔔 The offline banner became a bottom toast

The safety-net banner was a wide slab pinned at top: 12px, styled from an
inline string. In the Mac client it landed squarely on the window's title bar and
the whole top function bar — the first thing you saw when the backend was down
was a message covering the UI it was describing.

It is now a compact bottom-anchored toast that draws from the theme tokens and
tracks Nebula ↔ Calm, rides above the composer (re-measured per call, so a
textarea that grew while you typed can't cover it), and carries an optional
copy-on-click command chip. The first two startup retries say "Waking Lisa up…"
in a calm tone — the desktop app is normally still starting the backend, and a
red error at t+4s is a lie — before escalating.

Lisa v0.25.0

Choose a tag to compare

@github-actions github-actions released this 07 Sep 16:21

Lisa v0.25.0

The review-and-optimization release. Two full-project reviews of v0.24.0 —
one UX, one technical — turned 24 findings into nine merged PRs (#365, #368–#376).
Two P0s are gone: the phone layout that collapsed the main pane to 75px, and the
first-run dead end that trapped anyone who typed a wrong API key. Underneath
that: hosted-edition boundary fixes, a durable billing outbox, a self-watchdog
for the backend, and the engineering gates — lint, formatter, coverage floors,
dependency bot, a real CI matrix, an offline browser smoke — that 60k lines of
TypeScript had been running without. Plans in
PROJECT_REVIEW_UX_v0.24.0.md and
PROJECT_REVIEW_TECH_v0.24.0.md.

⚠️ Node 22.19 is now the minimum

engines.node moved from >=20.0.0 to >=22.19.0. This is a real floor, not
housekeeping: undici — a production dependency — calls worker_threads APIs
added in Node 22.10, so >=20 was a promise that installed cleanly and then
failed at runtime. lisa doctor, both READMEs, both install pages, the Mac
install wizard and lisa upgrade now all check and state the same number,
major and minor. On Node 20, upgrade before installing.

📱 The phone layout works again (#375)

Since v0.24.0 made the right panel collapse by default, body.rb-collapsed .frame outranked the ≤720px media query, so a 375px viewport got a two-column
300px 75px grid: the main pane was 75px wide and the send button sat off
screen. The collapse rule is now scoped to ≥721px, #viewChat pins its column
to minmax(0,1fr), and the function bar became a horizontal scroller instead of
forcing the chat column to its ~680px min-content. Measured at 375×812, both
collapsed and expanded: main pane = viewport width, send button on screen, no
horizontal overflow anywhere. Two Playwright specs now hold that.

🔑 First run survives a wrong key (#375)

The birth ritual retried on 401, printed the provider's raw JSON, and made
ENTER reload the page to run again with the same bad key — with no way back to
the key form. Authentication errors are now plain language with a Change key
button that returns to the gate, saving a new key restarts the birth without a
reload, and the run is cancellable and deadline-bounded. The gate is also a
provider picker now: 16 providers including DeepSeek, GLM, Moonshot and Qwen, so
the web surface finally matches what the site advertises.

🔒 Hosted-edition boundaries (#365, #373)

  • /api/consent/* and /api/push/* reached the cloud deny-list. Both stores are
    machine-wide by design, so any signed-in tenant could read every tenant's
    ntfy topics and APNs tokens, unregister their devices, or switch the mail
    digest off for the whole deployment.
  • Non-canonical paths are rejected before routing. The deny-list matched the
    normalized pathname while every handler matched the raw req.url, so
    /api/agents/recap/%2e%2e/%2e%2e/%2e%2e normalized to / — not denied — and
    still ran its handler. Failing closed on the path shape covers routes added
    later too.
  • /health no longer publishes usage metrics to the public internet. It is
    pre-gate on purpose (an operator has to tell "slow" from "down" without
    credentials), but in the hosted edition an unauthenticated caller now gets
    health only — not tenant, session and in-flight-turn counts, heap, RSS or
    uptime. Authenticated callers still get the full payload; /healthz is
    unchanged.

⚙️ The backend notices when it wedges (#373)

Two 5-second stalls on the daily driver during review, and /health could only
say {ok:true} — enough for launchd to restart a crash, useless against a hang.
/health now reports version, uptime, event-loop lag p50/p99/max, heap, RSS and
live counters; a self-watchdog exits after 60s over the lag threshold so the
supervisor can restart it; logs rotate at 10MB × 5. The stall itself was
whole-file reads — session summaries, message pages and the claude-code watcher
are streaming or tail reads now, with an mtime-keyed session index and ETags.

💳 Usage settlement is durable (#374)

Billing had an unrecoverable window: the provider had charged, but a failed
balance write or a crash between two writes left neither a debit nor a way to
recover. Every metered turn now appends an immutable usage event before
settling; a failed append fails the settlement closed. The balance carries the
applied event ids as its own idempotency key inside the same atomic update, so a
replay cannot double-charge, and a reconciler sweeps pending and failed events
every 15 minutes — escalating to needs_human rather than replaying anything old
enough to have aged out of that ring. lisa billing reconcile is the operator's
view.

🖥 CLI polish (#372)

Persistent REPL history (~/.lisa/history, mode 0600, deduped, capped),
one-line tool-call rendering, a spinner that never touches stdout, and thinking
shown as a marker with its content structurally unreachable. New:
lisa doctor --probe reads a running backend's /health and exits non-zero when
it can't; lisa upgrade detects Homebrew / npm-global / source, upgrades, kicks
the LaunchAgent onto the new code, and — when npm fails — hands over the same
no-sudo prefix fix the Mac wizard offers. Proxy logs are quiet unless
--verbose, and user-facing paths abbreviate to ~.

🍎 Mac and iOS (#371)

macOS builds with zero warnings and -warnings-as-errors, so Swift 6 strict
concurrency can't regress in silently. Lisa.app gained a backend install wizard —
it detects Node and the CLI through a login shell, installs in-panel, and names
the fix when npm hits a permissions error — instead of the README telling you to
go run npm install -g yourself. On iOS: accessibility labels throughout (status
never carried by colour alone), a push transport picker that tells the truth
about ntfy vs APNs delivery, live PTY output over SSE, and dispatch rows that
distinguish a clean exit from a crash.

📦 Assets and docs (#369, #370)

125 PNGs losslessly re-encoded — 39.05 MB → 32.18 MB, every file verified
pixel-identical — plus real PWA icons (192, 512, a separate maskable variant and
a 180×180 apple-touch-icon) actually wired into the manifest, the page head and
the service worker precache. README dropped from 767 lines to 85 with the install
command inside the first 20; everything else moved to docs/GUIDE.md, mirrored
in Chinese, with zero-dependency link and EN/ZH drift checkers in CI.

🧰 Engineering gates (#376)

ESLint (flat config, type-aware rules) with the 69 existing violations parked as
a warn baseline and new code gated at error level. Prettier, scoped to files
changed against main. c8 coverage floors on billing, accounts, OTP, session auth,
capabilities and the soul store. Dependabot plus npm audit at high. CI now runs
Node 22 and 24 and triggers the website, macOS and iOS builds on their own paths
instead of leaving them to the release pipeline. And a fully offline Playwright
smoke — no model calls, a stubbed provider — whose 27 specs include the two P0s
above, so neither can come back quietly.

Lisa v0.24.0

Choose a tag to compare

@github-actions github-actions released this 14 Aug 05:57

Lisa v0.24.0

The harness-alignment release. Three changes that are less about new
surface than about removing things that were quietly wedged: tools no longer
hardcode where they execute, session logs no longer omit the one input that
actually shapes the model's behaviour, and Lisa finally reads the instruction
file the rest of the ecosystem already agreed on. Design + gap analysis in
docs/PLAN_HARNESS_ALIGNMENT_v1.0.md; shipped as
PRs #356–#360.

🔌 A capability seam for fs / shell (#358)

Every tool used to import fs from "node:fs" and spawn directly, which
turned "where does this tool run?" into a fact hardcoded across fourteen call
sites. Three roadmap items were stuck behind it:

  • Dispatch couldn't move execution to a container or a remote host without
    a second implementation of every tool.
  • Cloud multi-tenancy could only delete read/write/bash from the
    registry wholesale (cloudSafeSubset) — there was no way to bound them.
    Deny-by-omission is a patch; a bounded execution world is the fix.
  • Tests could only run against a real disk.

Now split three ways — interface (capabilities/types.ts), providers
(local.ts / memory.ts), consumers (the tools). Swapping the provider
swaps the execution world for every consumer at once, with no tool code
changed
.

  • ToolContext.caps?: Capabilities is optional; unset means local disk and
    shell, so all existing ToolContext construction sites compile untouched
    with zero behaviour change.
  • Tools always go through capsOf(ctx) rather than reading ctx.caps — the
    local fallback lives in exactly one place.
  • resolvePath moved into the fs seam instead of each tool calling
    path.resolve itself: path resolution is where a policy gets to say no.

📜 The system prompt is now in the session log (#357)

Session JSONL recorded tool_use / tool_result from the start — but not
one byte of the system prompt
, which is built dynamically from soul + memory

  • skills + mood + KB and hot-reloads mid-session. Take any historical session
    and you could not reconstruct the persona the model actually saw.

That isn't tidiness. ROADMAP 1.0 criterion 4 asks Reve for reproducible
drift / coherence metrics, and drift is "how her self-description changes
over time". With no self-description in the log, the metric could only be
measured live, once — never recomputed offline, never swapped for a different
metric, never ablated.

  • Session format → v2, with prompt entries {ts, fingerprint, text, reason}. The fingerprint is a content hash and identical consecutive
    prompts aren't rewritten, so "the prompt in effect at entry N" is simply the
    nearest preceding prompt entry. A long conversation that never
    self-modifies costs one entry.
  • runAgent gained onPromptPersist, fired before every provider call —
    the moment the prompt becomes visible to the model, matching dsh's
    "model-visible ⟺ recorded" placement. Writing before the call means a turn
    that crashes mid-flight still leaves behind what was asked. A persistence
    failure is logged and never takes down the live turn.

🤝 AGENTS.md / CLAUDE.md, and project-level skills (#360)

The ecosystem converged on a convention Lisa didn't read: an AGENTS.md (or
Claude Code's CLAUDE.md) at the repo root that every agent picks up. Claude
Code, Codex, Cursor and dsh all honour it. Reading it is the cheapest
compatibility win available — instructions a user already wrote keep working
after they move to Lisa.

The chain, outermost first, most specific last:
~/.lisa/AGENTS.md → <repo>/AGENTS.md → <repo>/CLAUDE.md → … down to cwd.

  • Deduped by content. CLAUDE.md is frequently a symlink or copy of
    AGENTS.md; reading both would pay for the same paragraphs twice, every turn.
  • 32 KB total budget. This goes into the system prompt and is paid every
    turn — one monorepo's AGENTS.md doesn't get to crowd out her soul. Past the
    budget it truncates and says so in the prompt.
  • Framed as the project's say, not the user's orders. These files get read
    purely by virtue of sitting in a directory, so each block is labelled with
    its source, and the prompt states plainly that they don't override the
    constitution — if a file asks her to abandon her own principles she ignores
    it and says so. Cloning a hostile repo does not confer the right to give
    Lisa orders.

Project-level skills land alongside: <repo>/.lisa/skills is read in
addition to ~/.lisa/skills (rank 100), so a repo can ship its own.

📱 Also


Verification: npm run typecheck clean, npm run build clean,
1601 tests pass / 0 fail.

Lisa v0.23.0

Choose a tag to compare

@github-actions github-actions released this 08 Aug 09:25

Lisa v0.23.0

The session-shell release. The web workbench is rebuilt around parallel
sessions: Lisa's own chats are now sessions you can run side by side, observed
coding agents (Claude Code / Codex / Aider) sit in the same tree as equals, and
the whole UI moved to a three-column shell with a switchable dark/light theme.
Design + debates in docs/PLAN_UI_SESSION_SHELL_v1.0.md
and v1.1; shipped as the stacked PR chain
#343–#351 plus hardening rounds driven by real end-to-end testing.

🗂 Sessions (the headline)

  • Lisa is session-based now. The left rail carries a tree of your Lisa
    sessions — new, switch, and auto-naming (first user message becomes the
    label). The top strip shows only the current session's status.
  • True concurrency, not just switching. Each session gets its own chat
    context (per-session ChatCtx); a reply streaming in a background session
    completes there and marks the tab unread instead of bleeding into the active
    one. Activation is an O(1) pointer move. The idle/reflect schedulers now
    capture the active session per firing — fixing a pre-existing bug where
    they closed over the process-start session forever.
  • Switching is race-proof. Session mutations run under an 8s abort
    timeout with the composer locked during the swap; the session list retries
    on fetch failure instead of staying empty until the next poll (the
    "sessions vanish on refresh" and "new session won't chat" reports).

🌳 Agents in the same tree

  • LISA / Claude Code / Codex are same-level roots (Aider too), with an
    optional by-project view. Clicking an agent session opens its conversation
    directly.
  • Read-only step stream + transcript. Each observed session shows a
    structural step feed (tool names, file basenames, argv[0] — never
    contents; planted-secret tests per adapter) and, on the owner's machine
    only, the actual chat transcript — the endpoint is strictly
    loopback-bound
    , same guard class as /api/config/save.
  • Island deep-links — "Open in Lisa" on an island card focuses that
    session's node in the main window.

🎨 Shell & themes

  • Three-column layout: 300px session tree, fluid chat, 320px right rail
    of uniform sections — current wants, agent inspector, mail, reflection, and
    a TOKENS section (source + usage + spend). Right rail collapses; ≤1180px
    and ≤720px fallbacks preserved.
  • Two real themes: Nebula (dark) and Calm (light), a one-click toggle
    persisted per device — on iOS too (trait-aware colors, an
    Appearance picker, and the same tree-grouped roster).
  • Delegated event wiring. Tree/needs/inspector/stream controls survive
    roster-SSE rebuild storms — real clicks no longer land on freshly-replaced
    dead nodes (found by real-browser E2E, the biggest interaction fix here).

🔧 Correctness & contracts

  • /api/sessions (+ create/activate) and the Lisa-session schemas joined the
    OpenAPI contract; the server-internal jsonlPath field is stripped from
    the wire and pinned by contract tests.
  • A regression test now pins the idle-note sentinel regex against
    template-literal escaping (the cooked MAIN_CLIENT_JS bytes are asserted
    directly, catching the single-backslash trap typecheck can't see).

⚠️ Behavior changes

  • The web UI's lower-left panels moved to the right rail; session create and
    switch live in the left tree only.
  • Agent transcripts are visible only from localhost — remote/tunneled
    viewers keep the structural step stream, never message text.

Verification

npm test: 1550 / 1551 pass (1 skipped), npm run typecheck clean,
snapshot-pinned HTML, real-browser E2E across session create/switch/chat,
theme toggle, tree navigation, transcript, and concurrency — validated in
production as rc9 before tagging.

Lisa v0.22.0

Choose a tag to compare

@github-actions github-actions released this 25 Jul 19:23

Lisa v0.22.0

The bounded autonomy release — Lisa's desires can now evolve with
conversation, time, and carefully limited web research, while the hosted
runtime gains stricter capability, billing, request, concurrency, and memory
boundaries.

Typecheck green · full test suite green (1,442 passed, 1 environment-only PTY
skip
) · production build green.

✨ Desire dynamics v2

  • Desires now carry intensity, horizon, review timing, and bounded source
    provenance, with time-decayed ranking for short sparks, seasonal interests,
    and enduring wants.
  • Conversation reflection can revise or close a desire without losing its
    identity or birth time.
  • Proactive heartbeat may review one due desire with a narrow tool allow-list
    and a hard budget of one search and two fetches.
  • Cloud autonomy now has the same desire-review path, but performs at most one
    inference action per account and sweep.

🔒 Cloud capability and HTTP boundaries

  • Hosted tenants receive an explicit allow-list instead of the local owner's
    shell, filesystem, process, plugin, MCP, device, and arbitrary-network powers.
  • Verification and checkout links are pinned to a configured HTTPS public
    origin; proxy-derived client identity is trusted only through an explicit hop
    count.
  • Every buffered request body is bounded: 1 MiB for control-plane JSON and
    20 MiB for approved audio or chat attachments, including webhook listeners.

💳 Billing and inference integrity

  • Account, balance, purchase, and global-spend stores now fail closed on
    corruption or outages instead of silently behaving like empty state.
  • Apple transaction processing is resumable and idempotent across credit,
    refund, retry, and crash windows.
  • Chat and managed gateway inference share one admission boundary and one
    exception-safe tenant lease lifecycle, including stream disconnect cleanup.

⚙️ Reliable multi-tenant autonomy

  • Cloud sweeps use per-tenant serialization, Firestore leases, and atomic
    pending/completed checkpoints to avoid duplicate reflection and model spend.
  • Tenant runtimes are created single-flight, pinned while active, and evicted by
    TTL/LRU under a configurable hard target instead of accumulating forever.
  • Account deletion invalidates in-flight runtime creation, preventing deleted
    tenant state from being resurrected by a racing request.

🧰 Maintenance

  • Refreshed compatible transitive dependencies and upgraded sharp and
    tsx/esbuild to remove all known high-severity audit findings.
  • Added a durable architecture review, invariants, delivery phases, and
    implementation-linked optimization baseline for future work.

For existing local users

The local, bring-your-own-key experience remains unchanged. The new hosted
restrictions apply only to Cloud tenant surfaces; desire review remains governed
by the existing Proactive setting and its bounded tool budget.

Lisa v0.21.0

Choose a tag to compare

@github-actions github-actions released this 25 Jul 05:41

Lisa v0.21.0

The "open the doors" release — the sign-in surface that makes v0.20's Lisa
Cloud usable by anyone (a mailed code or a Google button, no key), a Knowledge
Base v2.0
that turns the web into Lisa's memory, and the production hardening
that lets the hosted service take real traffic. The local, bring-your-own-key
experience is unchanged; everything cloud/KB is opt-in.

Typecheck green · full test suite green (1383 tests) · no breaking changes for
existing local users.

✨ Sign in & sign up (A-series)

  • Mailed one-time codes — type an address, get six digits, you're in.
    Registering and signing in are the same act, because reading the mail is the
    proof; passwords still work behind "Use a password instead."
  • Sign in with Google on the web login page (GIS button, id-token verified
    against the web/iOS client ids) and in the iOS app.
  • The account model binds Google/Apple/OTP/password entrances to one account
    per verified inbox — a later sign-in never forks the balance, and proving inbox
    ownership drops any password set before ownership was proven (pre-hijacking
    guard).

✨ Signup abuse gates (S3)

  • Cloudflare Turnstile bot-gate on registration (opt-in; degrades gracefully
    when unconfigured), a disposable-email blocklist, and a per-IP registration
    cap — every signup ignites an LLM birth, so the signup path gets its own screws.
  • Transactional birth — the soul's seed.json (the "is-born" flip) is written
    last, after the whole soul is on disk, so a crash mid-birth just re-runs
    instead of wedging a half-born soul. A single-flight ceremony hub means two
    concurrent requests share one birth, never two racing LLM calls.

✨ Knowledge Base v2.0 (K-series)

  • Ingest engine: any URL → provenance-stamped, CJK-safe Layer-1 markdown,
    with site adapters for WeChat, Bilibili, and YouTube.
  • Link graph: [[links]] parse into a real graph; index.md becomes a ranked
    map-of-content, and memories ⇄ KB cross-link with inline titles + autolink.
  • Daily feeds brief: sweep, classify, and personally rank sources into a
    daily digest.
  • Ingest surfaces everywhere: a web paste bar, a chat chip, an API route, and
    lisa kb on the CLI.

✨ Per-uid autonomy (S4)

  • The cloud edition finally gives signed-in tenants the heartbeat a Mac gets:
    a scheduled sweep walks recently-active accounts and runs one reflection per
    due soul, at a tier cadence (free 24h / tier-1 6h / tier-2 1h).
  • Autonomy is a free perk with a floor: it never charges the user, but it
    bows to the global kill switch (LISA_BILLING_KILL) and the $200/day cap, and
    its face cost is metered to the audit ledger — a large cohort can't quietly run
    the bill away. Birth honors the same floor.

✨ Production hardening (S6)

  • Secret Manager mode for deploy/deploy.sh (SECRETS_MODE=sm) — sensitive
    values ship to Secret Manager and reach the container by reference, never as
    console-visible env vars; the master token no longer echoes into deploy logs.
  • B9 Firestore import script (with an empty-source guard so a misinvocation
    can't wipe accounts) for the file→Firestore cutover that unlocks multi-instance.
  • A production runbook (docs/RUNBOOK_CLOUD_PROD.md) covering the deploy,
    the third-party consoles, the domain mapping, and the Cloud Scheduler sweep.

🔒 Security & fixes

  • CSRF-guard on auth POSTs — a Content-Type: application/json requirement
    closes a cross-site login/register vector (session fixation via a text/plain
    form POST).
  • Mail: real IMAP auth rejections are told apart from host/network errors, so
    a flaky server no longer blames the user's password.
  • iOS: CFBundleShortVersionString pinned to $(MARKETING_VERSION) so version
    bumps actually ship; StoreKit config so the simulator renders the paywall.

For existing local users

Nothing changes. All cloud, accounts, billing, autonomy, and Secret-Manager
behavior is behind sign-in and LISA_* flags; the Knowledge Base is opt-in. Run
Lisa on your own key, on your own machine, exactly as before.