github Dicklesworthstone/beads_viewer v0.23.0

3 hours ago

Reality check 2026-09 (bridge plan docs/planning/REALITY_CHECK_BRIDGE_PLAN_2026-09-01.md)

  • Data sources: discovery only reads issue-file names from the loader allowlist (no more sync_base.jsonl shadowing), probe warnings are buffered and only surface for the source actually used, and every robot payload names its source_path / source_kind plus as_of / scope in one shared envelope.
  • Robot registry: five handlers that ignored --label / --recipe / --repo / --as-of now honour them; --robot-file-hotspots moved into the registry and roughly 1,400 lines of unreachable inline handler copies were deleted from cmd/bv/main.go, along with the never-imported pkg/beadscli package; --robot-help is generated from the registries.
  • Feedback loops: --feedback-* weights change --robot-triage scoring (after three samples), and correlation confirm/reject changes --robot-history, the commit index, --robot-explain-correlation, and the History view.
  • Correlation: explicit-ID and temporal strategies run alongside co-commit; the artifact cache is format-versioned; --robot-orphans reports the scanned window and beads-only commit count.
  • Sprints and alerts: four-signal at-risk detection shared by the dashboard and --robot-burndown (at_risk), a scope-aware ideal line, P opens the dashboard; every declared alert type has an emitter (velocity_drop, high_impact_unblock, abandoned_claim, potential_duplicate) plus new priority_mismatch and scope_creep, each with a suggested_action, labels for --alert-label, a proactive_max_issues cap with skipped_checks, and every threshold documented from .bv/drift.yaml.
  • TUI: attention view with cursor and drilldown, tutorial progress persisted, Shift+Tab / n N / t bindings, startup update check opt-out (BV_NO_UPDATE_CHECK).
  • Workspaces and recipes: .bv/workspace.yaml is auto-discovered when no .beads is reachable; recipes load from .beads/recipes/*.yaml and --recipe accepts a file path.
  • Release gate: scripts/release_gate.sh (gofmt, build+vet, -race unit and e2e, docs parity, action pins, vendor hashes, benchmark compare, robot smoke, and the gate's own script self-tests) with scripts/check_action_pins.sh, scripts/robot_smoke.sh, scripts/verify_vendor.sh, a vendored-asset MANIFEST.json and docs/PROVENANCE.md; ci.yml runs the gate; scripts/verify_isomorphic.sh builds the baseline in a detached worktree instead of stashing the caller's tree.
  • Release archives (#195): .goreleaser.yaml now names archives bv_<version>_<os>_<arch>.<ext>; bv --update prefers the versioned name and still accepts the unversioned form older releases used; install.sh selects by platform so it handles both; README's direct-download section points at the release page and checksums.txt instead of moving latest links.
  • Dashboard CSP (#197 residue): the exported dashboard's script-src no longer allows 'unsafe-inline': the four inline bootstrap scripts moved into head_init.js and the top of viewer.js, 'wasm-unsafe-eval' is declared for sql.js and the graph WASM, and bv --preview-pages serves its live-reload script as /__preview__/livereload.js instead of injecting an inline block. 'unsafe-eval' remains because the vendored Alpine build evaluates x-* expressions with Function(); switching to Alpine's CSP build is the remaining step. Guards: TestEmbeddedIndex_CSPHasNoInlineScripts (also checks every referenced asset is embedded) and the e2e export check. Verified in a headless Chromium with scripts/dashboard_browser_smoke.sh: no refusals, database, WASM graph engine, charts, and triage all boot, and a planted inline script is blocked while the app still runs.
  • Hardening sweep, pkg/analysis (from wip/fresh-eyes-20260826): 37 files landed after a per-file rebase behind the gate: exact issue-ID matching in dependency suggestions (bv-42 no longer matches inside bv-420), shell-quoted bead IDs in suggested br commands, cycle detection that reports truncation instead of silently capping, readiness-after-completions helpers shared by plan and priority, config caps normalised to defaults, and the cache refusing to serve incomplete Phase 2 results. Two tests on that branch were broken on the branch itself (a DeferUntil pointer aliased into the expected value; a cache-version literal not bumped) and are fixed here; the branch's asynchronous cache publish raced a synchronous second Analyze, which now stores before returning. The remaining packages of the branch are triaged in tracker item H4.
  • Benchmark gate (stage 8): scripts/benchmark.sh now runs ten tracked benchmarks against the frozen tests/testdata/benchmark/medium.jsonl (never the live tracker), writes benchmarks/baseline.txt with a provenance header (date, Go, CPU, OS, commit, dataset hash), and compares the best observed ns/op per benchmark with a built-in comparator (benchstat optional); tests/scripts/benchmark_compare_test.sh proves it turns red on a doubled median and a missing benchmark. compare judges HEAD against a fresh run of the baseline commit built in a detached worktree minutes earlier on the same machine, so host drift on a shared VM no longer reads as a regression; the stored baseline is the fallback.
  • Key registry decision (tracker item B9): the TUI KeyRegistry is the help index only; its never-called dispatch surface (Dispatch, RegisterView, Handler, BindingsCount, Clear) is gone. Keys that worked but were undocumented (E, f, !, w, s, S in the list; H, L, s on the board; E in the tree) are now in GetKeyBindingDocs, the sidebar, and the README, with tests driving each through Update.
  • Windows installer (#197 finding 3): install.ps1 now downloads the release zip and checksums.txt, verifies SHA-256 with Get-FileHash, and refuses a missing or mismatching checksum before anything reaches the install directory; Go is no longer required (-FromSource keeps a build pinned to the resolved tag). tests/scripts/install_ps1_test.sh runs it under pwsh against a local fake release: verified install, tampered checksum refused, missing checksums refused, -Version pin. README pins the piped form to the reviewed commit.
  • Hardening sweep, pkg/loader and pkg/workspace (from wip/fresh-eyes-20260826, pass 3): .beads/redirect following exposed as ResolveBeadsDir/ResolveBeadsDirWithTrace, the issues file opened only after a same-file check, bd export refreshes run with an absolute BEADS_DIR and without an ambient BEADS_DB, and the workspace aggregate loader reports dropped records per repository, routes parse warnings safely in robot mode, and rejects cross-repository ID collisions; over-limit lines are counted before their warning fires so handlers see consistent stats.
  • Hardening sweep, pkg/search (from wip/fresh-eyes-20260826, pass 4): a stored vector index whose dimension does not match the embedder is backed up and rebuilt instead of being served as a hit; NewHybridScorerAt pins the recency clock; normalizer and query-adjustment fixes land with their tests. Main's stricter vector-index validation is kept. The branch's internal/datasource slice is retired: the allowlist and silent-probing design already on main replaced it.
  • Graph WASM rebuild (#197 finding 8): scripts/build_graph_wasm.sh pins the rebuild without wasm-pack (cargo for wasm32-unknown-unknown, a wasm-bindgen CLI that must match the crate version in Cargo.lock, wasm-opt -Os) and prints built and vendored hashes with tool versions; docs/PROVENANCE.md records that the comparison is still owed and why.
  • Agent blurb v5: the ready-made AGENTS.md block now says that --graph-format=dot|mermaid returns the diagram text in the graph field of the JSON envelope. The version marker moved from v4 to v5 so bv --agents-update refreshes installed blocks (--agents-add compares versions, not content); this repository's AGENTS.md and the README copy were regenerated with the tool.
  • Decisions recorded: no path-matching correlation strategy (README diagram and prose agree); downgrade priority recommendations are not alerts; cycle_introduced is documented as new_cycle.
  • Environment registry (internal/env): Centralizes all 41 BV_* and BEADS_* environment variables in a single package with typed accessors (BV_NO_COLOR, BV_TEST_MODE, BV_LOG_FORMAT, BV_SEARCH_MODE, etc.) and an AST-walking vet test guaranteeing zero raw os.Getenv / os.LookupEnv calls in production code.
  • Documentation generator (internal/docgen): Emits living reference documentation (docs/generated/{flags,env,alerts,recipes,presets,keys,sort_modes}.md and constants.json) and synchronizes tables into README.md via go generate / bv --generate-docs.
  • Milestone completion: All 615 tracking beads and epics closed (100% completion across graph analysis, drift detection, TUI, search, correlation, and the 10-stage release gate).
  • Tracker recovery (2026-09-02): .beads/beads.db was at schema 0 and rejected by br 0.5.7 (SCHEMA_MISMATCH expected 17, found 0); the JSONL was harmonized (empty-string fields dropped, dependency metadata / thread_id added), a fresh DB was rebuilt from it and promoted, and the old DB was renamed aside (beads.db.bad_20260902T030027Z) rather than deleted. With the maintainer's written approval later that day the renamed DB/WAL/SHM and the two rebuild *.fsqlite-migration-state markers were removed; the recovery_20260902T023914Z/ snapshot (git-ignored) is the one leftover, kept for a recursive removal from the maintainer's own shell.

Fixed

  • SQLite-backed reloads (Ctrl-R / F5 and file-watch refreshes) failed on Windows with
    cannot connect to database: SQL logic error: invalid uri authority: E:%5C.... The read-only
    DSN was built with net/url, which turns a drive-letter path (or any relative path) into
    file://E:%5C..., putting the first path segment in the URI authority slot. The DSN path is
    now absolute and slash-normalized (file:///E:/...) on every platform (#198).

Don't miss a new beads_viewer release

NewReleases is sending notifications on new releases.