Skip to content

Changelog

  • Connect exposes a copyable blop setup mcp <client> for every MCP table client, including OMP, in both its agent row and manual configuration section. Existing registrations are not forced or replaced by the displayed command.
  • Overview’s first-spans step uses blop setup agents, not an individual agent launcher.
  • Doctor’s setup check now reads the same installed hook receipts and enabled capture policies as the connected-agent list. It names the installed hooks and capture mode, while retaining unrelated framework setup diagnostics.
  • CLI and Connect share this check and the collector’s advertised policy path.
  • Overview and Connect select run commands only from application framework adapters. Agent-only projects use blop run -- npm run dev, never a coding agent launcher. Existing application framework commands remain unchanged.
  • Add memory add --kind --title --body with optional tags and an explicit ID, using the existing graph change writer and JSON envelope. Default IDs use SHA-256 of the exact title/body JSON tuple, so identical retries return the existing node without adding a revision.
  • Make Memory’s agent prompt and human command executable, and use search --text for the row’s copy-read action. Addressed detail reads still use memory get.
  • Add memory markdown init|attach|index|list|detach: bounded, explicit, model-free projection of local Markdown notes, heading sections and references. Source folders remain authoritative and read-only; failed scans, including detected root replacement or mid-scan edits, preserve the last complete snapshot with failure freshness. Unsupported administration flags fail before any source or database operation.
  • Reuse existing memory search/context/get/neighbors and read-only MCP with path/section/hash citations. Stable frontmatter IDs survive renames; deletion and detach remove current retrieval without altering authored memory history.
  • Keep projection references unapproved and reject authored mutations of projected IDs. Local reads distinguish assessment: not_configured. Resolve exact local trace references without reading or uploading trace bodies.
  • Preserve authored assertion and approval provenance when a projected endpoint disappears or derived rows are rebuilt; restore visibility when its ID returns.
  • Anchor Markdown initialization to Linux procfs directory handles. Unsupported platforms fail explicitly rather than reverting to race-prone pathname writes.
  • Correct .markdown ingestion, code-fence closers and heading links; preserve real inner inline links after escaped outer brackets and resolve encoded # and ? filename characters while rejecting raw queries.
  • Preserve exact 1029-character source IDs and 1537-character path/heading citations in graph reads, authored commits/proposals and publication previews, including their published CLI schemas, without truncating identifiers.
  • Add memory bind|binding|unbind for deliberately selected hosted read destinations. User configuration contains no credentials or repository edits; subdirectories and Git worktrees share the canonical repository identity.
  • Bound CLI/stdio MCP reads reuse the existing profile and managed operations with fresh workspace/project/grant checks. Hosted failures never fall back to local results. Explicit local CLI scope remains offline; Markdown administration and publication consent remain separate.
  • Add a shared schema-validated assessment boundary and explicit HTTP adapter, without a mandatory model, new agent tool or provider fallback.
  • Preserve read data while adding task/query-bound receipts, exact source revisions/hashes, graph/policy/assessor versions and honest partial coverage. Selected memory never claims to cover unseen working-tree files or diff.
  • Enforce configured assessment on hosted direct, managed, CLI/MCP and frozen chat snapshot reads. Timeout, invalid output, changed sources or revoked grants return no unassessed fallback. Authorization stays deterministic code.

Controlled Markdown publication and web receipts

Section titled “Controlled Markdown publication and web receipts”
  • Publish one explicitly selected indexed Markdown snapshot using the existing destination/payload preview, reviewed hash and hosted owner approval. No directory upload, source reread, synchronization, reference-edge transfer or projection authority. Hosted corrections remain separate explicit edits.
  • Preserve citation identity on no-op reindex so unchanged publication retries retain their exact receipt; changed indexed content invalidates the preview.
  • Show assessment status, findings, bounded coverage and exact source revisions in the web memory browser, including history. Query/detail failures clear stale detail rather than presenting it alongside a fail-closed error.
  • Resolve blop.external-link references against existing Linear, Jira and GitHub issue/PR link receipts, through the current owning project/team grant. Exact receipt IDs, optional recorded URLs and UTC capture timestamps are checked without loading provider bodies or returning denied source hints.
  • Refresh accessibility after ownership/deletion changes while retaining authored knowledge/history. Unsupported content hashes remain unknown; an available retained receipt is neither live provider freshness nor claim verification.
  • This does not add a general ticket/PR/CI ingestion feed or source cursor.
  • Frame stdio requests on LF rather than Node’s text-line separators, preserving U+2028 and U+2029 inside JSON strings on Node 24, split UTF-8 characters, CRLF, and the final request at EOF.
  • Keep the generated MCP client table synchronized with the README only. The generated docs CLI reference no longer has a hand-synchronized MCP block.

