Skip to content

dreamd v0.1.0

Latest

Choose a tag to compare

@github-actions github-actions released this 05 Aug 13:56
· 34 commits to main since this release

Changed

  • CLI arms that open the Tantivy index no longer hoist a stdout / stderr lock. A hoisted StdoutLock / StderrLock is process-wide, so a command holding one across an index open could deadlock against Tantivy's own logging threads — the root cause behind the doctor --repair hang (AILAB-575). recall, score, and setup now write through unlocked std::io::stdout() / stderr() handles, which lock and release per writeln!. The eight arms that still hoist — archive, init, migrate, reset workspace, status, uninstall, update, version — each carry an inline // lock-ok (AILAB-583): rationale naming why they never open an index, and AGENTS.md now requires that rationale so a new or changed arm cannot silently reintroduce the hang. No user-visible output change. (AILAB-583 — crates/dreamd-cli/src/cli.rs, AGENTS.md)
  • The State-Drift benchmark is now the WasTrue benchmark. The Oct-2026 third-party eval scaffold was renamed throughout: scripts/benchmark/state_drift_bench.pywastrue_bench.py, along with its --demo / --verify-determinism / --bakeoff command references, the benchmark README, and the root README's roadmap row and methodology section. Repository tooling and documentation only — nothing in the shipped dreamd binary or the dreamd-mcp package changes. (AILAB-593 — scripts/benchmark/, README.md)

Fixed

  • uninstall / update no longer stop other homes' (or other users') dreamd servers. Both commands stopped local servers by shelling out to the manual README recipe's bare pkill -f 'dreamd mcp' / pkill -f 'dreamd watch', which is machine-global by construction: it SIGTERMs every process on the box whose command line matches, whatever $HOME it serves. The 2026-08-03 clean-box audit caught it (AILAB-554 F1) — a sandboxed HOME=/tmp/… dreamd update killed the developer's real Cursor dreamd mcp. The stop pass now enumerates the process table itself, keeps only entries that are the dreamd binary with a matching command line, and attributes each one to this invocation's scope before signalling: its executable must live under this $HOME's ~/.cache/dreamd-mcp, or its own HOME= must resolve to this $HOME. Everything else is left running, named on stderr, and reported to the caller so the restart contract cannot claim "no processes were running" about a daemon that is still up. Attribution data that cannot be read (another user's /proc/<pid>/environ is EACCES) fails closed — failing to stop a daemon costs one command, killing someone else's does not. An empty HOME is now treated as no home at all, since $HOME/.cache/dreamd-mcp would otherwise collapse to a cwd-relative path that attributes foreign processes (and, in uninstall, a cwd-relative ./.npm/_npx the scoped cache clear would delete). Covered by unit tests over a synthetic /proc tree, a cross-$HOME integration suite that spares and then stops a really-running dreamd watch, and a live step in the install-funnel suite. The packages/dreamd-mcp manual recipe no longer teaches the unscoped kill. (AILAB-584 — crates/dreamd-cli/src/commands/lifecycle_cleanup.rs, cli.rs, uninstall.rs, update.rs, packages/dreamd-mcp/README.md, scripts/alpha/install-funnel-suite.sh)
  • uninstall / update no longer unlink a live daemon's socket. Both commands run a best-effort pkill stop pass whose failure is only a stderr warning, so on a box without pkill — or where the signal is denied — the daemon was still serving when its socket file was removed. That orphaned it: the daemon kept working while every client resolved a path that no longer existed, so MCP silently fell back to the in-process Phase 1 backend and cross-harness recall stopped with no error. remove_socket now connect-probes first and leaves a live socket in place with an actionable warning, matching the rule dreamd archive and dreamd doctor --repair already apply. Because pkill returns when the signal is delivered rather than when the target exits — and dreamd watch drains its coordinator and Tantivy indexer before unlinking its own socket — the probe waits out a 5s grace window first, so a daemon that is merely mid-shutdown is not mistaken for one that refused to stop. (crates/dreamd-cli/src/commands/lifecycle_cleanup.rs, uninstall.rs, update.rs)
  • A healthy index is no longer wiped by a false schema-mismatch match. is_schema_incompatible gates a remove_dir_all of the index cache but matched a bare "schema" substring anywhere in the error text. tantivy_io_to_index embeds the directory path in its message, so any store living under a path containing "schema" (e.g. ~/dev/schema-tools/) tripped the branch and silently rebuilt a healthy index. It now matches tantivy's exact SchemaError rendering ("Schema error: '…'"). The companion || msg.contains("incompatible") alternative was removed: TantivyError::IncompatibleIndex renders through Incompatibility's hand-written Debug as "Library version: N, index version: M. …", so it never matched that variant and only widened the false-positive surface — an index-format mismatch stays a loud startup error rather than a silent wipe. (crates/dreamd-core/src/server/tantivy_handle.rs)

SHA-256 checksums

7ed46898b762a1c660b56dd64d54252d7daac5307404ef6750bf7a91d6d618e3  dist/darwin-aarch64.tar.gz/darwin-aarch64.tar.gz
8aed3bc579d36632d2fcc27dfe18bcfe0bf3f871ccf9e600032b8d72a9827826  dist/darwin-x86_64.tar.gz/darwin-x86_64.tar.gz
ce0b4a5992fac5569cdb220cf0b11c3740cc4af48606b00fa726ace747941ec0  dist/linux-x86_64-musl.tar.gz/linux-x86_64-musl.tar.gz
7ebf5a8cf752fcf96dd6e88c4db31069d9a7f2176b0e56240b16dc3c42b46566  dist/linux-x86_64.tar.gz/linux-x86_64.tar.gz