Skip to content

fix(brainstorm/lsd): --save writes the advertised .md file, not just a DB page#1634

Closed
garrytan-agents wants to merge 3 commits into
garrytan:masterfrom
garrytan-agents:fix/lsd-brainstorm-save-to-disk
Closed

fix(brainstorm/lsd): --save writes the advertised .md file, not just a DB page#1634
garrytan-agents wants to merge 3 commits into
garrytan:masterfrom
garrytan-agents:fix/lsd-brainstorm-save-to-disk

Conversation

@garrytan-agents

Copy link
Copy Markdown
Contributor

The bug

gbrain lsd --save (and brainstorm --save) printed Saved to <slug> but no wiki/ideas/<slug>.md file ever appeared. The help text promises a file (Persist to wiki/ideas/<date>-lsd-<slug>.md), but the code only called engine.putPage() — a DB write. Two failure modes:

  1. Advertised file never written. Callers expecting a committable .md artifact (to push to the brain repo) got nothing on disk.
  2. Silent false success. The console.log("Saved to ...") fired unconditionally after the putPage try-block, so when putPage failed (observed under PgBouncer transaction-mode), it still claimed success. Verified: a real LSD run reported "saved" but gbrain get <slug> returns page_not_found — nothing landed in either sink.

The fix

Write to both sinks and report honestly:

  • DB page via putPage (unchanged — queryable via gbrain get).
  • File at sync.repo_path/<slug>.md when a local repo is configured (resolved the same way autopilot.ts / notability-eval.ts do), so the saved idea is a real committable artifact at the advertised path.
  • Honest messaging: the success line states exactly which sinks succeeded. If both fail, it prints an explicit NOT persisted error instead of a false success.

Test

  • bunx tsc --noEmit clean (no new errors).
  • Repro confirmed against prod: prior LSD run's slug absent from DB despite "saved" message.

Notes for reviewer

  • Only touches src/commands/brainstorm.ts (shared by brainstorm and lsd profiles).
  • No behavior change when sync.repo_path is unset beyond a clearer message (DB-only, as before).
  • Help-text wording ("Persist to ... .md") is now accurate for repos with sync.repo_path set.

root and others added 3 commits May 24, 2026 09:16
The judgeSignificance trimming (slice at 4000 chars) could split a
UTF-16 surrogate pair when an emoji sits exactly at the boundary,
producing a lone high surrogate that Anthropic's JSON parser rejects
with 'no low surrogate in string'.

Add safeSliceEnd() helper that backs up by one char when the cut lands
between a high and low surrogate. Apply to:
- judgeSignificance transcript trimming (the direct cause)
- findBoundary hard-split fallback (defense-in-depth)

Fixes: dream cycle SYNTH_PHASE_FAIL on 2026-05-24 caused by
🤖 emoji at pos 3999 in telegram/2026-05-20-topic-1-topic-1.md
…g>.md file, not just a DB page

The --save path called engine.putPage() (DB-only) while the help text and
success message both promised a 'wiki/ideas/<date>-lsd-<slug>.md' FILE that
was never written. Worse, 'Saved to ...' printed even when the DB putPage
silently failed (observed under PgBouncer transaction-mode), so callers
believed an idea was persisted when nothing landed in either sink.

Fix: write to BOTH sinks and report honestly.
- DB page via putPage (unchanged, queryable via 'gbrain get').
- File at sync.repo_path/<slug>.md when a local repo is configured, so the
  saved idea is a committable artifact matching the advertised path.
- Success message now states exactly which sinks succeeded; if BOTH fail it
  prints an explicit 'NOT persisted' error instead of a false success.

Resolves the 'gbrain lsd --save claims saved but writes nothing' bug.
@garrytan

Copy link
Copy Markdown
Owner

Superseded — loading this work into worktree branch garrytan/lsd-save-dual-sink to land from there.

The novel fix here is the brainstorm/lsd --save dual-sink change in src/commands/brainstorm.ts (DB page + advertised wiki/ideas/<slug>.md file, with honest per-sink success/failure messaging instead of the unconditional false "Saved to ..."). That carries forward.

The synthesize.ts surrogate-safe slicing commit (safeSliceEnd) is dropped as already superseded on master: the canonical safeSplitIndex helper (v0.41.13 / v0.42.0.0) already covers this and its docstring explicitly notes that safeSliceEnd re-introduces a case-3 bug it was written to fix.

Thanks @garrytan-agents — brainstorm.ts contribution preserved via Co-Authored-By on the landing PR.

@garrytan

Copy link
Copy Markdown
Owner

Superseded by #1655 (v0.41.30.0). The brainstorm/lsd --save dual-sink fix lands there, reworked to route through the canonical ingestion path (importFromContent({noEmbed}) + a shared atomic writePageThrough helper extracted from put_page) instead of raw putPage + a hand-rolled file write. The synthesize.ts safeSliceEnd change is dropped (already superseded by master's safeSplitIndex, v0.41.13). Co-Authored-By preserved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants