Skip to content

v1.96.0 - Trust and Responsiveness Hardening

Choose a tag to compare

@itechmeat itechmeat released this 30 Oct 08:48
285cb9a

Open Second Brain v1.96.0 - Trust and Responsiveness Hardening

Open Second Brain v1.96.0 makes the vault's seams state what they accept, and its stdio reads stop queueing behind each other. Third-party text could carry wikilinks, @osb markers and osb fence lines into capture pages and ingest summaries as live vault structure - the link graph, the marker scanners and the section parsers read it as the vault's own; now an optional neutralization gate escapes that markdown at the write seam, off by default as a deliberate operator choice, with a shadow mode that measures without writing and a read-only doctor audit naming the pages that already carry planted rows. The install answers for its own state: a fresh o2b brain init seeds a managed .gitignore block so derived state stays out of git, a doctor error names every path git already tracks, and the readiness probe fails a write-back contract installed into a file the operative host never reads. And read-classified MCP calls run up to four in flight while writes stay exclusive and arrival-ordered behind a dispatch-level gate.

Trust and Responsiveness Hardening

What ships

  • Write-time markdown neutralization at the third-party seams, gated off, shadow or enforce. With markdown_neutralize_mode (env OPEN_SECOND_BRAIN_MARKDOWN_NEUTRALIZE_MODE, default off), the two seams where third-party text lands - capture writes and untrusted-source ingest summaries - run the gate on caller text: enforce backslash-escapes the structure-bearing markdown (wikilinks, @osb inline markers, osb fence lines, ATX headings) before it is written, so no scanner treats it as the vault's own, and stamps a neutralized_markers frontmatter key naming the escaped families; shadow leaves every write byte-identical and lets the would-be families surface through the doctor audit; off, the default and a deliberate operator choice, runs no gate. The env twin wins over the config key, an invalid value is refused by name at the seam, and because capture identity hashes the persisted bytes, flipping the mode between captures of the same text yields an honest duplicate rather than a silent mutation.
  • A read-only doctor audit names the pages that already carry planted rows. The o2b brain doctor pass gains the fail-soft planted-structure-rows finding: it counts the live structure rows third-party text planted in capture pages, untrusted-stamped pages, quarantined entity pages and source summaries, names up to five paths and counts the rest, and stays silent on a vault with none. Under shadow, the finding appends a preview of what enforce would escape on the next capture or untrusted ingest of the same text. The audit is read-only by contract - the rows leave only by re-capturing the text with the gate in enforce or by a later repair pass - so the finding carries no o2b command.
  • o2b brain init seeds a managed .gitignore guard, and a doctor error names derived state git already tracks. A fresh init in a git repository writes a managed guard block over /.open-second-brain/ - the derived runtime state, bench runs included - beside the identity stamp, so a fresh vault no longer leaves brain.sqlite visible to git status. The seeder merges with existing content, never clobbers a conforming block, keeps CRLF endings, reports malformed markers as a named conflict, and --force never rewrites the guard. For existing vaults, the git-tracked-derived-state doctor check measures what git actually tracks with git ls-files - never inferred from status - and answers with an error naming the untrack command and the missing ignore line; the check never edits anything.
  • o2b doctor --readiness fails a shadowed instruction contract. A workspace where the file the operative host reads carries no managed write-back block while another candidate file carries it had the contract installed where it never runs. The readiness probe now grades that placement as a fail: per the host-to-file precedence, claude-code reads CLAUDE.md, codex, cursor, opencode and aider read AGENTS.md, and gemini-cli reads GEMINI.md; the finding names the host, the file the host reads, the file carrying the contract and the read-only recovery clause. Symlinked candidates keep their refused unknown treatment, and a workspace with no instruction file at all stays skipped - nothing installed is not a contract violation.
  • Parallel reads with exclusive writes on the stdio MCP transport. Every tool is classified read or write in the registry at registration - write-mode-dominant, decided per operation family, never from arguments at dispatch - and the classification is metadata only: it never reaches the tools/list wire payload, and a definition that arrives without one is treated as write, so it can only ever lose concurrency, never safety. Read-classified calls run concurrently, up to four in flight - a constant, backpressured at the cap - while write-classified calls run one at a time behind a dispatch-level FIFO gate and never beside a read: the loop reads no further line until a dispatched write has settled. Cross-request frame order is surrendered in one direction - responses may arrive out of arrival order, which is legal JSON-RPC; correlate by response id and progress by progressToken - while each request's own progress notifications all precede its response.
  • Digest and brief delivery surfaces honor the enforced owner scope. The digest's maintenance actions, the brief period rows and the digest's dream-parsed shift and contradiction rows were filtered by transport reach alone, so under integrity.owner_scope_delivery: fail a scoped caller could receive rows naming preferences the sections beside them had already withheld. Those rows are now kept through the same enforced ownership rule at every reach, a caller the enforced scope narrows takes no report snapshot and is shown no delta, and without the gate - or under warn - every output is byte-identical.

Guarded seams, an install that answers for its own state, and reads that no longer queue behind each other - every claim above traces to the 1.96.0 CHANGELOG entry and the merged PR #281.