# Changelog
All notable changes to devist are documented here.
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/).
## [0.23.0] - 2026-05-04
### Added — Inbox audit thread
- 6th daemon thread `audit` — companion to `verify`, but answers a
different question. Where verify asks "did the user fix this?",
audit asks "should this advice have been raised in the first place?"
- **Triggers** (whichever fires first): 30-minute tick OR 5+ pending
actionable items older than 5 minutes accumulated.
- **Process**: fetches un-acked `suggest|warn|block` advice older than
5min (so fresh items have a chance to be acted on first), sends to
Claude with current strong/constraint memories injected so the
auditor can detect "this advice contradicts a user-declared
invariant", then auto-acks rejects with `acked_by='audit'` and a
reason logged.
- Cost: 1 Claude call per cycle, max 30 advice items per call.
### Why
Memory consolidation (v0.22.0) handles the Reso store. The advice
inbox needed the same treatment — even with MUST/MUST NOT in the
generation prompt, Claude can still produce noise. The audit pass
closes that loop by re-evaluating un-acked advice against the same
bar, and against the user's strong/constraint memories. Inbox
quality is now continuously evaluated, not just gated at generation.
## [0.22.0] - 2026-05-04
### Added — Reso memory consolidation thread
- New 5th daemon thread `consolidate` runs Reso's "sleep cycle":
reads all active memories, asks Claude to evaluate each against the
fact-extraction MUST/MUST NOT bar, then applies verdicts (keep,
update, merge, delete) via Supabase soft-delete + PATCH.
- **Triggers** (whichever fires first): hourly tick OR 10+ new
memories accumulated since last run.
- **Safety rails**: `source='user'` rows never auto-deleted/demoted;
`priority='constraint'` rows never auto-demoted; all mutations are
soft-delete (restorable via SQL); 60-memory cap per cycle.
- Heartbeats as thread name `consolidate` so the dashboard reflects
the new thread.
### Added — Watcher noise filter (editor artifacts)
- `is_editor_artifact()` filter blocks `*.tmp.<pid>.<ts>` atomic-write
residue, Vim swap (`.swp/.swo/.swn`), backup (`*~`), the `4913`
probe, Vite `*.timestamp-*.mjs`, smoke-test scratch (`SMOKE_*.md`),
and `tsbuildinfo`. Inbox audit on prior 28 advice items showed 9 of
them (32%) were repeated observations of these patterns.
- Unit tests cover atomic-write, Vim, Vite, SMOKE, and real-source
cases.
### Added — Project name aliases
- `WorkerConfig.project_aliases: HashMap<String, String>` lets users
pick a brand-correct casing for a watch-folder without renaming the
on-disk directory.
- Default ships `{"devist": "Devist"}` so Devist's Supabase rows
(memories, worker_events) carry the canonical brand label.
### Changed — Advice prompt mirrors facts MUST/MUST NOT
- 4 must-raise categories (concrete bugs with location, code-doc
drift with both sides cited, cross-cutting invariants, concrete
refactor wins) and 6 must-not categories (build artifacts,
gitignore nags, "consider tests", stale doc warnings, restating
diff, repeats of prior memory).
- Severity guidance: `block` reserved for prod-breaking; most output
should be `info` or `suggest`.
- Empty advice array is the expected outcome for most bursts.
## [0.21.0] - 2026-05-04
### Changed — branding + install UX
- Dashboard / landing copy capitalizes the brand to "Devist" in
user-facing prose (header, login subtitle, "What is Devist?",
overview subtitle, "Devist core" rules layer). CLI commands, paths,
and package names stay lowercase since those reflect actual shell
input.
- README Install section reorganized: Homebrew + `cargo install` are
now the documented default paths (both work today). Removed the
outdated "planned for v1.0" note.
- New README subsection explains the macOS "unidentified developer"
warning and two workarounds (`xattr -d com.apple.quarantine` or
Finder right-click → Open).
- Homebrew formula now ships a `caveats` block so the warning + fix
appear automatically after `brew install WebchemistCorp/devist/devist`.
### Why
Apple Developer ID signing ($99/year) is on the roadmap, not in scope
yet. Until then, clear documentation + a tap-side caveats block keeps
the install flow usable without surprising new users.
## [0.20.0] - 2026-05-04
### Changed — Reso fact extraction is now strict
- Rewrote the fact-extraction prompt with explicit MUST / MUST NOT
rules. Four valid categories: decision rationale (WHY), hard
constraints, cross-file invariants, and past-incident scars.
Six forbidden categories with concrete examples (dependency lists,
file structure, CI config, doc restatements, version snapshots,
observation phrasing).
- Default to empty `facts: []` when in doubt — most bursts now
produce zero memories, which is the expected outcome.
- Confidence threshold raised 0.7 → 0.85.
### Why
Earlier extractions surfaced mostly code-surface restatements
(rusqlite version, release profile flags, file paths) — information
already visible in `Cargo.toml` / `ci.yml` / module doc comments. After
13 such entries the user reported low value + heavy duplication. New
prompt makes the bar explicit: a fact is something a future maintainer
or AI cannot learn by reading the code.
## [0.19.0] - 2026-05-03
### Added — macOS launchd integration
- `devist worker enable` registers a LaunchAgent
(`~/Library/LaunchAgents/dev.webchemist.devist.worker.plist`) with
`RunAtLoad=true` + `KeepAlive=true`. Daemon now auto-starts on every
login and respawns on crash.
- `devist worker disable` removes the LaunchAgent.
- **Self-restart on update** — daemon polls its own binary mtime every
30s (after a 60s grace window). When the binary changes
(`cargo install --force`, `brew upgrade devist`) AND launchd is
managing the daemon, it exits cleanly so KeepAlive respawns the new
binary. No manual `worker stop && worker start` needed after updates.
- `worker status` shows whether launchd registration is active.
- `worker start` detects the LaunchAgent and uses `launchctl kickstart`
instead of forking, keeping the daemon under launchd's lifecycle.
macOS only — Linux/Windows fall back to the existing detached-fork flow.
### Changed
- Daemon's `run_loop` now writes its own PID file, so `worker status`
works regardless of how the daemon was launched.
- `ci.yml` triggers only on PRs (was: PRs + main pushes). Solo
workflow runs tests locally before pushing; Dependabot PRs still
validated.
- `ci.yml` dropped `publish-dry-run` job — release.yml's actual
publish covers the same checks.
### Dependencies
- rusqlite 0.31 → 0.39 (Dependabot).
## [0.18.0] - 2026-05-03
### Added — Reso unified memory system
- New `memories` table on Supabase as the canonical store, with mem0
Cloud as semantic index (dual-write). Replaces the old `worker_rules`
table + standalone mem0 design.
- Daemon writes `info` advice + high-confidence facts to Reso with
scope (`project`/`tech`/`user`) + priority
(`constraint`/`strong`/`preference`/`info`).
- `constraint` and `strong` memories are always injected into the
advice prompt; `preference` surfaces via semantic search.
- Dashboard **Memory** page replaces the old Rules page — list, scope
tabs, search, promote/demote priority, soft-delete.
### Changed
- Daemon dropped the `rules-sync` thread + entire `worker_rules` code
path. Built-in safety rules now live compiled-in
(`prompt_constants.rs`).
- Inbox redesigned: card layout with project/path in header, full-width
body, locale-aware relative time, Copy + Ack actions only.
- Page headers across Inbox/Overview/ProjectTimeline drop redundant
subtitles. Memory page title becomes "Reso 시스템".
### Fixed
- ProjectTimeline History tab crash caused by Supabase realtime channel
name collision when both Activity and History subscribed to the same
channel — channel names now include a per-instance random suffix.
### Migrations
- `0013_memories.sql` — create `memories` table.
- `0014_backfill_rules_to_memories.sql` — migrate existing
`worker_rules` rows.
- `0015_drop_worker_rules.sql` — drop legacy table.
## [0.17.2] - 2026-05-03
### Fixed
- Release workflow now passes `--allow-dirty` to `cargo publish`.
CI sometimes regenerates `Cargo.lock` after checkout, which made
v0.17.0 and v0.17.1 publishes fail to push to crates.io even though
the binaries built fine. This patch unblocks the pipeline so
`cargo install devist` picks up the latest version.
## [0.17.1] - 2026-05-03
### Tuned
- verify thread is more responsive:
- tick: 60s → **20s**
- per-project cooldown: 5min → **90s**
- per-project budget: 4/h → **8/h**
- Net effect: typical "user fixes issue → auto-ack" latency drops
from 60s–6min to ~30s–1m30s. Cost ceiling stays bounded by the
hourly budget + change-gate.
## [0.17.0] - 2026-05-03
### Changed
- `listProjects` now reads from a server-side aggregating view
(`public.project_summary`) instead of fetching 2000 raw rows and
reducing in JS. Removes the silent long-tail-project drop that
would have appeared once event volume grew.
### Migration
- `migrations/0012_project_summary_view.sql` — `CREATE OR REPLACE
VIEW … WITH (security_invoker = true)` so the existing `worker_events`
RLS policy is honored. `GRANT SELECT` to authenticated + service_role.
Idempotent.
## [0.16.0] - 2026-05-03
### Added — Advice row interactions
- 📋 **Copy** button on each advice row → `navigator.clipboard.writeText`
with brief check-mark feedback.
- ✏️ **Inline edit** — pencil icon opens a textarea, Save PATCHes
`payload.text`. Migration `0011_grant_payload_update.sql` adds the
required column-level UPDATE grant.
- ✨ **Apply with AI** — clicking the Sparkles icon shows a confirmation
modal, then INSERTs an `apply_advice` worker_job. Daemon spawns
`claude` in the project directory with `--permission-mode bypassPermissions`
so the agent can edit files surgically. On success the advice
auto-acks (`acked_by='apply'`) with a 10-second Undo strip
(Gmail-style reversibility).
- Acked badge now shows the source: `acked (verify)`, `acked (apply)`,
or `acked (user)`.
### Internal
- `ClaudeCli::ask_json_in_dir(prompt, workdir, timeout)` — wraps
`claude -p` with a working directory + bypass permissions, parses
JSON response. Used by the new `handle_apply_advice` job handler.
- `WorkerEvent.acked_by` surfaced in TS types; `ackEvent(id, source)`
signature accepts an explicit attribution.
### Migration
- `migrations/0011_grant_payload_update.sql` — `GRANT UPDATE (payload)
ON worker_events TO authenticated`. Idempotent.
## [0.15.0] - 2026-05-03
### Added — periodic, change-gated auto-verify of advice
- New 5th daemon thread `verify` runs every 60s. Per project:
1. Skip if cooldown < 5min since last check.
2. Skip if no `file_changed` in local SQLite since last verify
(change-gate — no tokens spent on quiet projects).
3. Fetch un-acked, **verifiable** advice from Supabase.
4. Read current content of the referenced files (locally, no
extra Supabase round-trips).
5. One Claude call per project: which items are resolved?
Conservative prompt — only resolved=true if the issue is
clearly absent from current file content.
6. PATCH each resolved row with `acked_at=now()`,
`acked_by='verify'`.
- Per-project rate limit: 4 verify calls per hour
(sliding-window `HourlyLimiter`).
- Advice generation now emits `verifiable: true|false` per item +
`paths: [...]`. Subjective advice (`verifiable=false`) is ignored
by the verify thread.
### Added
- Migration `0010_acked_by.sql` adds `worker_events.acked_by` text
column (`'user'` | `'verify'` | `'apply'`). Authenticated users
retain UPDATE permission on it alongside `acked_at`.
- `Db::distinct_projects()` and `Db::project_has_changes_since()`
helpers backing the verify thread's local-SQLite gate.
- `SupabaseClient::list_pending_verifiable_advice(project)` and
`ack_event(id, source)` for the verify ↔ Supabase round-trip.
- `urlencoding` dependency for safe project-name URL encoding.
### Why
File events themselves are too noisy to drive auto-ack. Periodic
batched verification with a change-gate keeps cost bounded
(typical day: ~10-30 Claude calls instead of hundreds), preserves
local SQLite as the source of truth for activity, and reads
Supabase only when there's actually pending work.
## [0.14.0] - 2026-05-03
### Changed — daemon advice locale follows the user automatically
- `auto` advice (file-change burst) used to use the static
`advice_locale` from worker config (default `"ko"`). It now resolves
the user's current language preference at write time:
1. `public.user_locale_pref` view (latest user's
`auth.users.raw_user_meta_data.lang`)
2. fallback to `cfg.advice_locale`
- Same resolution for AI rule-generation jobs when the dashboard
doesn't pass an explicit `input.locale`.
- `SupabaseClient::get_user_locale()` caches the value for 5 minutes
→ ~one extra REST hit per cache window, otherwise zero overhead.
- Failures (HTTP, missing view, no preference) silently fall back to
config — advice generation never blocks on locale resolution.
### Added
- Migration `0009_user_locale_pref_view.sql` — public view exposing
the most-recently-active user's `lang`. Restricted to `service_role`.
### Removed
- Japanese (`ja`) from the dashboard. Two languages only: `en`, `ko`.
Translation of dynamic content turned out to be too much surface
area for too little benefit; `advice_locale` write-at-source is the
canonical answer.
### Notes
- Single-user assumption: the view returns one row (latest user). For
multi-user, replace with a per-(client_id) mapping table.
- Existing English advice rows from earlier daemon runs were
one-shot translated to Korean in the conversation log; not part of
any migration.
## [0.13.0] - 2026-05-03
### Added — locale-aware AI output
- `WorkerConfig.advice_locale` (default `"ko"`). Daemon's advice prompt
appends an explicit instruction to write all natural-language strings
(every `text`, every `explain` field) in this BCP-47 language code.
JSON keys/structure stay English regardless.
- `worker_jobs.input.locale` is honored per-request — the dashboard
passes the user's current UI language so AI-generated rule drafts come
back in that language. Falls back to `advice_locale` from config.
- Dashboard now translates `severity` (info/suggest/warn/block) and
`event_type` (advice/advice_error/file_changed/scan/...) per language.
Filter buttons, EventRow badges, and the "acked" pill all localized
for en/ko/ja.
### Added — Japanese
- Full `ja` dictionary covering Landing / Login / Dashboard / pages.
- `LANGUAGES` array exposes `English / 한국어 / 日本語`.
### Changed
- `LanguageSwitch` uses shadcn/ui `Select` (not native `<select>`).
- I18nProvider now syncs language preference to
`auth.users.user_metadata.lang` so it follows the user across devices.
- Sidebar title is the typographic logo `DEVIST` + small `DASHBOARD`
caption + email.
## [0.12.0] - 2026-05-03
### Changed (breaking)
- Rules are now two layers: **devist core** (built-in, immutable,
ships with the binary) + **user global** (single editable file at
`~/.devist/worker/rules.md`). Per-project rules removed.
- `devist worker rules path|show|init` no longer accept `--project`.
- `Rules::load(monitor, project)` → `Rules::load_global()`.
- Templates no longer ship `.devist/rules.md.tmpl`.
### Added
- `BUILTIN_RULES` constant in `src/worker/rules.rs` with output
discipline, safety, scope, and tone sections that always inject
into the Claude advice prompt regardless of user config.
- Dashboard Rules page redesigned: collapsible read-only "devist core"
panel at top, single editable user textarea below. The AI generation
flow now operates on the user layer only.
### Migrations
- `migrations/0008_drop_project_rules.sql` deletes any
`scope LIKE 'project:%'` rows from `worker_rules`. Idempotent.
### Why
Per-project rules added cognitive load (which scope am I editing?)
without commensurate value. A few well-written global rules + the
project's own `CLAUDE.md` cover the same ground more cleanly.
## [0.11.0] - 2026-05-03
### Changed
- Daemon no longer pushes `file_changed` / `file_changed_continuous`
events to Supabase. They remain in local SQLite (so `worker watch`
CLI and the burst-based advice trigger keep working) but stop
flooding the dashboard. Sync log now reads e.g.
`[sync] pushed 0 events to Supabase (1 local-only)`.
### Migration
- `migrations/0007_drop_file_changed_events.sql` — one-shot DELETE
of historical `file_changed*` rows from the cloud table. Idempotent.
### Why
A typical workday produced thousands of file-change rows that drowned
out the few advice items that mattered. The dashboard's "Recent
events" was essentially noise. Local SQLite is unaffected — full
fidelity stays where forensic detail is useful (the CLI).
## [0.10.0] - 2026-05-03
### Added — Per-thread daemon heartbeat
- Migration `0006_worker_heartbeat.sql` adds the table
`(client_id, thread, last_beat_at)` with composite PK, RLS
authenticated read, joined to supabase_realtime. Daemon writes via
service-role.
- Each daemon thread emits a heartbeat every ~10s during its loop:
`main` (in the watcher poll), `advice` (now uses recv_timeout so it
beats while idle), `rules-sync`, `jobs`. Failure to write a heartbeat
is non-fatal — best-effort.
- Thread spawns are wrapped in `panic::catch_unwind` so a panic
surfaces as `[<thread>] thread panicked` in the log instead of
silently leaving the PID alive while the thread is dead.
- Dashboard sidebar shows a small `DaemonStatus` widget under the
user email: ● green if all threads beat within 30s, yellow within
2 min, red beyond. Click expands a per-thread breakdown with the
age in seconds. Polls every 10s.
### Why
Previously `devist worker status` only checked the PID, so a thread
crashing silently (e.g. `jobs` panic) showed as `running` while no
jobs were processed. The dashboard now surfaces the truth.
## [0.9.0] - 2026-05-03
### Added — Rules editor Phase 2 (AI assistance)
- Migration `0005_worker_jobs.sql` adds the queue table:
`worker_jobs (id, kind, scope, input jsonb, output jsonb, status,
error, client_id, created_at, updated_at)` with auto-touched
`updated_at`, RLS (authenticated read + insert), and realtime.
- Daemon spawns a `jobs` worker thread that polls every 5s for
`status='pending'` rows, atomically claims via
`UPDATE WHERE id=X AND status='pending'`, dispatches by `kind`,
spawns `claude -p` for `generate_rules`, writes back `output` +
`status='done'` (or `'error'` with `error` text).
- Dashboard Rules page gains an AI assistant section:
natural-language intent textarea → "Generate" button → INSERT
`worker_jobs` row → realtime subscription on that row → preview
pane with Claude's draft + explanation → "Use this draft" loads
it into the editor (still editable before save).
### Notes
- `generate_rules` prompt asks Claude to MERGE with current content
rather than replace, so iterating rules with successive prompts is
additive by default.
- Realtime is the primary update path; a 4s polling fallback handles
the case where the user reloads after submitting.
## [0.8.0] - 2026-05-03
### Added
- **Rules editor** (Phase 1: editor + sync, no AI yet).
- Migration `0004_worker_rules.sql` adds the table + auto-touched
`updated_at` trigger + RLS policies (authenticated read+write) +
realtime publication.
- Daemon spawns a `rules_sync` thread that bootstraps any local
`rules.md` content into the table on first run, then polls the
table every 10s and mirrors changed rows to the appropriate local
file (global → `~/.devist/worker/rules.md`, project scope →
`<monitor>/<name>/.devist/rules.md`).
- Dashboard ships a `/dashboard/rules` page with scope picker
(global + per project), textarea, save button, and a
"last updated" relative time.
- Daemon log tags: `[rules-sync] thread up`,
`[rules-sync] bootstrapped <scope> from <path>`,
`[rules-sync] wrote <path> (updated_at=...)`.
### Notes
- Table is canonical: edits made directly to local files after
bootstrap are not pushed back. Use the dashboard or restart the
daemon (with the table row deleted) to re-bootstrap.
- AI-assisted rule generation (Phase 2) lands later: dashboard
describes intent in natural language → daemon spawns claude CLI
via a `worker_jobs` queue → result returned to dashboard.
## [0.7.0] - 2026-05-03
### Added
- `devist project sync <name>` — add-only sync from the project's
template. Walks the latest template files and copies any that don't
already exist in the project. Existing files are never overwritten,
so user edits are safe. Useful for catching old projects up to new
template scaffolds (e.g. the `.claude/`, `_workspace/`, `.devist/`
files added in the recent templates release).
- `--dry-run` flag prints what would change without writing.
- `--var key=value` overrides for rendering newly added templated files
(mirrors `devist init`).
### Notes
- Idempotent: a second sync with no template changes is a no-op.
- This is intentionally a one-way "fast forward" for missing files
only. A full 3-way merge (with lockfile + diff) is a separate
feature that will land later if needed.
## [0.6.0] - 2026-05-03
### Added
- `render.rs` now supports conditional blocks:
- `{{#if VAR}}...{{/if}}` — render when `VAR` is set and non-empty
- `{{#unless VAR}}...{{/unless}}` — render when `VAR` is unset/empty
- Nesting works. Inside a *skipped* branch, unknown variable references
are tolerated (they wouldn't be reachable anyway). Active regions
still error on unknown vars.
- `agent_mode` is a recognized template variable. `devist init` derives
`is_devist` and `is_vibe` boolean-style vars from it (default
`agent_mode = "devist"`). Templates can now ship a single
`CLAUDE.md.tmpl` that conditionally renders devist-flavored or
vibe-flavored content.
- Companion `devist-templates` release pairs every template with
`CLAUDE.md.tmpl` + `AGENT.md.tmpl`, and adds a new `react-vite`
template (no Supabase, pure React + Vite + TS + Tailwind v4 +
shadcn/ui).
### Tests
- 12 render unit tests covering conditional truthy/falsy/nested cases,
skipped-branch tolerance, unmatched/unclosed errors.
## [0.5.0] - 2026-05-03
### Security
- New `src/worker/secrets.rs` module with a 4-layer blocklist
(filenames, prefixes, extensions, path segments). Matched paths are
dropped at the daemon — never recorded in SQLite, never pushed to
Supabase, never read by the advice pipeline. Defense-in-depth check
also runs in `advice.rs::collect_snippets`.
- 7 unit tests cover dotenv family, credential files, key extensions,
`~/.ssh` / `~/.aws` / `secrets/` segments, case-insensitivity, and
Windows separators.
### Changed
- mem0 search query now summarizes the burst's parent dirs, filenames,
and extensions (e.g. `"Project foo: edits in src/auth affecting
login.tsx (tsx, ts)..."`) instead of the prior keyword-style
`"project: foo"` which never matched stored facts.
### Added (web dashboard)
- Realtime subscription via Supabase channel (`useRealtimeWorkerEvents`).
Inbox, Project timeline, and Overview update live on INSERT/UPDATE.
Project timeline subscribes with a server-side `project=eq.X` filter.
- Acknowledge flow: per-row Ack button on advice rows. Acked rows
render muted with a strikethrough title and "ACKED" badge. Inbox and
Project timeline have a "Show acked" toggle.
### Migrations
- `migrations/0003_worker_events_realtime_and_ack.sql` — adds the table
to `supabase_realtime` publication and creates a column-restricted
UPDATE policy (`GRANT UPDATE (acked_at)` + RLS) so authenticated
dashboard users can only mutate `acked_at`, not other columns.
- Fixed `migrations/0002` — replaced unsupported
`CREATE POLICY IF NOT EXISTS` with a `DROP POLICY IF EXISTS` + create
pattern so the file is idempotent.
## [0.4.0] - 2026-05-02
### Added
- Real Supabase L2 push (replaces the prior stub):
- `migrations/0001_worker_events.sql` defines the table, idempotency
index `(client_id, client_event_id)`, and RLS enable.
- `WorkerConfig.client_id` (defaults to hostname) is the per-host
idempotency key.
- Daemon batch-flushes up to 500 unsynced rows every
`sync_interval_secs`, marks them synced on success, retries on the
next interval otherwise.
- Rules system that shapes Claude advice deterministically:
- Global `~/.devist/worker/rules.md` and per-project
`<monitor>/<project>/.devist/rules.md`. Both plain markdown,
concatenated and prepended to the advice prompt.
- `devist worker rules path|show|init [--project N]` to manage them.
- `rules init` writes a starter template (Korean tone, focus areas,
mem0 persistence policy).
### Changed
- Advice prompt now starts with a "User-defined rules (follow these
strictly)" section when rules are present.
## [0.3.0] - 2026-05-02
### Changed (breaking)
- Removed `devist brief`, `devist scan`, `devist explain`, `devist watch`
CLI commands. The underlying scanner/git helpers remain as internal
libraries for the worker.
### Added
- `devist worker` background daemon that observes a parent folder of
projects and records every file event into a local SQLite store
(`~/.devist/worker/worker.db`).
- `worker start` (with first-run setup), `worker stop`, `worker status`,
`worker watch` (live tail), `worker config show|get|set|path`.
- AI advice generation (Phase 2):
- Idle-burst trigger: after `advice_idle_seconds` of quiet on a
project, the daemon spawns the `claude` CLI with the changed
snippets and recent mem0 memories to extract facts + advice.
- mem0 Cloud integration (`api.mem0.ai`) for long-term semantic
memory of facts above `mem0_confidence_threshold`.
- 4-tier guard against runaway calls: `advice_enabled` kill switch,
`advice_min_batch`, per-project `advice_max_per_hour`, global
`mem0_max_writes_per_hour` sliding-window limiters.
- `worker advice [--project N] [--limit N]` lists generated advice.
- `worker memory search <query>` for ad-hoc mem0 lookup.
- `devist doctor` now also checks the `claude` CLI.
### Notes
- The daemon writes its log to `~/.devist/worker/worker.log` and PID to
`worker.pid`. Restart after changing config (`worker stop && start`).
- mem0 + Claude integration is opt-in: without `mem0_api_key` the worker
silently skips advice generation; the SQLite event log still works.
## [0.2.0] - 2026-05-02
### Changed (breaking)
- Renamed CLI command `devist projects` → `devist project`
(e.g. `devist project list`, `devist project forget <name>`).
### Added
- `devist start <name> --dev` now runs the template's `install` command
(e.g. `pnpm install`) automatically when `package.json` exists but
`node_modules` is missing, before launching the dev server.
- Release workflow publishes GitHub Releases directly (no draft step).
## [0.1.1] - 2026-05-02
### Fixed
- Release workflow now downloads SHA files via GitHub API,
supporting draft releases.
- `cargo publish` step is idempotent — re-running on an existing
version is treated as a non-fatal no-op.
## [0.1.0] - 2026-05-02
Initial beta release. Phase 1 through Phase 4 complete.
### Added
- Core CLI with 12 commands: `setup`, `doctor`, `about`, `template` (list/add/sync/remove),
`projects` (list/forget), `init`, `start`, `stop`, `brief`, `scan`, `explain`, `watch`.
- Template system with `devist.toml` manifest, variable substitution via
`*.tmpl` files, automatic discovery of single- and multi-template repos.
- Lazy backend management: only one project's `supabase`/`docker-compose`
stack runs at a time. `start` automatically stops any other active
project's backend.
- Code comprehension commands (`brief`, `scan`, `explain`, `watch`) for
understanding AI-assisted codebases.
- Workspace at `~/.devist/` with `config.toml`, `registry.toml`, `state.toml`,
and template cache.
- 7 official templates: `react-supabase`, `react-native-supabase`,
`flutter-supabase`, `fastapi-postgres`, `nestjs-postgres`, `rust-axum`,
`wordpress`.
### Notes
- Beta — APIs and template manifest schema may change before v1.0.
- Public Homebrew tap and crates.io publish targeted for v1.0.
[Unreleased]: https://github.com/WebchemistCorp/devist/compare/v0.17.2...HEAD
[0.17.2]: https://github.com/WebchemistCorp/devist/releases/tag/v0.17.2
[0.17.1]: https://github.com/WebchemistCorp/devist/releases/tag/v0.17.1
[0.17.0]: https://github.com/WebchemistCorp/devist/releases/tag/v0.17.0
[0.16.0]: https://github.com/WebchemistCorp/devist/releases/tag/v0.16.0
[0.15.0]: https://github.com/WebchemistCorp/devist/releases/tag/v0.15.0
[0.14.0]: https://github.com/WebchemistCorp/devist/releases/tag/v0.14.0
[0.13.0]: https://github.com/WebchemistCorp/devist/releases/tag/v0.13.0
[0.12.0]: https://github.com/WebchemistCorp/devist/releases/tag/v0.12.0
[0.11.0]: https://github.com/WebchemistCorp/devist/releases/tag/v0.11.0
[0.10.0]: https://github.com/WebchemistCorp/devist/releases/tag/v0.10.0
[0.9.0]: https://github.com/WebchemistCorp/devist/releases/tag/v0.9.0
[0.8.0]: https://github.com/WebchemistCorp/devist/releases/tag/v0.8.0
[0.7.0]: https://github.com/WebchemistCorp/devist/releases/tag/v0.7.0
[0.6.0]: https://github.com/WebchemistCorp/devist/releases/tag/v0.6.0
[0.5.0]: https://github.com/WebchemistCorp/devist/releases/tag/v0.5.0
[0.4.0]: https://github.com/WebchemistCorp/devist/releases/tag/v0.4.0
[0.3.0]: https://github.com/WebchemistCorp/devist/releases/tag/v0.3.0
[0.2.0]: https://github.com/WebchemistCorp/devist/releases/tag/v0.2.0
[0.1.1]: https://github.com/WebchemistCorp/devist/releases/tag/v0.1.1
[0.1.0]: https://github.com/WebchemistCorp/devist/releases/tag/v0.1.0