Inspector UI rebuilt on the design system (#664)

Section titled “Inspector UI rebuilt on the design system (#664)”
  • Every Inspector page is rebuilt on the design system and reads the real collector APIs, with in-place live updates on one shared event stream and no page reloads. Focus, selection, open panels and filters survive updates.
  • New guarded local writes: DELETE /api/runs (dry run first, running runs refuse) and POST /api/inspector/settings/limits. New reads: /api/inspector/overview, /api/inspector/memory, /api/inspector/cloud and /api/test-coverage/history.
  • Cover text runs through typed escaping; writes need same-origin JSON plus a marker header. The overview gains a “when failures happen” heatmap (#665).
  • Worker and metric CLI overview paths no longer send a bare ? separator when no filter is set (Node 24 request framing).
  • Redact credentials in log bodies from unregistered (plain OTLP) sources, as their attributes already were, and cap those bodies at 64 KiB. Rows stored before this change are not rewritten.
  • App-error issue titles lead with the recorded exception, e.g. TypeError: Cannot read properties of undefined (reading 'amount') in POST /api/checkout (HTTP 500).
  • Server spans without http.route are fingerprinted on the request path (url.path/http.target, ids normalized), so errors on different endpoints are separate issues. Such issues regroup once: new occurrences get a new id.
  • Hook sessions end: a measured end closes its start span, a turn_end closes the open turn when the host has no turn ids, and session_end closes whatever the session left open.
  • The Issues list wraps the “What happened” title (up to 3 lines) instead of cutting it at 28 characters, so issues that share a prefix are told apart.
  • blop doctor fails the port check when a non-Blop process holds the port.
  • Too many requests in flight answers 503 overloaded with Retry-After: 1 instead of capture_unavailable, and the connection ceiling is raised so a burst gets that 503 rather than a dropped socket.
  • Use the default 24-hour Logs range when the URL has no range, including history traversal, instead of restoring a remembered selection. Keep explicit URL ranges authoritative, consistent with Sessions and Issues.
  • Align the demo failure test with the current MAST policy: a downstream app failure alone establishes neither a mode nor a rule. Keep the classifier and the demo’s issue, span, and memory-read assertions unchanged.
  • Exercise the OpenCode plugin OTLP tool-span capture contract alongside AI SDK model calls and app spans in the blop run end-to-end fixture. Generic AI SDK spans alone are application telemetry, not coding-agent evidence for doctor stitching. Keep the strict stitching check and verify the plugin-to-app causal chain through MCP.
  • Native hook events queue durably before the bounded delivery-time identity probe. Offline, restarted, slow, redirected, old or different-store collectors do not produce host callback errors or output; mismatched identities receive no telemetry POST. Pending events drain when the bound collector answers.
  • blop agents status and doctor expose pending events, paused destinations and held-delivery reasons. Native integrity, input, outbox and enqueue failures remain loud and return non-zero.
  • Legacy blop agent hook delivery failures, including an exhausted budget after enqueue, are silent. Configuration and capture-loss diagnostics keep their existing exit behavior. Legacy queued rows without stable collector identity retain destination-only delivery; native legacy callbacks check the recorded process instance, but background replay cannot protect store identity.
  • Recorded argv also masks prefixed/camelCase credential flags and -u basic-auth values, without changing the launched process’s arguments or treating -p as a password flag. Init preflights a redirected .blop parent before any writes.

  • OpenCode resolves the collector before configuration writes, rolls back its edits when setup-state publication fails, and refuses switching config paths until the existing setup is removed. Pinned collectors use the version handshake and report registry ownership rather than being unconditionally external.

  • MCP client and marketplace deadlines terminate owned process groups, escalate after a bounded grace period, and settle even when descendants retain pipes. Verification-skill commands apply the same bounded teardown. Desktop installer locks retain owner identity and offer explicit stale-lock recovery instructions; a live installer is never automatically displaced.

  • Agent wiring snapshots only setup-owned files, not retained telemetry/outbox contents. Bulk MCP repair addresses every stale scope and preserves collector pins, including environment-based URLs. MCP results reject oversized fixed sections and disclose content/diff cuts made by replay previews.

  • Evaluation HTTP and CLI share the 128 KiB input limit and the same opaque-ID and actor contracts as storage. Interrupted/malformed mutation receipts retain unknown-outcome guidance. Manage-only queue authors and review-only completers no longer need unrelated read grants; assignment removal releases outstanding claims with revisioned audit, and next-item selection skips stale evidence.

  • Fresh runs replace inherited blop.run.id while preserving other user resource attributes. Usage reports enforce their upper time bound, cap group discovery and retain validated unscoped Codex counters. Worker raw commands preserve leading collector selectors and honor the final output format. Run usage errors preserve --report after environment and trigger flags.

  • Flow discovery traverses explicitly requested directories outside cwd and accepts ./-prefixed globs. Optional-loader errors distinguish absent packages from broken transitive imports/exports; repair guidance uses the CLI’s original installation context, including setup-doctor warnings.

  • OpenCode rollback/removal restores original bytes without a UTF-8 round trip. MCP conflict diagnostics disclose clipped-key collisions and exhausted node budgets; refused MCP rollback selects the drift recovery hint. Init destination refusals use structured invalid-config errors, failed alert sends include a next command, and recorded argv reserves the computed shell-quoted marker size.

  • Collector hostname aliases require the saved collector identity rather than equating IPv4/IPv6 origins blindly. Native rollback’s deletion-only exception rejects added duplicates of owned callbacks. Flow evidence rejects fields whose credential redaction expands beyond the byte contract instead of silently clipping an identifying signature.

  • Doctor normalizes IPv6 socket hosts and HTTPS default ports, shares strict active Codex exporter checks, and honors OpenCode’s active config override. Pi extension recipes are unverified/not-applicable rather than false failures. Monitor init respects preferred config precedence; status MCP and foreground-stop hints pin the resolved collector. Served OpenAPI3 schemas use nullable scalar types and declare alert-action path parameters.

  • Storage compaction checks free capacity on each SQLite volume independently. Resource retention uses indexed bounded age batches; concurrent legacy-log migrations recheck columns under the write lock. Span status filters include server 5xx failures and retain successful spans with unspecified kind.

  • Delete previews enforce the store-format gate on a read-only connection. Deletion and retention remove trace/conversation bookmarks only when their exact retained subject disappears, without resurrecting them on recapture.

  • Issue retractions repair surviving evidence timestamps/titles independently of regression state. Comparisons use one actually observed service/kind/operation cohort on both sides and include null-kind/status-less successes. Provider 429s retain an error causal chain without promoting ordinary app/tool 429s.

  • Service reports select distributed traces through failed spans in that service. Issue navigation preserves failure-class filters, and muting/fixing an issue removes its owned expanded fix-context preview.

  • Why applies project eligibility before limiting open issues and selects that project’s own occurrence, run and trace for shared fingerprints. Git authorship recognizes only final trailer paragraphs, not coauthor examples in body prose.

  • Automatic hook setup preflights native files before enabling capture. Late filesystem failures report retained paths, current consent and the disable command rather than imply rollback. Native removal resumes exact completed restoration steps after interruption while still refusing unrelated drift.

  • Hook and application consent writers share a cross-process lock. Inspector edits verify their expected revision under that lock and return conflict instead of overwriting newer capture restrictions.

  • Amp, Goose and Hermes project observers accept owned descendant directories while retaining the shared bridge’s nested/outside-repository refusal. Amp propagates public-text selection truncation. Hermes forwarding failures emit fixed content-free diagnostics without vetoing host callbacks.

  • Cursor compares complete owned handlers, including timeout, while preserving foreign entries. Missing installed modules are caught inside its callback boundary and still produce the neutral observer response.

  • Disabled hook bindings are excluded before the deliverable batch limit, so held rows cannot starve another binding at the same destination. Replacing a queued start atomically updates lifecycle and pending-end pairings, with new audited identities for changed ends and content-free replacement mappings.

  • Memory initialization applies a hook’s SQLite busy timeout before schema writes, not after a fifteen-second wait. OpenCode session-location lookups have a 500ms deadline; cleanup abandons pending lookups and late results cannot enqueue an event after capture stops.

  • Collector startup brackets IPv6 URLs, probes busy ports on their actual host, and filters registry reuse by an explicitly selected host. Foreground startup refuses an already healthy IPv6 collector rather than starting a duplicate.

  • Lost-run sweeps rotate through bounded pages of runs and launchers, so live entries cannot permanently hide later dead processes. Live events page run starts and completions independently in each cursor’s order.

  • Run, imported-session and app-trace live-event cursors use persistent insertion sequences instead of reusable SQLite rowids. Purging the newest or every row cannot hide recaptured evidence; upserts retain their original insertion order.

  • Bash, Zsh and Fish live completion honor collector flags on the command line. Subcommands offer their own flags and values without list-only parent flags. Bash file candidates preserve whitespace and literal glob characters.

  • Agent launchers refuse explicit collectors that conflict with saved capture bindings and fall back to an unchanged plain launch after wiring refusal. OpenCode native telemetry uses the same selected collector as hooks and MCP. Undo preserves pre-existing identical MCP entries; conflict and hosted-doctor diagnostics do not expose saved credentials or memory content.

  • Recorded commands mask credential aliases without hiding adjacent flag names. Copyable collector hints quote URLs for the shell. JSON metadata keeps authored dictionary keys, prompt versions preserve UTF-8 BOM bytes, config show --host accepts its advertised override, and pending prompts take the default on EOF.

  • Init refuses symlinked output files before writing. Collector prerelease versions follow SemVer ordering. Why retains an issue-free trace’s inspector link and escapes producer-controlled reasons; failure-context escapes all terminal fields and pins trace identity on span drill-down.

  • Memory publication preserves rule guards in the reviewed payload and hash. Replacement edits clear omitted optional content, pinned rules respect project applicability in inherited briefs, and approved purge remains possible after access to cited evidence is revoked. Read-log queries accept their 500-node cap.

  • Native hook identity checks and delivery share one one-second callback budget; slow or unavailable collectors leave events durably spooled before host deadlines. Project-only adapters retain actionable rollback-drift errors without probing unsupported global bindings.

  • Alert shutdown waits for active evaluations and delivery receipts before closing storage. A drain requested during a send includes newly queued transitions; paused-only rules still expire history, and failed alerts test --send exits nonzero while retaining its delivery diagnostic.

  • Metric previews select exact newest nanosecond points before limiting, totals have their own serialized-byte budget, and windows without a contributing delta interval remain unknown. Overview service edges use trace-wide app failure and exclude internal collector services.

  • Protobuf log event names reject invalid wire types. Captured content reports truncation from actual byte clipping, not a producer’s literal marker suffix.

  • Flow evidence projection redacts credentials from service names, operations and fallback error-log signatures before grouping or returning context.

  • The Python application session example batches span export off the asyncio event-loop thread, retaining explicit final flush and shutdown.

  • Sequential monitoring and hook test commands use Node’s native test timeout, removing the GNU timeout dependency on macOS. Vector-backend PR checks cover main and both development integration branches.

  • Run JSON/report output, stored argv and lifecycle command lines now use the same credential-redacted, bounded representation. Agent runs without content capture retain only argv0; split credential flags are masked without changing the child’s arguments. Fix-context repros and latest-run notes redact before collapsing control characters.
  • Metric capture classifies original attributes before redaction and omits nested content-bearing containers without consent, preserving typed metadata without promoting containers into session or worktree identifiers. Unscoped numeric token counters retain accounting validation instead of being mistaken for credential attributes.
  • MCP conflict descriptions mask camelCase credential fields and bound depth, nodes and output bytes. Failed recovery-snapshot writes preserve the original client failure and report that the previous entry could not be saved.
  • Alert history expires during steady-state evaluation as well as transitions. Pending events retain their selected destination, including locally recorded events promoted on connection; disconnect pauses queued sends. Slow hosted delivery no longer blocks evaluation. Agent-connection and native-hook rollbacks refuse later byte edits; invalid project configuration blocks collector startup.
  • Structural replay titles use registered agent labels only; unknown agent values cannot inject content or inherited object properties into hosted titles.

New commands

  • blop why [<run_|iss_|ses_|trace id> | --last] [--all-projects] explains one failure: what broke, the agent step and app span where it broke, the deterministic MAST mode (blop.mast/v1) and failure kind, and the memory the agent read in that session. It ends with the next command and an inspector link. A demo answer is marked as demo data and never hands its issue to a coding agent.
  • blop runs [--failed --since --limit --branch --all-projects] and blop runs show <id> [--timeline] list the runs of this repo and compare a run with the previous run of the same command.
  • blop demo [--clean [--yes]] records a passing and a failing demo run, an issue and a memory read, all tagged blop.demo=true, so blop why --last has an answer before anything is instrumented. --clean --yes removes only demo data.
  • blop claude, blop codex and blop opencode [-- args] start the agent with Blop capture wired: the first launch in a repo wires the hooks, the MCP entry and the capture binding (project scope), lists every file it changed and ends with the exact undo line. They fail open and return the agent’s own exit code. -p <n> and --url <url> before -- name the collector.
  • blop config show [--json] prints every setting with its value and source.
  • blop help all lists every command; root help shows the core ones.

Changed behaviour

  • Bare blop is now the status table plus one Next: line. It starts a stopped collector in the background, never prompts and no longer opens the browser. blop start is an alias of blop up.
  • blop status text uses the same table as bare blop. Its --json output only gains fields, and the envelope next now carries the next step.
  • Next: lines and hints carry the -p or --url you passed, so the suggested command asks the same collector.
  • Settings resolve in one order: flags, BLOP_* environment, project .blop/config.json (.blop/monitor.json is still read), user config, defaults. An invalid BLOP_* value is ignored with a warning that names it. blop init writes .blop/config.json and the gitignore lines .blop/* and !.blop/config.json, so the config can be committed.
  • Coding agents (CLAUDECODE, CODEX_SANDBOX, AI_AGENT, BLOP_AGENT=<name> and similar) get blop.cli/v1 JSON by default from runs, runs show, why, issues, issue and status. -o text and BLOP_AGENT=0 keep text.
  • blop doctor has a warning status for checks that do not fail the setup (for example a missing optional package).
  • blop run keeps the child’s exit code and summary through Ctrl-C, escalates SIGTERM and SIGHUP after a grace period, and prints a local summary when the collector never answers.

Store and collector

  • A newer or unrecoverable store exits 78 (do not retry). blop up --recover moves the store aside, never deletes it, and starts an empty one.
  • The size cap is enforced, oldest activity first, with recent traces protected. Status and health report busy retention passes and a WAL held by a reader. blop up --compact compacts a large legacy store on request.
  • The collector exits 70 when its capture worker is exhausted, and a managed one in that state is replaced.
  • runs record their argv and project root (additive, nullable columns).

Agent hooks and MCP

  • Native hooks spool to the outbox before contacting the collector, so a down or hung collector never loses an event. Hooks bind to a stable per-store collector identity, so a collector restart no longer stops capture. Bindings made before this change need blop agents setup <id> once.
  • A project binding accepts hooks from the repo root or any directory under it that no nested git repository owns.
  • New MCP tools list_runs, get_run, why and open_link mirror the CLI.
  • blop setup mcp <client> --remove on a JSON config gives back the exact bytes from before Blop’s add when nothing else changed since (or deletes the file Blop created); otherwise it takes out only Blop’s entry.
  • A project hook rollback blocked by global hooks installed later (blop setup agents) names the global removal to run first.
  • blop setup opencode --remove on an OpenCode config edited since puts back the user’s own experimental.openTelemetry value (such as false) instead of dropping the key. A setup record from an older Blop that did not record its edits now says the config was left as is, and what to take out by hand.
  • blop codex and blop setup mcp codex work with Codex 0.165, which prefixes “No MCP server named ‘blop’ found.” with Error: ; before, a fresh machine was told its Codex install was broken and nothing was wired. Checked against the real Codex 0.165.0 binary in a sandbox.
  • The first blop codex launch notes that Codex runs new hooks only after you trust them (/hooks in Codex); codex exec skips untrusted hooks silently.
  • A client that runs but refuses (such as a missing CODEX_HOME) is no longer called a moved or removed install; the hint says to fix what the client reports.
  • blop claude -p <port> <args> without -- notes that -p went to the agent and prints the -- form that names the collector.

Install

  • npm i -g @blopai/cli works: @blopai/test and @blopai/browser-harness are optional dependencies. blop test and flow checks without them exit 2 with an install hint.

Removed

  • blop verify (and its MCP tool, routes and columns): Blop has no trustworthy basis for saying a fix worked. Mark an issue fixed in the inspector.
  • blop connect and blop disconnect: the launchers wire on first launch, and blop agents setup, blop agents install-hooks and blop setup mcp do the pieces (each with --remove). Typing a removed command is the plain unknown-command error (exit 2).

Known limitations are listed in docs/cli-spec.md, section 11.

  • Add blop setup agents to detect installed coding agents, start or reuse a local collector, and install supported user-global hooks in one command.
  • Preserve existing modes, exclusions and foreign settings; support explicit --capture, --url, --port and per-agent JSON results. Repeated runs do not duplicate hooks; failures do not prevent other agents from being installed.
  • Keep native OTel recipes and MCP setup separate, and preserve host activation requirements and the distinction between installed hooks and live delivery.
  • Show capture enabled/disabled, mode and policy revision in blop agents status, including metadata-only policies whose content permissions do not change when disabled. Keep live delivery explicitly unverified.
  • Label native telemetry tiers as static capabilities in agent detection and status output, separate from the current hook setup. Status rereads state on every invocation; JSON contracts are unchanged.
  • Keep the current CLI and plugin shell while replaying the audit fixes. Share local-time date, duration and percentage formatting across current web pages; expose local collector Issues through the query catalog without mixing hosted test-failure counts.
  • Disclose taken sign-up emails in the restored password flow without linking retired password recovery. Refuse cross-workspace invitations, distinguish already-confirmed email links, and retain chat step labels and measured timing.
  • Keep permission-denied 403s on the current page. A valid session whose workspace membership ended goes to workspace setup instead of sign-in; current shell, workspace and billing reads use the same discriminator.
  • Hide unshipped per-account notification preferences; existing links continue to shipped workspace alert destinations. Preserve shipped Discord and export integrations and show paid-plan restrictions consistently.
  • Regenerate the triage last-run migration as 0074_flaky_sway, after the current alert-rule and agent-commit migrations, with a merged-schema snapshot.
  • Add the hosted Agent Map and session Graph views, blop map, blop session, and the read-only get_agent_map MCP tool alongside get_status and get_audit.
  • Preserve the collector’s session-tree, capture-policy and durable-metric reads; project the agent graph separately and stamp validated hook parent-link attributes.
  • Project accepted, policy-sanitized OTLP metrics into latest CPU, memory and host/instance uptime samples in the same transaction as durable metric points.
  • Keep the existing unknown-payload ingest API, precise metric history and protobuf error responses; malformed or disabled-source points never feed samples.
  • Shell:
    • The inspector follows the Local Inspector v3 design (docs/inspector-source/v3/).
    • Content sits in an inset rounded frame. The rail is 232px, and the current page uses the raise fill.
    • A 48px top bar shows This machine, the collector address and the page name.
    • Page titles are 20px. The header holds the page’s CLI equivalent and its range control.
    • CLI chips are checked against the CLI registry. Detail pages show none.
    • Phones keep the app bar and drawer. Tablets get the 64px icon rail.
  • Home:
    • A status strip: Needs attention, Capture, Agent.
    • Overview tiles joined in one strip.
    • One span activity chart with errors stacked in red. Its axes are HTML, so they stay readable at any width.
    • The rail’s Issues item counts open issues.
  • Pages:
    • Tables sit in cards with small uppercase headers. Tabs are pills.
    • Sessions gets a one-line summary. The throughput chart sits in a card.
    • Memory rows expand in place to Body, Connected to and Provenance, fetched on demand.
    • Issue rows lead with Fix context. It opens the exact text it copies, and Escape closes it.
    • The failure heatmap draws hits in red, with HTML axes.
    • Run detail reports Test result, Capture health and Runtime evidence separately.
    • Connect leads with endpoint, agent and skill cards. Every command is real.
    • Settings opens with what agents can do. The local MCP server only reads, so each write names where it happens.
    • Coverage’s empty state offers the address to publish to, and a Refresh button that reports what it found.
  • Responsive:
    • The observation graph uses one column on narrow screens.
    • Long branch names, commands and filter options shrink inside their controls.
    • Every page fits 320px with no sideways scroll (test/monitoring/inspector-v3-responsive.test.ts).
  • Keys: g m opens Memory, and g o opens Coverage.

Inspector: overview charts from the Blop App design

Section titled “Inspector: overview charts from the Blop App design”
  • Home: an Overview above span activity, on the same range. It has four tiles (traces, failure rate, p95 trace duration, model cost), each with its change against the previous period of equal length and a sparkline. It also shows trace outcomes as a donut and model cost by model.
    • When retention removed any of the previous period, its changes are unknown, never computed against a partial count.
    • Cost comes only from priced model-call receipts. Unpriced calls are listed as unpriced and kept out of totals and shares, never counted as zero.
  • Issues: failure classes over the last 7 days, and a day-by-hour heatmap of when failures happen (local time).
  • Runs: finished runs per day over 14 days, with failures stacked and the pass rate as a line.
  • Each read is one bounded read-only snapshot (newest 10,000 rows) with a visible truncated state. Each chart has an accessible summary and a data table with the same numbers, and is server-rendered SVG with no inline styles (the inspector’s CSP stays style-src 'self'). New fragments: /inspector/fragments/charts/{overview,issue-patterns,runs}.
  • The inspector now matches the Blop App v20 design (docs/inspector-source/): graphite surfaces (#161616 page, #141414 panels), #ededed text, one blue accent for the current item, selection, focus and chart data, and status colours for meaning only. Dark only (color-scheme: dark).
  • Inter for the interface and Geist Mono for code, both self-hosted from the collector (/inspector-fonts/inter-latin.woff2, inter-latin-ext.woff2); no CDN. scripts/vendor-geist.mjs now vendors Inter as well.
  • The rail, nav items, buttons and fields take v20’s proportions: 34px nav rows with 8px corners, the current page tinted blue, filled buttons in #2563eb so white labels hold 4.5:1, and smaller page titles (24px).
  • --pass, --warn and --idle, which Memory and Settings read but the theme never defined, are now defined, and their light fallbacks are gone.
  • A contrast test holds every text token at 4.5:1 and every status colour at 3:1 on each surface.

Inspector: memory traversal, provenance and session associations

Section titled “Inspector: memory traversal, provenance and session associations”
  • Traverse one, two or three hops with explicit hops and cursor URL fields, 200 nodes per page, previous/next navigation, and exact omitted-node/edge counts. Draw only stored edges whose endpoints belong to the selected scope and page.
  • Cite each drawn edge in its SVG title and readable relation list using the stored memory_edges primary-key tuple (from, type, to); no standalone edge ID exists. The drawing retains its 160-edge cap and reports omitted edges.
  • Resolve collector provenance once at startup: blop up --project <id> and blop monitor start --project <id> override BLOP_PROJECT_ID. Show the git origin and repository root without inventing a mapping to authored project IDs; unresolved identity remains labelled unresolved with all-local scope. Project selection, including an explicit all-local selection, overrides the default. Refuse reuse when a requested project differs from the running collector.
  • Omit git origins that cannot be parsed rather than exposing raw credentials in collector health or inspector provenance.
  • Preserve the running collector’s startup project during automatic version upgrades, including all-local scope, instead of inheriting the invoking command’s environment. Keep an explicit restart project authoritative; leave collectors running with a version warning when their scope or identity cannot be verified safely.
  • Show separate curated-memory/recorded-evidence session and trace associations from exact saved source identities, reusing local accessibility resolution. Associations neither merge records nor prove session use or causality; the evidence graph has no incoming memory-reference relation.

Memory: shared libSQL and PostgreSQL vector backends

Section titled “Memory: shared libSQL and PostgreSQL vector backends”
  • Export a SQL-free VectorBackend contract with structured scopes, revisioned writes, cosine rows, indexing coverage and bounded cursor pagination.
  • Preserve local DiskANN/exact scoped retrieval, native warning strings and synchronous write-transaction isolation; keep vector SQL in backend modules for the memory store and runtime-evidence adapter.
  • Add an optional dynamically loaded pg adapter with pgvector vector(384), HNSW/IVFFlat cosine indexing, scope-before-ranking and pinned model guards. No driver dependency or hosted graph migration is imposed on local users.
  • Exercise identical backend assertions against temporary libSQL and real PostgreSQL, with explicit skips when no PostgreSQL URL is configured.
  • Leave inspector views unchanged under their ownership restriction; their legacy vector SQL/interface migration remains blocked on permission to edit those modules. Backend guarantees and boundary: docs/vector-backends.md.
Section titled “Inspector: Settings command actions, deep links and truthful states”
  • Give overview commands native keyboard-accessible Copy controls through the shared page-action handler, with polite success/failure announcements and visible commands when scripting is unavailable. Redacted API-key values have no copy control; configured MCP argv is never exposed as arbitrary copy text.
  • Serve sticky section navigation and native ?view=settings#connected, #agents, #memory, #evidence and #ask anchors before scripts run. Preserve namespaced overview IDs and anchors across capture-policy swaps; restore detailed-section fragments after asynchronous rendering and preserve the selected project when following section links.
  • Distinguish missing evidence from unreadable stores and present memory from an unbuilt semantic index. Scope capture freshness to the explicitly selected project’s identity-resolved hooks, not binary detection or another project’s activity. Read at most the newest 1,000 collector observations within seven days through the timestamp index before parsing metadata; label missing sampled capture and excluded older activity explicitly. Unavailable metadata and unselected projects stay unknown.
  • Preserve validated credential-free collector URL/port pins in stale MCP repair commands; withhold unsafe or ambiguous pinned repairs.

Inspector: read-only, scope-truthful Memory view

Section titled “Inspector: read-only, scope-truthful Memory view”
  • Enforce native read-only graph and evidence handles with SQLite URI mode=ro; semantic reads preserve schema and vectors from obsolete models.
  • Compute semantic coverage from active, index-eligible nodes in the selected project and current model/revision, without letting retired or foreign nodes block recall. Apply kind/status filters before the 100-hit semantic bound.
  • Keep meaning controls and canonical detail/revision/semantic URLs synchronized across fragments. List reads return metadata only, bounded to 200 rows.
  • Omit unreadable node records with scoped corruption counts. Resolve exact evidence identities locally; missing or unreadable evidence never inherits a saved positive accessibility label or an unconfirmed link.
  • Measure omitted relations, revisions, graph nodes and graph edges separately. Show immutable addressed content, source/relation provenance, revision actors, and revision-pinned CLI commands with Unicode body-section continuation.

Universal agent hooks: selectable global or project capture

Section titled “Universal agent hooks: selectable global or project capture”
  • Extend native global/project hooks to all 11 registered adapters: Claude Code, OMP, Pi, OpenCode, Hermes, Gemini CLI, Codex, Goose, Amp, Cursor CLI and Crush. Setup, install-hooks, status, doctor, capture-policy, run and env use selectable scopes. Without --project, scope defaults to global; --project <local-id> implies project scope. Explicit project requires a project; global rejects one.
  • Use public native hook/plugin contracts without exact host-version allowlists. Agent info/list JSON exposes native, global and version-independent hook capabilities with refusal reasons. Unknown or incompatible callback formats still fail closed; implemented does not mean every release/platform is certified.
  • Capture global callbacks under one explicit global source/project label. Exact-physical-cwd project-native installations take precedence even when disabled; matching drift fails closed without global fallback. Preserve collector identity, bounded/redacted local delivery, outbox and policy controls, including existing metadata-only reductions and exclusions. New bindings default to full supported exposed content with 30-day body retention, never hidden thinking or attachment bytes.
  • Keep observer integrations non-intercepting: Cursor/Amp omit pre-tool and permission interception; Goose’s PreToolUseResult observer cannot change approvals; Crush exposes top-level PreToolUse only. Unexposed callback content remains unavailable rather than being reconstructed from private history.
  • Preserve foreign host settings/plugins and preview/apply, atomic writes and hash-drift-safe removal. Native-only launchers have no fabricated artifacts or fallback: run requires real native installation. Version-2 receipts explicitly mark each file’s host-config role; version-1 receipts remain safely removable. Adapter seams accept config-path/context information for multi-file native formats. Idempotent apply correctly reports no changes.
  • Resolve builtinAdapters through lazy getters to break the real shared-renderer/ registry import cycle, while retaining extensible registry lookup.
  • Observed gates: package build passed; a plain OMP launch delivered 14 global events including real tool/reply activity. Pi delivered 9 lifecycle/auth-failure events and OpenCode delivered 5 prompt/context/model-error events before provider 401 failures. Gemini delivered no callbacks because auth/client and workspace-trust gates blocked it. Codex’s model run succeeded but its hook source/session query returned no events; native /hooks trust review remains required, with no trust bypass written. Hermes, Goose, Amp, Cursor and Crush were unavailable locally; source-grounded callback/bridge fixtures are not live host/model delivery. No aggregate test-count or blanket certification is claimed.
  • Retain prior Claude Code 2.1.310 evidence: six main-cycle callbacks from global and bound-project launches without competing-scope duplicates, with prompt, public reply and tool input/output. Subagents, compaction and errors were not exercised; this does not qualify the separate native-plugin mechanism.

Inspector integration: durable metric-only sessions

Section titled “Inspector integration: durable metric-only sessions”
  • Keep metric-only sessions marked Unknown in server-rendered htmx rows as well as client-rendered rows. Their exact source/session links expose recorded metric totals separately from spans; marking a row wrong cannot fabricate a trace-backed issue.
  • Retention preserves both metric pruning and consent-bound log/native-span body expiry.
  • Forward request headers to the capture child before body bytes arrive, so route-specific upload limits return 413 immediately instead of a transport timeout when an oversized client sends only its declared Content-Length.

Inspector: chart ranges and reachable empty states

Section titled “Inspector: chart ranges and reachable empty states”
  • Home’s span-rate, error-rate and p95 charts follow one URL-backed range selector, including reload and Back/Forward. Home and Issues chart fragments accept the shared presets from 5m through 30d and all (retained data, up to 30 days), while preserving explicit from/to windows.
  • Home and Issues leave an absent range implicit: Home defaults to the last 24 hours on both the page and chart fragment; Issues defaults to all retained data (up to 30 days). Neither rewrites the URL or borrows a remembered selection. Explicit changes push history; Back restores the parameter-less default window. Sessions and Logs likewise add no default range on mount.
  • Empty Home windows identify older retained spans and offer a one-click 30-day range. Empty retained ranges, expired buckets and capped samples remain separate states.
  • Issue sparklines aggregate occurrences over the same selected window as their list, rather than silently showing a fixed 24 hours. Charts retain bounded grids, conditional ETag refresh and activity-driven htmx updates; Sessions and Logs retain their existing explicit range-change behavior.

Inspector: a Resource view in the step detail

Section titled “Inspector: a Resource view in the step detail”
  • The selected step’s span data is a visible Attributes / Events / Resource tablist instead of a collapsed “Advanced span attributes” block. The view is in the URL (panel=events|resource), so a reload returns to it and Back/Forward step through view changes.
  • Resource groups the span’s resource by OpenTelemetry namespace (Service, Telemetry SDK, Process, Host, Container, Deployment, Cloud, Other), with counts, mono values, a copy control per row and “Copy all as JSON” of the bounded set the collector returned. A search filters the loaded set client-side (“Showing N of M”); it never reads again or changes the URL.
  • It tells the absences apart: an exporter that sent no resource, a span that is no longer retained, and a metadata-only agent hook source whose resource is only Blop’s source stamp. /api/inspector/span adds resourceTotal and resourceSource; the 60-entry and 2,000-character caps are unchanged.
  • Closing the shortcuts sheet no longer takes focus back from a field focused before its queued close event, which could send g i typed there to Issues.

Inspector: reactive lists and a light, denser look

Section titled “Inspector: reactive lists and a light, denser look”
  • Add a small dependency-free reactive layer (/inspector-reactive.js): a state cell, a resource controller with scope generations, one live-feed owner per document, keyed DOM patching and disposable mounts. Sessions, Logs, Runs and the Settings capture-policy editor use it. A filter change aborts older reads, so a slower reply for the previous scope never paints; a failed new scope drops old rows instead of showing them as matches; kept rows keep their node, focus and scroll position across live refreshes.
  • Logs refresh live behind the shared Pause / “N new” control and offer Maple’s time-range presets inside the 24-hour log bound (5m, 15m, 30m, 1h, 6h, 12h, 24h; 7d and 30d are listed as unavailable). The log sheet is a right-hand drawer.
  • The capture-policy editor keeps draft, accepted policy and write outcome apart: a 409 or an unacknowledged save locks saving until “Read accepted policy” reads the current revision; repeated submits write once.
  • The inspector now uses light surfaces with hairline borders, tabular numbers and dot-and-word indicators; every colour is a theme token.
  • Move hook implementations into src/hooks/: a single HookAdapter registry owns host formats and launch conventions; shared engines retain binding, outbox, install/rollback and capture behavior. Existing module exports remain intact. Add a public adapter-authoring guide with the folder-plus-registry rule and verified-host acceptance loop.
  • Add blop agents install-hooks <id> --project <local-id> for persistent OMP user plugins and Claude Code user-settings command hooks. Preview exact diffs by default; --apply writes atomically and --remove --apply restores hash-checked pre-install bytes. Preserve foreign config and refuse later drift.
  • Native hooks resolve exact project bindings/policies on disk without launcher environment, reject stale collector instances before enqueue, and report native configuration separately from delivery in agents status. Project launch remains optional and does not register duplicate hooks. OpenCode and Codex native installers remain deliberately deferred pending verified contracts.
  • Local agent content capture is on by default for a newly enabled project binding: native harness spans now honour the binding’s consent, so prompts, public replies and tool input/output/errors are retained locally, bounded and redacted. blop agents env exports OMP’s verified OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT value per mode.
  • The inspector shows its “content not included” notice only when a step genuinely has no retained content.
  • Body and metadata retention default to 720 hours (30 days). Per-binding body retention uses blop agents capture-policy set --retention-hours (1–720); store retention uses BLOP_MONITOR_RETENTION_HOURS after collector restart. Expired bodies become tombstones, and the replay horizon follows maximum retention.
  • Settings now edits each existing harness/project binding’s mode, body retention and class exclusions through the CLI’s shared atomic policy writer. Accepted values and revisions update only on success; invalid values, stale revisions and server errors cannot appear as saved. Changes apply to future events and pending delivery, not retained history. Store retention remains explicitly restart-only, not hot-reloadable.

Unreleased (CLI UX overhaul, branch feat/blop-cli-v01)

Section titled “Unreleased (CLI UX overhaul, branch feat/blop-cli-v01)”

The JSON contract is blop.cli/v1. Its JSON Schemas ship in this package under schema/ and print with blop schema. Within v1, fields are only added. Most changes below touch output that 1.7.0 did not have yet (it always emitted warnings: [], and run, tail, workers and setup had no envelope), so the practical break for 1.7.0 users is small. Each change is listed so scripts can be checked.

  • Reuse the local hook binding as native span content consent. New bindings default to full/720-hour bodies; absent, mismatched, disabled and narrower bindings remain metadata-only on the native path.
  • OMP project agents env and agents run select its documented full/summary/none emission mode and export the exact source/installation/project/adapter identity. No new content variables are added to other adapters.
  • Keep credential redaction and the existing attribute/event byte limits. Native public message structures exclude hidden reasoning, environment dumps and attachment/file fields. Native body expiry removes projection/index/raw copies without changing metadata retention; readers refuse expired bodies.
  • Show bounded native content in session/trace step details. Agent-context summaries distinguish retained content from launcher/metadata-only steps; captured text remains inert and is not expanded into the copied summary.
  • Add blop failure-context --source KEY --trace ID --since 15m --json and GET /api/failure-context, using one source-scoped read snapshot and the blop.failure-context/v1 data schema (blop schema failure-context).
  • Return observed span/log symptoms, deterministic ranks with reasons, exact source/collector/trace/span/log identities, missing parents, capture coverage and pinned exact drill-down queries. Service/session/recorded-attempt selectors intersect; source/owner identity prevents reused-ID leakage.
  • Enforce server-side window/row/byte caps and a terminating worker deadline, with two readers maximum. Preserve disabled history, empty/truncated/unknown sources, unavailable stores and stale-revision conflicts as distinct states.
  • Keep reads metadata-only, with unknown verification and no inferred agent links, model diagnosis, hosted-run join, MCP change or new raw store. Offline --db never starts or contacts a collector.
  • Qualify real Node /ok, /fail, unrelated failure and recovery exports through built CLI, curl and generic openapi-client-axios 7.9.1 drill-down. Extend the local-monitoring skill and OpenAPI only for this contract.

Unified evidence-launched browser checks (#490)

Section titled “Unified evidence-launched browser checks (#490)”
  • Add blop test init|add|list|run|watch and blop flows (including ls). Keep legacy top-level/spec aliases and the older flow group; run -- <cmd> remains the observability wrapper.
  • Resolve flows run --from trace <id>|--from finding <code> read-only from local evidence, with bounded windows/rows/bytes. Missing, stale or over-cap evidence exits 2 before spec loading. Recorded context never chooses a target.
  • P00 qualification (2026-10-24, Linux x64, Node 22.23.3): clean packed consumers use public SDK revision 691292c78cf737ec6863abd1c65750f61ba31e04, not a workspace patch; real Chromium trace/finding launches exported SDK-owned blop.evidence.* attributes matching JSON, while plain runs stayed unstamped. Provenance is not causality or independent verification; this is not release/platform certification.
  • Divergence from older CLI plans: test is now the browser-check group, not a future issue-to-generated-test command. add scaffolds a reviewed spec only.
  • Add blop setup doctor [--json] for the whole local loop. One data.checks array reports pass/fail/not-applicable, reasons and exact remediation commands. No auto-repair; exit 0 with no failures, otherwise 1.
  • Check collector/status health, local store permissions/retention/retained amount, pinned Chromium, harness/SDK resolution, Node >=22, agent recipes, Git and binding. Never write telemetry/config/state, launch agents/browsers, start a collector or contact external hosts. Keep stale registry records untouched.
  • Identical facts serialize identically: the envelope’s generated_at uses an explicit fixed epoch sentinel, not an audit timestamp. Publish setup-doctor schema and teach help/quickstarts/the local-monitoring skill to audit first.
  • Keep blop doctor unchanged: it remains an active OTLP round-trip diagnostic. SDK semver is checked, not Git revision integrity; unrecognized recipe shapes remain failures, not inferred success. Non-loopback acknowledgement never enables external probes.
  • Keep SDK execution off CLI bootstrap so a missing SDK is a doctor finding, not an import-time crash. Browser flag values are checked exhaustively against the SDK public type. Hook checks inspect supported event entries, not arbitrary strings/comments; per-signal destinations/protocols override generic settings.
  • Add blop report --since 2h --format markdown|junit|json, with exact service, session, or stored-finding scopes. Read one local query-only snapshot; never discover/start a collector, run analysis, contact the network, or upload.
  • Include the source database/revision, explicit half-open window, bounded service/error/log summaries, stored findings, SDK flow outcomes, exact evidence IDs and copyable reproduction/drill-down commands. Keep unknown/unverified/ verified receipt state separate from execution outcome.
  • Bound source rows, metadata fields and rendered UTF-8 bytes with explicit truncation. JUnit retains unknown evidence as skipped, not successful checks, and is exercised through the ingest parser.
  • Add --until for byte-identical rendering of an unchanged evidence snapshot; report JSON uses the pinned window end as generated_at. Publish the report data schema through blop schema report. Sharing remains a separate decision.

Scoped rich hook capture (unreleased working implementation)

Section titled “Scoped rich hook capture (unreleased working implementation)”
  • Add strict blop.agent.hook/v3 without widening retained v1/v2. Explicit project setup defaults to full supported public content after notice; preserve existing reductions. Conversation-only, metadata-only and class exclusions filter before producer IPC and again before collector persistence.
  • Add owned agents setup/run --project artifacts for OMP18.11.3 and Claude Code2.1.300, safe removal and capture-policy show/set. Refuse binary/version, collector-binding, symlink and artifact drift. Do not edit OMP settings or silently restart a collector. Configuration is not callback/delivery proof.
  • Capture public prompt/assistant/tool input/output/error fields through the shared durable outbox and exact receipt path. Store bodies once, reference them from metadata, retain the original expiry clock and remove expired content indexes. Queued restrictions produce auditable replacement identities.
  • Enforce body expiry in exact/token/phrase searches before the physical retention sweep, including indexed coverage. Distinguish malformed body errors, a missing retained copy and known expiry without failing the whole observation page. Bound physical body/index cleanup while retaining observation metadata.
  • Open coding-agent sessions on their recorded conversation unless a tab or step link was selected. Preserve public-message availability reasons and show unknown duration rather than inventing a running state. Detail identity now uses the shared resolved activity identity, not a service-name fallback.
  • Scoped agents status --project checks owned artifacts, binary/version and selected collector identity without repair or restart. Show each class’s policy permission separately from unverified live acceptance. Preserve bounded run/git metadata when suppressing unconsented native harness bodies.
  • Policy changes preserve exclusions unless an explicit replacement or --clear-exclusions is requested. Add scoped enable/disable and original-time retention updates without requiring a mode change. Use canonical strict flag parsing with repeated exclusions and last-value precedence for scalar flags.
  • Bind observation pagination to its exact source/session, evidence revision and earliest retained-body expiry. Changed/expired snapshots return409 and offer an explicit first-page refresh instead of mixing versions or retrying a stale cursor. Historical cursor layouts are rejected rather than silently upgraded.
  • Keep literal OMP identity independent from historical opencode service naming. Retain exact same-call and recorded-membership graph associations separately from recorded causal parents. Show actual bodies and explicit tool outcomes in the existing bounded inspector.
  • Claude uses observer-only in-process native mods with the shared sanitizer, no transcript scraping. Serialize awaited bridge writes across concurrent callbacks; retain fixed content-free failure diagnostics. Organization policy can withhold system/compaction callbacks, and is never bypassed.
  • Extend the same OpenCode plugin and JSONC editor for scoped2.0.21 setup/run/ removal. Own a directory reference, preserve other config entries/comments, and retain the config document on undo. Pin actual and logical launch cwd. Shared selection excludes history/provider state; retain public system text and exposed compaction summary only. Native event replay uses a stable source-scoped wire identity and the original native clock.
  • Classify an exposed nonzero shell exit as failure even when the SDK says execution completed. Correlation failure diagnostics no longer echo exception messages. Fixture behavior and actual one-prompt inspector readback passed; OpenCode’s full model/tool/lifecycle cycle is not qualified, nor is V1.
  • Main-cycle live receipts cover OMP/Sol and Claude’s configured default model. Other-host, subagent/compaction/fallback, capacity and publication gates remain separate; no all-host or full-plan certification is implied.
  • Emit strict blop.agent.hook/v2 metadata on the existing subprocess → OTLP → local observation path. Mint a UUID before first delivery; isolate source, installation, adapter, session and call identities. Retain each callback as an immutable event observation, with a scoped call key rather than overwriting terminal facts. Retained v1 stays readable without v2 receipt claims.
  • Keep Stop/agent_end as turn completion, actual shutdown as session end, and compaction phases distinct. Preserve unknown outcome, missing/conflicting aliases, expired/missing starts and measured-zero duration explicitly.
  • Sanitize before local bookkeeping/send and again before evidence persistence; omit payload content, paths, claimed machine/worker authority and raw diagnostics. Reuse existing source-filtered observation/graph queries; no inferred causal parents, authored memory, publication or new graph authority.
  • Replace pairing-only files with bounded, private hook-outbox.sqlite: pair and enqueue sanitized metadata in one durable transaction before network delivery. Add exact committed/replayed event-ID/hash/revision receipts in the evidence writer transaction, all-or-nothing hash conflicts and bounded replay after offline restart, sender/drainer crashes or lost responses.
  • Enforce count/byte/age/disk/batch bounds, one drain lease and collector-owned timer, credential-revision auth pause, opt-out for capture and replay, explicit expiry/refusal/quarantine losses and safe CLI queue/receipt status. Process exit or ordinary HTTP 200 is not delivery; capture completeness remains unknown.
  • Preserve exact receipts through the existing authenticated TLS receiver. Meter actual rollback-journal footprint, including expiry and counter transactions; avoid dirtying the outbox on empty collector polls.
  • Print explicit OMP/Pi metadata extensions with agents hook-config; add Pi registry metadata. Reuse the common bridge/outbox, suppress foreign locations and disabled capture, and leave tools to configured native telemetry.
  • Bound synchronous bridge calls to avoid OMP’s detached turn-end/shutdown race. Qualify OMP18.11.3 real read/edit, success/failure, shutdown, opt-out and offline replay, native-overlap tool ownership and abrupt-exit unknowns; Codex/Pi model/auth blockers and untested compaction remain explicit. H3 stays partial; H4 associations and full H5 are not implied.
  • Add blop evaluation grant|revoke|call and the existing collector owner’s /api/observations/evaluation/* HTTP actions. Local grants bind one source, principal and permission set, expire within 24 hours, are checked fresh and keep bearer credentials in private files and trusted backends, not browsers.
  • Store typed numeric/categorical/boolean/text/correction scores, immutable config revisions, per-score comments/history and grant-bound mutation audit separately from recorded evidence. Enforce scoped config/subject checks, explicit expected revisions and canonical idempotent replay. Corrections preserve original output.
  • Add revision-safe annotation queues, eligible human assignments, atomic claims, required-score completion, bounded next/list and per-member bulk outcomes. Retain author/reviewer/evaluator provenance and immutable source references after source removal; absence does not invent an expiry/deletion cause.
  • Keep P3 partial: collaborative comment threads/anchors, mentions/reactions/ preferences, hosted operation contributions and selected-result memory curation remain unimplemented. No hosted review UI, local MCP writes, telemetry upload or complete P3/release claim.
  • Export browser-safe @blopai/cli/monitoring/contracts for exact local/hosted source-scoped subjects, worker-attempt references, provenance, content-state and byte-bounded query/cursor validation. Parsing never grants source access or enables content capture, publication or evaluator execution.
  • Keep opaque Unicode session IDs distinct from imported coding sessions and service-scoped agent conversations. Reject control characters, malformed Unicode, ambiguous identity and foreign source/machine bindings.
  • Normalize ten observation types, source-scoped opaque conversation IDs, requested/observed models, environment/release/version, user/tags and bounded typed metadata in the ingestion transaction. Preserve unknown and conflicting dimensions; historical spans require explicit replay to acquire projections.
  • Add source-preserving application session list/detail, role-labeled replay, parallel tool association, sparse durable bookmarks and bounded continuation. Keep coding-agent, hook, worker, run and request investigation paths distinct.
  • Add explicit --capture-gen-ai-content consent independently of legacy custom attribute capture. Persist new application payloads only in local normalized observations; omit them from legacy raw span/search and hosted structural proxies. Default capture, hook payloads and unclassified status text remain metadata-only. Report ingestion metadata clipping separately from previews.
  • Bound replay pages to 50 observations/256 KiB, field previews to 4,000 UTF-8 bytes and explicit single-observation full reads to a separate 1 MiB ceiling. Enforce exact source/service/session/trace/span ownership on those reads.
  • Bound pending HTTP intake and writer requests to eight with visible overload rejection. Cap hook delivery at one second and keep partial tool duration unknown rather than assigning a measured zero.
  • Add runnable standard OTel TypeScript/Python session recipes with async/manual context, parallel tools, W3C client/server extraction, masking and flush/shutdown. Actual isolated runs verified three traces/15 spans per language and capture mode; these controlled producers are not external-agent/provider certification.
  • Keep session bookmark/source controls and bounded-content guidance inside the viewport at tablet widths as well as on phones; wrap the action group instead of clipping controls or hiding provenance.
  • Read application-session model fields in the bounded observation scan without a second projection lookup per observation; preserve snapshot and source scoping.
  • Make capacity investigations reproducible with a separate 10k reduced fixture, raw proc mappings and database inode identities, and per-isolate V8 heap-space statistics. Reduced runs cannot pass full-envelope gates. The round-4 summary index candidate failed full-envelope latency targets and was withdrawn; native allocator retention and the unchanged query/RSS capacity gates remain open.
  • Record the round-5 allocator/transactional-summary experiment: exact summary compatibility and reduced query/ingestion improvements, but 344.164/346.383 MiB natural-idle peaks failed the prerequisite for a full run. Both candidates were withdrawn at that checkpoint; no allocator policy or native addon ships. The separate round-6 capture-process qualification is recorded below.
  • Keep the OTLP/query HTTP listener in a database-free parent; normalize, persist, retain and query the same local store in a listener-free capture child. Preserve JSON/protobuf/gzip, source/consent boundaries, parent collector identity, SSE and blop.cli/v1 across bounded, backpressured fork IPC.
  • Fail child outages honestly with capture_unavailable for intake/writes and query_unavailable for reads. Never replay an interrupted mutation. Bound automatic recovery to two restarts and terminate the child with the collector.
  • Record parent and child RSS separately. The sanctioned parent RSS gate does not mean total capture memory disappeared; unchanged targets and retention remain authoritative in the capacity plan.
  • Record round 6’s full 100k envelope: ingestion/query p95 pass at 356.756/164.489ms, but parent natural loaded-idle peak 151.023 MiB fails strict <150 MiB. Disclose capture child peak 358.516 MiB; retain the architecture and stop without a rerun, waiver, IPC tuning or summary-rollup reapplication.
  • Reuse a parent-owned, bounded HTTP forwarding connection pool instead of constructing and closing a virtual socket for every request. Keep the 128 connection ceiling, 64 KiB frames, backpressure, deadlines and no-replay outage behavior unchanged; destroy the pool when the parent stops.
  • Close the parent capacity gate in round 7’s single authorized full rerun: natural loaded-idle peak 141.887 MiB, ingestion/query p95 313.222/141.847ms, all three capacity gates PASS. Disclose separate capture child peak 327.324 MiB and parent overall peak 151.547 MiB. At that checkpoint, summary qualification was blocked by missing archives; round 8 resolves it below.
  • Maintain exact writer-owned application-session summaries with intake, retention and lost-launcher updates. Read at most 201 indexed aggregate rows globally; preserve the 3,000-observation fold, ties, model/source precedence, partial flags and independent earliest-window detail/replay behavior. Historical WAL snapshots remain read-only and retain their original pre-migration view.
  • Rebuild the rollup from the recorded design after temporary source loss and qualify it with fresh all-3,001-row differential proof and one full 100k A+B run: ingestion/query p95 399.192/92.089ms, parent natural loaded-idle peak 138.523 MiB, all three capacity gates and 15 correctness probes PASS. Disclose separate child sampled peak 354.367 MiB and the higher full ingestion tail versus round 7; this is not a total-machine memory or release claim.
  • Add source-bound typed filters, exact bounded facets and token/phrase/full-field content search over already masked, consented observations. API, inspector URL, saved views and JSON page export use the same validated query interpretation; missing, null and empty values remain distinct. Historical, truncated and unsupported metadata/index coverage is explicit; reads never backfill content.
  • Persist mutually exclusive usage buckets and immutable exact-decimal cost receipts. Recorded cost, including zero, takes precedence; invalid or missing usage/currency is unavailable, not zero. Append source/model price revisions with effective dates and input-token tiers without repricing earlier receipts.
  • Add scoped application-end-user summaries and expanded/grouped execution graphs with exact recorded-parent edges, repeated-call identity, cycle/missing- parent disclosures, bounded responses and an accessible evidence list.
  • Add a Sessions → Observations inspector view and a workspace-admitted, read-only hosted telemetry view. Price and saved-view writes stay same-origin local operations; these additions do not enable remote localhost access, publication, arbitrary SQL, tokenization/model downloads or provider calls.
  • Adapt selected non-enterprise Langfuse T04/T05 behavioral cases with per-case provenance and controlled-fault receipts. This is not full upstream parity or a performance/release certification; P1 capacity gates remain open.
  • Export @blopai/cli/graph: shared native libSQL access, the existing pinned local embedding model and vector ranking, plus revisioned authored memory with source/proposer/approver attribution. Keep the monitoring evidence adapter and its wire schemas separate.
  • Apply identity/project grants before retrieval, counts and ranking. Preserve explicit rule lookup, conflicts and approved supersession independently of semantic similarity; similarity creates no evidence edges.
  • Require exact target/policy revisions and action-bound approval for consequential knowledge changes. Reject ambiguous patches and brief overflow atomically; retain revision history, explicit retire/restore and content-free purge receipts.
  • Persist applied graph writes and explicit index receipts in the same transaction as revisions/vectors. Exact index replay and restart recovery do not invoke the model again. Exercise native checkpointed VACUUM INTO backup/restore for content, history, vectors and action receipts; the driver’s declared backup()/serialize() APIs are unimplemented.
  • Reject chat continuation through another member’s conversation or thread ID before saving messages or granting tools. Reject an explicit inaccessible project instead of silently anchoring the chat elsewhere. A disposable Postgres smoke reproduced the prior foreign-thread resolution and confirmed the ownership rejection.
  • Keep existing mixed-case operation IDs stable while deriving bounded, collision-checked MCP labels. Authorize native run, evidence and historical artifact reads through the same management descriptors without changing their browser query normalization.
  • Freeze run targets, refs and scenario selections before launch; atomically claim queued runs once and distinguish cancellation requests from observed executor/provider outcomes. Exercise concurrent claims and native HTTP reads against isolated PostgreSQL.
  • Keep reviewed bulk deletion and its completion receipt in one transaction. A failed receipt rolls back child cascades; projects created after the reviewed ALL snapshot remain untouched.
  • Make local authored memory available without an account or collector: exact add/patch/history through blop memory, with stale-revision rejection. The official MCP client can retrieve that same local revision through the eleven-tool read-only stdio catalog while the collector is offline.
  • Preserve the browser fetch receiver in the shared management client; requester-bound handoff navigation now reaches the authenticated security page in Chromium instead of failing with an illegal invocation. Keep an empty MCP tool catalog usable after every permitted app is disabled, without advertising disabled operations.
  • Add delegated device login, protected local profiles, live cloud operation discovery/calls and explicit reviewed-hash publication. Logout revokes the grant before deleting local credentials. Keep payload --input independent of the global --no-input control.
  • Load local and hosted memory/procedure sections with --field and Unicode continuation bounds. Bind local proposals to their retained idempotency key; freshness filters apply before authorized search ranking and pagination.
  • Move active web knowledge and learned procedures into per-workspace graphs through verified, resumable migration; retain legacy Postgres rows only as inert migration data. Resolve run sources against current workspace/project/attempt/artifact ownership and retention.
  • Freeze only the small task-consumed memory brief under fresh conversation/grant bindings, outside privileged prompt instructions. Live policy still gates every write; revocation and membership changes invalidate access to the frozen snapshot.
  • Expose one shared memory editor with revision-addressed receipts, historical comparison, explicit relationship direction and reviewed per-file document extraction. Keep tall/phone panels scrollable and restore keyboard focus after closing.
  • Reject streamed oversized HTTP requests promptly without waiting for both branches of a cloned request body to cancel. Restore a matched native graph/Postgres backup and recover an interrupted completion from its applied graph action without replaying a later revision.
  • Bound local CLI/MCP and hosted/web memory reads by bytes as well as row counts: share metadata and Unicode-safe preview pages with lossless hit/edge/revision cursors, metadata-only skill lists and explicitly selected Unicode procedure sections. Preserve complete edge identities even when JSON escaping requires omitting previews. Count addressed metadata omissions and make complete metadata progressively retrievable with a snapshot hash; the editor reconstructs it before changing content, preserving hidden references. Report neighborhood source omissions with sourceCount/sourcesTruncated; preserve complete core graph-store contracts. Local MCP exposes four collector evidence tools plus seven offline memory reads without account, collector or model initialization. Return compact commit/proposal manifests with explicit omissions so successful large writes are not misreported as unknown oversized responses.
  • Parse only the registry’s exact declared negative spellings across Node versions; --no-input cannot be interpreted as negating the string-valued payload --input.
  • Give Home an issue-first layout, with active agents and recent sessions in a quieter supporting column; stack the same content on smaller screens.
  • Refine the dark neutral palette, type hierarchy, navigation, filter boundaries, button states and spacing. Keep fonts self-hosted and status labels explicit.
  • Remove status-dot halos, pulsing loading placeholders and repeating onboarding motion. Empty issue queues link to recorded runs instead of repeating setup commands, and explicitly avoid implying that every flow was verified.
  • Redesign Sessions, scoped and recent logs, worker evidence, issue detail, run review, Connect, Settings, search and optional Ask around observe → investigate → verify. Make Logs and Workers discoverable from Sessions and keep advanced metadata behind disclosures.
  • Show the copied fix-context occurrence beside the handoff action, preserve exact session/worker evidence in agent briefs, and retain source receipts when copying an Ask answer. Distinguish command success, recorded checks and AI interpretation from independent verification.
  • Separate collector/agent/app/correlation readiness on Home and Connect. Explain bounded search, effective read-only settings, capture consent and configured-provider traffic without claiming complete evidence or zero network activity.
  • Record agent-launch process start and exit before the agent’s SDK flushes. Home lists observed active agents; Sessions links and filters use the same lifecycle evidence. Nested launches keep their enclosing run open, and lost local launchers stop reading as active after the collector’s sweep.
  • Recognize OMP’s native instrumentation scope even with a custom service name, instead of counting its model/tool activity as application requests.
  • Refresh Home on streamed activity, recover with polling while disconnected, and use the observed start time for unfinished spans instead of showing a 1970 timestamp.
  • Include the required protocol = "binary" in Codex OTLP configuration recipes.
  • Keep native conversation details consistent with the Sessions list: agent identity, recorded model, run and git stamp survive the drill-down, including custom-named OMP services.
  • Exclude Codex’s anonymous auth/runtime traces from coding-session counts and read its native model attribute. A model turn remains visible without inventing conversation links.
  • Keep agent prompt arguments out of launcher command metadata unless content capture is explicitly enabled; lifecycle observation still records start, exit and run correlation.
  • Explain missing application spans without claiming that agent telemetry is absent, and keep Home’s relative timestamps advancing without new telemetry.

Worker lifecycle and cancellation evidence

Section titled “Worker lifecycle and cancellation evidence”
  • Expose exact lifecycle/model evidence IDs and unknown source coverage/dropped records in mounted worker details. Verify authenticated receiver, CLI, API and inspector agreement without confusing stale connectivity, zero exit codes or unfinished spans with verified task success.
  • Mount the shared escaped cancellation renderer in exact worker details: distinguish source-reported exit from digest-bound independent observer evidence, retain execution/child/transport coverage and post-request activity, and expose no worker controls.
  • Add optional startMonitoringServer caller-supplied cancellationEvidence: {events, policy}. Copy the authenticated upstream snapshot at startup; raw OTLP/HTTP payloads still cannot grant observer authority. Ordinary daemon behavior remains default-deny and does not install an observer or add a transport.
  • Export cancellationEventDigest and cancellationCss from the monitoring API. Embeddings must load the CSS separately; the fragment no longer emits inline styles, preserving the inspector’s same-origin CSP and theme.
  • Add Pi to the inspector’s Coding agent (MCP) tabs and blop setup mcp pi. Setup preserves existing servers and supports project .mcp.json and user ~/.config/mcp/mcp.json, with handshake verification and scoped removal.
  • Pi needs pi-mcp-adapter; the Connect instructions include installation and reload steps. OMP reads the project configuration natively without that adapter.
  • Keep authenticated trace ownership, source capture consent, OpenCode model/version compatibility and interruption cleanup alongside the CLI UX changes.
  • Route multi-agent setup, hook/launch, source/filelog commands and graph index/search through the command registry. Agent setup uses the shared persistent collector policy; an explicit port wins over an environment URL.
  • All local inspector, chat, run and issue stores use the libSQL adapter against existing SQLite files. Graph snapshots retain user-recorded verification receipts.
  • Preserve opaque telemetry attributes and tags keys in machine output, query observation provenance, and status ingestion receipts.
  • Document source policy configuration and agent-hook timeout flags in command help. Help checks cover behavior and readability rather than pinning exact wording snapshots.

Breaking: the collector’s HTTP API is same-origin, and checks Host

Section titled “Breaking: the collector’s HTTP API is same-origin, and checks Host”
  • No more Access-Control-Allow-Origin: * outside OTLP ingest. The inspector, its APIs, sessions, session trees and transcripts, issues, fix context, runs, settings, health, the query API and /api/stream send no CORS header. A page on another origin can no longer read them; a script or tool that called the API from a browser page on another origin breaks. Call it from a local process (curl, fetch in Node, the CLI or MCP), or from the inspector itself.
  • CORS stays on OTLP ingest only: POST /v1/traces, /v1/logs and /v1/metrics and their OPTIONS preflight answer Access-Control-Allow-Origin: *, so an OpenTelemetry SDK running in a browser page on your dev server keeps exporting. Those routes take telemetry in and answer only an accepted count.
  • Host check on every route, OTLP included, with no exemptions (any future /mcp route too): the Host header must be 127.0.0.1:<port>, localhost:<port> or [::1]:<port>, else 403 Forbidden: Host is not this collector's loopback address. This defeats DNS rebinding. A local SDK, the CLI, MCP and the inspector send one of those already. A request through another name (host.docker.internal, a LAN name or an /etc/hosts alias) is refused; the collector binds loopback only. From a container, run the OTel SDK’s exporter against a port forwarded to the host’s loopback (for example ssh -L or a sidecar) with Host: 127.0.0.1:<port>, or run the instrumented process on the host. A dev-server proxy in front of /v1 (Vite server.proxy) must rewrite Host (changeOrigin: true), or the SDK can export straight to the collector, since OTLP answers CORS.
  • Origin check outside OTLP ingest: a present Origin must be the collector’s own (http:// plus one of those hosts), on GET too, else 403.
  • Guarded writes and chat follow the same rule. Issue state, mark-wrong, run start and finish, the workers acknowledgement and the inspector chat accept any of the three loopback Hosts, with Origin equal to http:// plus that same Host, and still require their marker header, JSON and no cross-site fetch. The inspector opened as localhost:<port> or [::1]:<port> now works fully; before, its chat and writes answered 403.
  • Errors. Every --json failure is one envelope on stdout with ok: false and error: {code, message, hint, docs, next}.
    • Rejected HTTP queries retain optional error.details with the responding collector instance, evidence revision and HTTP status.
    • Renamed codes: collector_unavailable is now collector_not_running, query_failed is now query_rejected, and invalid_argument is now invalid_value (or a more specific code such as unknown_flag or missing_value).
    • workers’ invalid_or_unavailable_snapshot is split into invalid_value, invalid_snapshot, collector_not_running and others.
    • graph and evidence errors use the envelope instead of a blop.graph/v1 error document.
  • Envelope.
    • Success envelopes carry ok: true.
    • Every envelope has a top-level next: [{command, when}]. On a failure it repeats error.next, which is also objects now, not strings.
    • warnings entries are {code, message} objects, not strings. One example is version_mismatch on up and status.
  • blop run --json. The old one-line camelCase object {runId, exitCode, sessions, requests, failedRequests, newIssues, regressedIssues, url} is gone.
    • It is now a blop.cli/v1 envelope. On stderr it is the last line Blop writes, on a line of its own; with --report <file> it goes to that file instead.
    • data has snake_case keys. new_issues and regressed_issues are lists of {id, title, url}. The old url is now data.collector_url.
    • ok is true when the command started, and false only when it never started.
    • Usage errors of blop run --json also go to stderr (or to the report), never to stdout.
  • blop tail -o ndjson (also --json and -f json). Each line now has schema_version and type. Keys are snake_case: exitCode is now exit_code, endReason is now end_reason, and traceId is now trace_id.
  • blop issues --json. Rows gain trend_24h. trend24h stays until blop.cli/v2, and every document carries one deprecated_field warning, so a non-empty warnings no longer means something went wrong: branch on code.
  • blop issue <id> --fix-context --json is an envelope with the markdown in data.markdown. It used to print the raw markdown.
  • blop init --json. data.next (a string) is removed. The suggested command is in the envelope’s next[].
  • blop workers overview|detail --json is a full envelope: ok, generated_at, page and next are added, and the document is pretty-printed. Its data keys are snake_case, for example worker_id and connection.connection_state.
  • blop setup opencode --json is a blop.cli/v1 envelope with the setup as data. It used to be a separate blop.setup/v1 document.
  • blop evidence ... --json and blop graph ... --json are envelopes. Text output is still the raw document.
  • blop setup mcp --json (new) is an envelope with command: "setup mcp" and data: {client, scope, target, invocation, action, snippet, backup?, verified, activation?}, or {clients: [...]} with no client. Its error envelopes say "setup mcp" too. blop setup opencode --json keeps command: "setup". action is added, replaced, unchanged, printed, command, removed or absent; invocation is null with --remove; backup is a path under Blop’s state dir (backups/<client>/).
  • blop init --json gains data.mcp with --mcp <client>, and without it one more next[] step, blop setup mcp.
  • The OpenCode MCP snippet (README, Connect page, blop setup mcp opencode) gains "timeout": 30000 when the command is npx, because a cold npx start outlasts OpenCode’s 5 second default.
  • BLOP_MCP_VERIFY=1 (new, internal; do not set it): blop mcp answers the protocol but never contacts a collector, whatever --url/--port say. It says so once on stderr (blop mcp: verify mode, no collector contact), and every tool call answers that it is in verify-only mode. blop setup mcp uses it for its start check and for the client’s own health-check, so setup never marks a collector “MCP connected”.
  • MCP invocation detection no longer trusts an inherited npm_command=exec: a blop on PATH that is this installation is always used. The Connect page shows install buttons only for that, or for a published pinned npx; another installation on PATH gets the update step (mcp.install_reason: "other_install").
  • The npx MCP command is pinned: npx -y @blopai/cli@<version> mcp (was npx -y @blopai/cli mcp, which fetched 1.7.0, a version without mcp). The Connect page shows it only when that version is known to be published; otherwise it shows npm i -g @blopai/cli and no install buttons (mcp.links is null, mcp.install is the step).
  • blop doctor --json. Rows are {id, category, status, ok, detail, fix, advisory}. A failed blocking check prints ok: false, the error, and the checks in data.

Breaking: blop mcp speaks MCP 2026-07-28 too, and its tool results changed shape

Section titled “Breaking: blop mcp speaks MCP 2026-07-28 too, and its tool results changed shape”
  • Both eras. Legacy clients keep the initialize handshake and ping; 2025-11-25 joins the accepted versions, and an unknown requested version now gets 2025-11-25 back (it was 2025-06-18). Modern clients get server/discover (supportedVersions ["2026-07-28", "2025-11-25", "2025-06-18", "2025-03-26", "2024-11-05"], capabilities.tools, instructions, ttlMs: 3600000, cacheScope: "public", _meta["io.modelcontextprotocol/serverInfo"], resultType: "complete"). A request whose params._meta carries the per-request protocol fields is served statelessly: a missing protocolVersion or clientCapabilities is -32602, a version other than 2026-07-28 is -32022 with data.supported and data.requested, and results carry resultType, serverInfo in _meta, and on tools/list ttlMs and cacheScope. ping is not a modern method (-32601 with modern _meta).
  • JSON-RPC edge cases. A request with "id": null (or a non-integer, non-string id), a JSON array (batches are not part of MCP), a non-object line and a request without a string method get -32600; unparseable JSON stays -32700 with id: null. Notifications are never answered.
  • Tools. Each tool has a title (List Blop issues, Get Blop issue, Get fix context, Get session or trace timeline) and annotations: {title, readOnlyHint: true, openWorldHint: false}; serverInfo has title: "Blop"; instructions end with “Needs a running Blop collector (blop up). Read-only.”
  • Results are structured, snake_case and compact. Each result carries structuredContent that matches the tool’s new outputSchema, and the same JSON, compact (no pretty-printing), in its text block (get_fix_context: the markdown). The shapes are the CLI’s: list_issues is {data, returned, total, truncated, note?} with blop issues --json rows (not_seen_in_latest_run, trend_24h, absolute url; was camelCase); get_issue is the blop issue <id> --json detail (snake_case, plus url, truncated, occurrences_returned, dropped?, note?); get_fix_context’s structured copy is {id, markdown, fix_context_url, url, truncated}; get_session keys are snake_case (session_id, trace_id, source_id, duration_ms, span_id, parent_span_id, metadata.call_id, …). The outputSchemas are composed from schema/issues, schema/issue and the new schema/mcp-tools (blop schema mcp-tools).
  • Size. Results are capped near 36 KB (was 50 KB, pretty-printed), under Claude Code’s 10,000-token warning. A cut result stays valid JSON with truncated: true and a note naming the command that shows everything (blop issues --json, blop issue <id> --json, blop issue <id> --fix-context, blop open <id>). get_issue empties whole sections (objects to null, lists to empty) before it drops chain steps, so it still matches schema/issue.
  • Which collector. blop mcp reads the collector of the client’s project: BLOP_PROJECT_DIR, else CLAUDE_PROJECT_DIR (Claude Code sets it), else its working directory; --url and BLOP_MONITOR_URL still win. When several collectors run and none matches, a tool call is an isError result listing each one (url and workdir) and the exact BLOP_MONITOR_URL=... fix; it used to answer silently from the default port. A collector that answers 200 with a body that is not JSON is an isError result too (it used to read as an empty list).
  • get_fix_context whose first line alone is over the cap keeps as much of that line as fits (whole characters), then the note; it used to return the note alone.
  • stdout carries only JSON-RPC messages (now covered by a test that feeds valid, invalid and failing input); diagnostics go to stderr.

blop setup mcp: one client table, Gemini CLI, Windsurf, Claude Desktop, stale entries

Section titled “blop setup mcp: one client table, Gemini CLI, Windsurf, Claude Desktop, stale entries”
  • One table (src/monitoring/mcp-clients.ts) now drives blop setup mcp, the Connect page’s tabs, snippets and install links, mcpConfigSnippets, blop mcp --help and the README and docs client section (generated between markers by node scripts/render-mcp-docs.mjs; a test fails when they drift).
  • New clients. gemini runs gemini mcp add -s project|user blop <command> (and gemini mcp remove -s <scope> blop), never --trust, and verifies by reading mcpServers.blop back from .gemini/settings.json or ~/.gemini/settings.json (read only; a backup of the previous file goes to Blop’s state dir). It used to be refused. windsurf and claude-desktop print the entry and where it goes and never write (action: "printed", a print_only warning): Windsurf’s config path is moving (~/.config/devin/mcp_config.json, older ~/.codeium/windsurf/mcp_config.json), and Claude Desktop has no project and a minimal PATH, so its entry uses the absolute path of blop. blop init --mcp and completion offer all eight.
  • User-scope Cursor and VS Code entries carry env.BLOP_PROJECT_DIR = "${workspaceFolder}", and so do the Connect page’s Cursor snippet and both install links (which install at user level). A user-scope entry written before this has no env and now reads as stale (missing_project_env); blop setup mcp cursor --scope user --force rewrites it.
  • The VS Code snippet on Windows wraps npx in cmd /c on the Connect page and in its install link too, as setup already did. Codex’s TOML snippet gains startup_timeout_sec = 30 when the command is npx.
  • Connect page JSON. mcpSnippets is keyed by client id (claude, codex, cursor, vscode, opencode, gemini, windsurf, claude-desktop; claude-code is now claude), and mcpClients lists the tabs in order.
  • Stale entries. blop setup mcp with no client reports, per client, every blop entry in entries[] ({scope, target, command, args, status, reason, detail, update}). An entry is stale when it pins an older @blopai/cli, runs an unpinned one, uses npx while this blop is on PATH, names a command that no longer exists, or (user-scope Cursor and VS Code) lacks BLOP_PROJECT_DIR; text output prints one warning: line on stderr per stale entry with its update command, and next[] lists them. A server someone else named blop is status: "other" and never offered for --force. A client’s status can now be other, and the text word for a stale one is stale (was stale command).
  • blop doctor gains an mcp check under Agents: ok when no Blop entry is stale (none at all is fine), a warning naming each stale entry with its update command as the fix. It is advisory, so it never fails doctor; the Connect page shows it too.
  • Exit-code table. 0 ok, 1 failure, 2 usage, 3 Blop not running, 4 query rejected, 5 timeout, 6 could not verify (blop init, blop setup mcp: the result could not be confirmed, or nothing was written because it would not work), 129 terminal closed (SIGHUP), 130 interrupted, 143 terminated (SIGTERM) (blop help exit-codes). 129 and 143 come from blop setup mcp when its start check is cut short.
    • Bad flags used to exit 1; they now exit 2.
    • An unreachable collector exits 3.
    • --state bogus exits 2 before any request is sent.
  • Interrupts. Ctrl-C now exits 130 for blop tail, a foreground collector and blop monitor start. It used to exit 0.
  • Strict parsing. Unknown flags, extra arguments and a leading -- exit 2. --reasoning-effort was never implemented and is now an unknown flag.
  • Output formats.
    • -o takes only the formats a command lists, and anything else exits 2. For example, skills --json used to be ignored and is now refused.
    • --json -o text, -f json -o text and workers --json -o text exit 2.
  • blop flow init asks before overwriting. Without a terminal it exits 2 unless --force is given.
  • One collector precedence on every command: flag, then env, then the registry or the default. blop up -p/--port and --host (and blop monitor start) now win over BLOP_MONITOR_URL, as they already did on status, stop, run, open, init, mcp, doctor and the query commands. Before, blop up -p N in a shell where eval "$(blop status -o env)" had exported BLOP_MONITOR_URL silently reused that collector, or exited 3 when it was gone.
  • blop up reads BLOP_MONITOR_HOST, the env of --host, as the client commands already did (blop monitor start did before this release too). It is held to the same rule: 127.0.0.1, ::1 or localhost, anything else exits 2.
  • host_refused (exit 4). A request the collector refuses for its Host (a BLOP_MONITOR_URL or --url that names host.docker.internal, a LAN name or an /etc/hosts alias) is host_refused, with a hint naming the loopback forms. It read as The collector rejected the query (HTTP 403) (query_rejected). blop mcp tool results say the same.
  • blop setup opencode --url exits 2 (unsupported_flag). It was accepted and ignored; the command starts or reuses a collector by port (-p).
  • blop tail’s help no longer lists exit codes 3, 4 and 5: a collector that is down is waited for, with one warning, and tail reconnects. blop status’s note now says -q silences stdout only (errors still go to stderr).
  • Exit never waits more than 5 s for stdout and stderr to drain. A reader that keeps the pipe open and never reads used to hold the process forever; it now exits with the intended code.
  • blop issues. Piped output is tab-separated with no header (use --header for one): ISO times, the full commit, and the inspector URL. The terminal shows an aligned table.
  • blop run. The summary on stderr is a 7-line block instead of one line.
  • blop tail. The status lines are now warning: Blop is not running at <url>; waiting for it (start it with blop up) and Connected to Blop at <url>.
  • Errors. All errors use error:, usage:, hint: and docs: lines on stderr.
  • Help. All help is generated from the command registry. Root help’s setup row reads Connect a coding agent: blop setup mcp claude, and blop setup --help lists JSON FIELDS per subcommand (blop setup opencode --help, blop setup mcp --help).
  • blop init ends with one more line: Agents: blop setup mcp <client> .... Its Next: line (and next[0] in JSON) names the dev command bare blop run would start, with the lockfile’s package manager (blop run -- pnpm run dev); it always said npm run dev.
  • The MCP line blop up prints for a coding agent, and the m shortcut’s copy, are now blop setup mcp claude (plus -p N or --url <url> only when you passed one), spelled npx -y @blopai/cli@<version> setup mcp claude when blop is not on PATH and that version is known to be published, and npm i -g @blopai/cli && blop setup mcp claude otherwise, the same rule the Connect page uses. They were a hand-built claude mcp add blop -- blop mcp [--url ...], which registered a server that could not start for npx users and pinned the URL of a non-default port. blop setup mcp claude checks that the server starts before it adds it.
  • blop up opens the inspector by the rule blop open uses: not under --no-input or BLOP_NO_INPUT, BROWSER=none, over SSH or with no display (it already skipped coding agents and pipes).
  • blop run with no command runs the package.json dev script with the package manager the lockfile names (pnpm, yarn, bun, else npm) and says so in one stderr line. Without a dev script it still exits 2, now with the scripts it found in the hint. A dev script that runs blop itself (blop run, npx blop, bun run src/cli/index.ts) is refused (exit 2, dev_script_runs_blop). A coding agent running blop run gets one short stderr block before the command starts (inspector URL, blop issues --json, blop run --json).
  • blop run prints one line before the command starts: blop run: telemetry to <url> · service <name> · content capture off (--capture-content) · found ai-sdk (blop init prints their setup) (or no agent SDK found here). --no-summary drops it and the end summary block. The command’s own stdio is untouched.
  • blop run inside blop run. Every command blop run starts gets BLOP_LOCAL_RUN_ID, BLOP_LOCAL_RUN_PID, BLOP_LOCAL_RUN_START and BLOP_LOCAL_RUN_DEPTH, with a collector or without one. While that outer blop run is still running, a blop run -- <cmd> inside it joins its run (no second run, the outer TRACEPARENT and run id are kept; its own --capture-content, --url and --port do not apply, and it says so once; --json reports recorded: false with nested_run, plus nested_flags_ignored when flags were dropped), and a bare blop run inside it exits 2 (nested_run), so a dev script cannot recurse, even indirectly. A marker whose blop run has ended (a shell or terminal that outlived it) is ignored with one stderr note (stale_run_marker in JSON) and a new run starts. With 8 runs already enclosing it, blop run exits 2.
  • --no-summary also drops the coding-agent block.
  • The lockfile and packageManager for bare blop run are also looked up in parent folders, up to the git root (workspaces).
  • Root help lists open (INVESTIGATE) and completion (MANAGE).
  • blop open [<issue|session|run|trace id> | <page>] [--print] [--json] opens the inspector at that object or page (home, sessions, issues, runs, connect, settings) on the resolved collector. It prints the URL instead with --print or --json, for a coding agent, with --no-input, with BROWSER=none, over SSH and with no display. An unknown target exits 2 with did-you-mean. blop issue <id> --web and blop trace <id> --web do the same for one object. BROWSER=<command> now names the program that opens a URL (also for blop up): a :-separated list (; on Windows), tried in order, with %s for the URL. When no browser starts, blop open prints the URL. On Windows the URL goes to rundll32 url.dll,FileProtocolHandler (not cmd /c start, which cut URLs at &).
  • blop completion bash|zsh|fish prints a completion script generated from the command registry: commands, subcommands, flags and their values, plus live issue and run ids from the running collector (through the hidden blop __complete, which prints nothing when the collector does not answer).

Renamed commands (old names still work, with a notice on stderr)

Section titled “Renamed commands (old names still work, with a notice on stderr)”
  • blop run x.blop.ts (flow checks) is now blop flow test. blop run wraps a command.
  • blop test, blop watch and blop list are now blop flow test|watch|list.
  • blop monitor start|stop|status are now blop up, blop stop and blop status.
  • blop status is a lifecycle command (-o text|json|env, --logs), not a query.

Standalone agent testing and local coverage

Section titled “Standalone agent testing and local coverage”
  • Move the agent-test DSL, runner, configuration, reporters, optional platform upload, templates and authored examples into @blopai/test. Import tests from @blopai/test; @blopai/cli retains the blop command and delegates Browser Harness flows to that package. Remove the old runtime/reporters/platform exports rather than preserving aliases.
  • Add opt-in Chromium JavaScript coverage with --coverage and explicit collector delivery through --coverage-endpoint. Save the report before hosted artifact upload, remove stale coverage artifacts on non-coverage runs, and preserve test identities when a run ends early.
  • Add the local inspector’s Coverage view: latest report, file/test filters, executed UTF-16 source-character totals, paginated source annotations, test outcomes and visible collection gaps. Persist bounded reports separately from trace storage; do not imply statement/branch coverage, source maps, unloaded-file coverage or a run/trace join.
  • Exclude oversized browser-script measurements with explicit warnings instead of losing the run’s report. Validate collector payloads, enforce body and evidence limits, and apply the local write boundary.
  • Discover DSL registrations, default exports and named test arrays together, deduplicate repeated exported objects, and retain registered checks on repeated Bun imports.
  • Document agent-driven E2E goals, deterministic assertions, evidence, safe targets, runtime/provider failures, flake handling, CI artifacts and coverage limits.
  • Move testing ownership to the independent blop-oss/blop-test repository; preserve the genuine May 2026 implementation and full dated provenance, squash the standalone import, and consume an immutable public Git source until npm publication is provisioned. Remove the workspace package, portable browser patch and testing release workflow; CLI, dashboard and generated GitHub workflows use the external SDK. Align skill tool results with the browser harness’s caller-origin, untrusted content boundary.
  • Verify canonical and legacy CLI flow execution against the standalone SDK’s public exports with real Chromium and loopback app/provider fixtures: actual assertions produce exit 0/1 and matching results, JUnit, events and progress. Preserve the immutable shipping Git dependency while using the local clone for this verification; repair the clone’s root example import to use @blopai/test.