v0.38.0.0 Smoke Test Report
Editor’s Note (v0.39.3.0): This report was contributed verbatim from PR #1299 (Production smoke test of the v0.38.0.0 ingestion cathedral release on a live Postgres-backed server (Supabase, pgvector, PgBouncer transaction mode). Test date: 2026-05-22 Server: MCP HTTP server v0.38.0.0 on port 3131, Postgres engine Prior version: v0.37.9.0thebuildceo-agents). Two findings were re-diagnosed during the v0.39.3.0 wave; seeCHANGELOG.mdfor corrections:All 2 bugs and 10 warnings are addressed in v0.39.3.0. The report below is preserved as the historical record of what production looked like on 2026-05-22.
- BUG-2 location: the empty-body crash site is the
elsebranch atsrc/commands/serve-http.ts:1594-1597(Buffer.from(JSON.stringify(req.body), 'utf8')throws whenreq.body === undefinedbecauseJSON.stringify(undefined) === undefined), not line 1508 as originally reported. The empty-Buffer guard at:1600correctly fires for empty Buffers but never reaches the undefined case.- WARN-5 root cause:
modusbrain capture --helpis minimal becausecaptureis missing from theCLI_ONLY_SELF_HELPset atsrc/cli.ts:34-53. The detailedHELPconstant atsrc/commands/capture.ts:90-113is correct and comprehensive but unreachable; the dispatcher’s generic short-circuit at:95firesprintCliOnlyHelp(command)first.brainstormandlsdare in the self-help set, which is why their help works.
Summary
🐛 Bugs (2)
BUG-1: capture --file doubles frontmatter on files with existing frontmatter
Severity: Medium
Repro:
title: '---' (it parsed the inner --- delimiter as the title), and
the original frontmatter is preserved verbatim inside the body:
buildContent should detect existing frontmatter (the commit
message says it has a “looks like markdown” heuristic for first-line heading
or frontmatter delimiter) and not double-wrap. The inner frontmatter fields
should merge with capture’s fields.
Location: src/commands/brainstorm.ts → buildContent function (shared
with capture).
BUG-2: POST /ingest crashes with unhandled TypeError on empty body
Severity: Medium Repro:empty_body check (documented in the
code and tested in the E2E suite), but the body-parser middleware for
/ingest uses express.raw() which returns undefined for an empty POST
(no Content-Length, no body). The empty_body guard fires AFTER the
computeContentHash(body) call, which crashes on undefined.
Fix: Move the null/undefined/empty-buffer check before the content-hash
computation, or add a guard at the top of the route handler:
⚠️ Warnings (10)
WARN-1: Dedup does not actually deduplicate identical captures
Observed: Capturing identical text twice produces the same slug but differentcontent_hash values:
captured_at changes between runs (it’s timestamped).
The slug is deterministic (derived from content text), so it correctly
maps to the same page — but the hash changes every time.
Impact: The “24h content-hash LRU dedup” in the daemon layer won’t
catch duplicate captures because the hash differs. The put_page
upsert catches it at the slug level (overwrites), so no duplicate pages
are created — but the content_hash-based dedup layer is effectively
bypassed for CLI captures.
Suggestion: Compute content_hash from the user’s input text before
adding frontmatter, or exclude captured_at from the hash computation.
WARN-2: Same text with different --type flags overwrites the previous capture
Same slug is generated for identical text regardless of --type. The
second capture with --type observation silently overwrites the first
with --type idea. This is correct behavior (slug = content hash), but
may surprise users who expect type changes to produce distinct pages.
WARN-3: --source flag crashes with raw FK violation
WARN-4: facts:absorb connection error after every capture
Every capture logs:
WARN-5: capture --help is minimal — doesn’t show flags
brainstorm --help which has a full Options section,
examples, and cost info. The capture help should document --type,
--file, --source, --json, --stdin, --slug, etc.
WARN-6: capture, brainstorm, lsd missing from modusbrain --help
None of these three commands appear in the main help text. They work when
invoked directly, but users can’t discover them from the help output.
modusbrain --help lists every other command (get, put, search, etc.) but
the v0.37/v0.38 commands are absent.
WARN-7: Binary file capture succeeds silently
WARN-8: Provenance columns not populated by capture
The capture CLI reports "source_kind": "capture-cli" in its JSON output,
but the actual database row has:
put_page call that persists the page.
WARN-9: Admin register-client ignores scope parameter
Registering a client via/admin/api/register-client with
"scope": "read write" creates a client with scope "read" only.
The admin endpoint appears to ignore or default the scope field. Required
manual DB update to get write scope for webhook testing.
WARN-10: brainstorm / lsd may hang or timeout on PgBouncer
In transaction-mode PgBouncer environments, brainstorm consistently
times out after the cost estimate with canceling statement due to statement timeout. The hybrid search + domain-bank phase appears to
hit PgBouncer’s statement timeout. This may be environmental, but the
command should handle the timeout gracefully and report what failed
rather than silently producing no output.
✅ What Works Well
modusbrain capture "text"— works perfectly for the simple case. Frontmatter stamps, JSON output, disk write, immediate searchability.modusbrain capture --file— works for plain text and simple markdown (frontmatter doubling bug only affects files with existing frontmatter).modusbrain capture ""and no-args — clean error messages:"provide content positionally, --file PATH, or --stdin".modusbrain capture --file /nonexistent— clean ENOENT error.- Unicode/emoji —
modusbrain capture "测试 🧠🔥 émojis"works perfectly. - Long text — 2500+ character capture works, correctly produces 2 chunks.
- POST /ingest auth gate — properly rejects missing auth (401), invalid tokens (401), and insufficient scope (403).
- POST /ingest content-type validation — properly rejects image/png and application/pdf with a helpful error pointing to skillpack processors.
- POST /ingest accepted types — text/plain, text/markdown, text/html, application/json all accepted and queued.
- X-Modusbrain-Source-Id header — custom source ID flows through correctly.
- MCP health endpoint — returns clean JSON with version and engine.
- OAuth client_credentials flow — works correctly once the client has proper scope.
- Content-hash dedup on webhook — verified via response
content_hash. - Migration v81 — provenance columns added cleanly, nullable, no disruption to existing pages. 290K+ existing pages unaffected.
brainstorm --help/lsd --help— excellent help text with examples, cost estimates, and cross-references.- Soft delete + recovery — cleanup via
modusbrain deleteworks with 72h recovery window. --typeflag —note,idea,observationall work correctly.
💡 Suggestions
-
capture --helpparity — give it the same quality help text asbrainstorm --help. Document every flag. -
Main help completeness — add
capture,brainstorm, andlsdto themodusbrain --helpcommand listing. These are user-facing features that can’t be discovered. - Content-hash stability — consider computing the dedup hash from user input text only (before frontmatter injection) so identical captures are properly deduped at the daemon layer.
-
Provenance write-through —
capturealready knows it’ssource_kind: "capture-cli". Pass this through toput_pageso the DB columns are populated. -
Binary file guard — reject or warn on non-text input in
capture --file. Check file content or extension before proceeding. -
--sourceerror UX — catch the FK violation and print a human-friendly hint about registering sources.