eji87apuq7rsiskmnma1qd5pr78d7daa · 20 rows
| id | content_hash | title | description | design | acceptance_criteria | notes | status | priority | issue_type | assignee | estimated_minutes | created_at | created_by | owner | updated_at | closed_at | closed_by_session | external_ref | spec_id | compaction_level | compacted_at | compacted_at_commit | original_size | sender | ephemeral | wisp_type | pinned | is_template | mol_type | work_type | source_system | metadata | source_repo | close_reason | event_kind | actor | target | payload | await_type | await_id | timeout_ns | waiters | hook_bead | role_bead | agent_state | last_activity | role_type | rig | due_at | defer_until | no_history | started_at | is_blocked |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| sr-ht-dolt-0qf | fc02bbd7697c59c02d006fb5e3bf2c052d971c36d809bea95e2ef0a159889b16 | MCP surface: a read-only agent door to hosted databases | Serve /mcp on the web listener so an agent reads a hosted Dolt database — and the beads tracker inside it — by calling tools instead of scraping the board HTML. Read-only by construction: no SQL tool (the pure-Go build stands on never starting the engine), no writes, no second reading of any schema. Spec: docs/DESIGN.mcp.md. | docs/DESIGN.mcp.md is normative. Donor is sourcehut-coverage/mcpsrv (modelcontextprotocol/go-sdk v1.6.1): stateless streamable HTTP, Host allowlist replacing the SDK DNS-rebinding guard, consumer-side seams in ports.go, in-process client over fakes in tests. | open | 1 | epic | NULL | NULL | 2026-08-12T20:10:04Z | Eugene Blikh | bigbes@gmail.com | 2026-08-12T20:10:04Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | 0 | NULL | NULL | NULL | 0 | NULL | 0 | |||||||||||||||||||||||
| sr-ht-dolt-0qf.1 | 573249e114393372c5f26a2572baf8fa924e214e471ed31e1d75e9c8245b53d6 | Extract the beads projection into a root beads/ package | web/beads.go holds the one reading of the beads schema (fingerprint, lane bucketing, ready rule, status categories, dependency walk, event humanizer, filter model, row helpers) where a second consumer cannot reach it. Move it to a root beads/ package depending on browse/ and the stdlib only; web/beads.go and web/milestones.go keep their View implementations. Prerequisite of the MCP beads tools, of the cross-database ready page and of cross-database links. | docs/DESIGN.mcp.md §8. Pure move plus export renames — web/beads_test.go and web/milestones_test.go move with it. A behaviour change smuggled into this commit makes the refactor unreviewable. | go test ./... green with the suites relocated; no behaviour diff in the rendered board (same fixtures, same output); beads/ imports neither net/http nor core. | in_progress | 1 | task | NULL | NULL | 2026-08-12T20:11:37Z | Eugene Blikh | bigbes@gmail.com | 2026-08-12T20:15:38Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | 0 | NULL | NULL | NULL | 0 | 2026-08-12T20:15:38Z | 0 | ||||||||||||||||||||||
| sr-ht-dolt-0qf.2 | 8e6146eadd1e58f2b423fb9dd6cd47903d1e79ea7e967d24566aea9812fb090c | authn: the tokens.sr.ht bearer plane and core.GrantRead | /mcp is bearer-only, and this service has no bearer plane today: cookie, meta PAT over HTTP Basic, and the dolt keypair JWT on gRPC. Add ParseBearer plus a plane over sr-ht-ecore/bearer (working tokens issued by tokens.sr.ht, ClientID tokens.sr.ht, gated on the new core.GrantRead = "dolt:read") and a meta-PAT arm over the existing decode path, gated by authn.TokenGrantsAllow at core.AccessRO. A token that fails verification is a refusal, never a downgrade to anonymous. | docs/DESIGN.mcp.md §4. sr-ht-ecore/bearer + /grants are already reachable (sr-ht-ecore is a direct dependency); cov.sr.ht authn/instance.go is the donor, including the consumer-side InstanceValidator seam. [tokens.sr.ht]origin absent means no such daemon: working tokens refused, meta PATs and anonymity still work. | Table-driven classification tests with no network: working token with/without dolt:read, meta PAT, garbage, absent header (anonymous), expired. | closed | 1 | task | NULL | NULL | 2026-08-12T20:11:44Z | Eugene Blikh | bigbes@gmail.com | 2026-08-12T20:27:26Z | 2026-08-12T20:27:26Z | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | Landed in 6288fc1: ParseBearer, the InstanceValidator seam over sr-ht-ecore/bearer, BearerCaller with Authorize, ResolveBearer branching on ClientID, core.GrantRead. Plus 0f6d50a (gofmt drift in authn tests, pre-existing at 587483e). | 0 | NULL | NULL | NULL | 0 | 2026-08-12T20:17:10Z | 0 | |||||||||||||||||||||
| sr-ht-dolt-0qf.3 | 700764cff30a4c71a08b87eecb428a469a1701bb257a567e2e8b55e8e1762223 | mcpsrv: skeleton, Host allowlist, grant gate, list_databases | New mcpsrv/ package: Server + New over modelcontextprotocol/go-sdk, stateless streamable HTTP, the Host allowlist that replaces the SDK DNS-rebinding guard, the read-grant gate in front of the handler, consumer-side seams in ports.go, and one tool (list_databases) to prove the surface end to end. | docs/DESIGN.mcp.md §5-§7. Stateless is an authentication decision: in stateful mode the principal of the initialize request answers every later call. Port the donor identity matrix test and re-run it against our pinned SDK rather than citing the donor. | Identity matrix test (no credential / stranger token / owner token on one session) asserts the answer follows the call; Host allowlist test (instance host passes, rebinding host 403 before the SDK); grant gate test. | in_progress | 1 | task | NULL | NULL | 2026-08-12T20:11:44Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T05:01:29Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | 0 | NULL | NULL | NULL | 0 | 2026-08-13T05:01:29Z | 0 | ||||||||||||||||||||||
| sr-ht-dolt-0qf.4 | bd8dd472bd71f282d5eaea3072a8e8cd448fb2c7d330444408baed331e9121f6 | mcpsrv: generic tools over the browse seam | list_branches, list_tables, read_rows, get_commit_log, get_commit_diff — the browse surface as tools, addressing a database as {owner, name} and defaulting ref to the repository default branch. Caps: read_rows limit<=500 (default 100), get_commit_log limit<=100 (default 25); a truncated result says so and carries the true total. | docs/DESIGN.mcp.md §9.1, §9.3. Visibility is core.Allowed/OpBrowse with NotFoundForPrivate masking — never a distinguishable forbidden. | Visibility matrix per tool over PUBLIC/UNLISTED/PRIVATE x anonymous/stranger/grantee/owner; cap tests. | open | 2 | task | NULL | NULL | 2026-08-12T20:11:45Z | Eugene Blikh | bigbes@gmail.com | 2026-08-12T20:11:45Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | 0 | NULL | NULL | NULL | 0 | NULL | 1 | ||||||||||||||||||||||
| sr-ht-dolt-0qf.5 | 4fcc9363da648c65592a42ad2216428ffa16a7f84c3e48e5c568583cfa3774a3 | mcpsrv: beads tools over the shared projection | list_issues, get_issue, list_milestones, list_memories over the extracted beads/ package. Lists carry identity and metadata and no long-text bodies; get_issue carries the bodies, both dependency directions, the transitive trees, subtasks with the rollup for an epic, comments and the merged history. The tool list is static per server, so a database without the fingerprint is refused per call, naming the generic tools as the way to read it anyway. | docs/DESIGN.mcp.md §9.2. list_memories reports the revision each memory was last written at, sharing the walk with the Memory view. | A non-beads database answers the beads tools with the explanatory refusal, not an error; list_issues carries no description/design/notes field at all. | open | 2 | task | NULL | NULL | 2026-08-12T20:11:46Z | Eugene Blikh | bigbes@gmail.com | 2026-08-12T20:11:46Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | 0 | NULL | NULL | NULL | 0 | NULL | 1 | ||||||||||||||||||||||
| sr-ht-dolt-0qf.6 | 60d5c474af1047fa392cd9d63c9cb26b0accfdf049c3f41f371722ea531999d1 | Wire /mcp into the daemon, config and README | Register the MCP handler in cmd/doltsrht/main.go with r.Handle("/mcp", …) before web.Register and outside its CSRF group (bearer surface, no Origin, no cookie), document [tokens.sr.ht]origin in config.example.ini, and describe the surface in README.md. | docs/DESIGN.mcp.md §3, §10. Handle and not Mount: Mount rewrites the path to the empty remainder and claims /mcp/*. No mcp-enabled switch — a surface that is off in production is one nobody tests. | An httptest boot proves /mcp answers a tools/list and that the CSRF guard does not touch it, while a browser POST to a web form still requires same origin. | Also amend authn/ctx.go's package doc: it still says 'the three authentication flows' and does not mention the bearer plane added in 6288fc1. The wiring commit is where that sentence becomes wrong in a way a reader can see. | open | 2 | task | NULL | NULL | 2026-08-12T20:11:47Z | Eugene Blikh | bigbes@gmail.com | 2026-08-12T20:27:33Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | 0 | NULL | NULL | NULL | 0 | NULL | 1 | |||||||||||||||||||||
| sr-ht-dolt-0qf.7 | 46b9183986187b6c28b54f588ebbf6016eb24826ef63e641fb59a008be493edd | mcpsrv: ready_work across every visible beads database | ready_work with no database named answers the ready set across every beads database the caller may see, sharing the /ready aggregator and its cache; the page and the tool differ in rendering only. | docs/DESIGN.mcp.md §9.2 and docs/DESIGN.views.md ch.4 — one implementation, two surfaces. | The tool and the page answer the same set for the same caller. | open | 3 | task | NULL | NULL | 2026-08-12T20:11:52Z | Eugene Blikh | bigbes@gmail.com | 2026-08-12T20:11:52Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | 0 | NULL | NULL | NULL | 0 | NULL | 1 | ||||||||||||||||||||||
| sr-ht-dolt-16t | 88a2fd7a5715be57384920506c31f7cd305072679ab394336b15dd060c0a7610 | Show the original object on the issue detail page | The issue detail pane (`/view/beads?issue=<id>`) renders a curated subset of an issue: the fields the card model carries, the dependency trees, and the Comments / History tabs. Everything the view does not model — columns bd added that BeadIssue has no field for, custom metadata, the exact stored strings behind the humanized events — is invisible without leaving for the generic table browser and hunting for the row by hand. Show the original object on the detail page: the raw stored row(s) behind the issue, as read from the tables, so the rendering can be checked against what is actually in the database. | - Carry the raw data on BeadsData in detail/epic mode: the `issues` row as an ordered column → value list (column order as read, NULLs kept distinct from empty strings — `cell` currently flattens the browse NULL placeholder to "", so read the row directly rather than through it), plus the matching rows from the satellite tables the pane already reads (labels, dependencies, comments, events) when they add anything. - Render it as a third tab in the existing activity switch next to Comments / History — the switch is a pure-CSS radio group, so a third radio + label + panel needs no JS — or as a `<details>` block under the field table if the tab strip gets crowded. Keep it collapsed by default: it is a debugging surface, not the main reading. - Present it as a key/value table plus the row as JSON, both escaped; values can be long free text (descriptions, design notes) and must wrap rather than blow the layout out horizontally. - Reuse the read that already happens in Build — the detail pane loads these tables anyway, so this must not cost another Rows call. - Tests in web/beads_test.go: raw block present in detail mode and absent in board mode, a column with no BeadIssue field still shows up, NULL renders distinctly from "". | On /view/beads?issue=<id> the raw stored row behind the issue is visible without leaving for the table browser: every column of the issues row (including ones the view models no field for) with NULL distinguishable from an empty string, collapsed by default, long values wrapping instead of widening the page. | open | 2 | feature | NULL | NULL | 2026-08-10T11:13:36Z | Eugene Blikh | bigbes@gmail.com | 2026-08-10T11:13:36Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | 0 | NULL | NULL | NULL | 0 | NULL | 0 | ||||||||||||||||||||||
| sr-ht-dolt-44n | b50bb951638f211f7c763f1bd998752099e314d771c1f93716eedd99ce9cb4d0 | Beads views, round two: stream, memory, freshness, cross-database | Six changes to the read-only beads surface: a one-column stream layout beside the parade board, a view for the memories bd remember writes, a freshness line in the header, a cross-database ready page, cross-database issue links, and copy-ready bd commands on the detail pane. Spec: docs/DESIGN.views.md. | docs/DESIGN.views.md is normative. Everything stays read-only and stays inside the todo.sr.ht visual idiom the board already adopts. | open | 2 | epic | NULL | NULL | 2026-08-12T20:10:11Z | Eugene Blikh | bigbes@gmail.com | 2026-08-12T20:10:11Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | 0 | NULL | NULL | NULL | 0 | NULL | 0 | |||||||||||||||||||||||
| sr-ht-dolt-44n.1 | c75e486b670035125752508f498c905d88782b651d831cb7a753cb4b3a6ade9a | Beads board: the one-column stream layout | ?layout=stream renders the same filtered cards top to bottom under section headers in parade order (Rolling, Lined Up, Stalled, Past Stand) with a Board | Stream toggle in the filter bar. Each section sorts to its own question: Rolling by started_at desc, Lined Up ready-first, Stalled by fewest blockers, Past Stand by closed_at desc. Past Stand is collapsed in a <details> — no JavaScript. | docs/DESIGN.views.md ch.1. A layout of the Beads view and not a fifth tab: filters, the ready toggle and ?issue= links are unchanged. Needs the withQuery template func so the toggle preserves the current query. | Section counts equal lane counts for the same filters; each section order asserted; an unknown layout value falls back to the board. | closed | 2 | task | NULL | NULL | 2026-08-12T20:11:47Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T05:17:21Z | 2026-08-13T05:17:21Z | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | Landed in fe616c8: ?layout=stream with per-section sorting, Past Stand collapsed in <details>, sticky section heads, withQuery template func. Measured in-page: scrollWidth == innerWidth at 1280px and at phone width. | 0 | NULL | NULL | NULL | 0 | 2026-08-13T05:01:37Z | 0 | |||||||||||||||||||||
| sr-ht-dolt-44n.2 | 7609b97699f2d7865c8d81e2ef9d79f8a93eb2a8ca7b62075ea085ca7626e2d4 | Freshness line in the beads/milestones/memory header | Nothing on the board says how fresh it is: with a 30s auto-push debounce and a manual pull, a store that stopped receiving pushes yesterday renders identically to a current one. Add a shared beadsHead partial rendering "<branch> · last commit <relative> · <short hash>", the hash linking to the commit page, fed by a Head *browse.CommitInfo field on the handleView envelope so every view gets it without asking. | docs/DESIGN.views.md ch.3, ch.7. One Log(ctx, ref, "", 1) call. Needs the ago template func; absolute time in the title attribute. | A database with no commits renders the header without one rather than failing. | in_progress | 2 | task | NULL | NULL | 2026-08-12T20:11:48Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T05:18:22Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | 0 | NULL | NULL | NULL | 0 | 2026-08-13T05:18:22Z | 0 | ||||||||||||||||||||||
| sr-ht-dolt-44n.3 | 7ba664f882da02bf0a032cb7e237a7e829cace479e7bd3f7878c7726b24a9887 | browse: TableHash and the memory revision walk | A memory row is (key, value) with no timestamp, so a two-month-old note is indistinguishable from one written this morning. Recover the date from history: add browse.TableHash (root.GetTable then Table.HashOf — O(1), reads no rows) to browse/ and both BrowseSession seams, then walk the log newest-first, skipping every commit whose config table hash is unchanged and reading rows only at the boundaries, to attribute each kv.memory key to the commit that last changed it. | docs/DESIGN.views.md ch.2.1. Bound the walk at 500 commits (the most active tracker on this instance had 225 after three weeks, measured 2026-08-12 via dolt_log); an unresolved key renders "older than the last 500 commits" rather than a date the walk cannot support. The commit message is a claim; the table hash is the fact. | Fixture history where a key is written, changed, then left alone for several commits resolves to the changing commit; the not-found-within-walk arm is covered. | closed | 2 | task | NULL | NULL | 2026-08-12T20:11:49Z | Eugene Blikh | bigbes@gmail.com | 2026-08-12T20:18:34Z | 2026-08-12T20:18:34Z | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | browse.TableHash landed in 97e0f8a (root.GetTable + Table.HashOf: covers schema, rows and secondary indexes, cheaper than GetRowDataHash). The revision walk itself, and adding TableHash to the BrowseSession seams, belong to the Memory view and are specified in docs/DESIGN.views.md ch.2.1 — tracked on sr-ht-dolt-b08. | 0 | NULL | NULL | NULL | 0 | 2026-08-12T20:15:46Z | 0 | |||||||||||||||||||||
| sr-ht-dolt-44n.4 | 740c8403d3b42789698b44c736d7b2512d0e413c0bc926b035a56afed9182726 | Copy-ready bd commands on the issue detail pane | The page shows work and cannot change it — that is the architecture. Hand over the command instead: a small block under the issue header with the bd commands appropriate to its status (open: --claim, close; in progress: close, --status=open; closed: reopen), each line user-select: all so one click selects a whole command. | docs/DESIGN.views.md ch.6. No JavaScript and no clipboard API. The command names the issue and nothing about paths: this service does not know where the tracker is checked out, and guessing one would be inventing a fact about the reader machine. | The offered commands follow the issue status; nothing is offered that bd would refuse. | open | 3 | task | NULL | NULL | 2026-08-12T20:11:50Z | Eugene Blikh | bigbes@gmail.com | 2026-08-12T20:11:50Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | 0 | NULL | NULL | NULL | 0 | NULL | 0 | ||||||||||||||||||||||
| sr-ht-dolt-44n.5 | b094d41863ae456425aa8ab3ff458192890cfd4439196ad6523e1ae52cebdcdd | /ready: the cross-database ready page | Seventeen databases on this instance carry the beads fingerprint, and "what is ready to work" is answerable in each and nowhere across them. Add GET /ready (a page, not a View): for every database the caller may browse, check the fingerprint and collect the ready set through the shared beads/ rule, grouped by database. Filters: q, assignee, priority, db. | docs/DESIGN.views.md ch.4. Bounded three ways: a per-database cache keyed by (repoID, head hash) so an unmoved head reads no rows, a 60s TTL, and a 64-database ceiling that the page reports when hit. The cache holds projections, never open browse handles. The aggregator is the one /mcp ready_work calls. | A PRIVATE tracker the caller may not browse is absent rather than 403; a second request with unmoved heads performs no row reads; the ceiling reports itself. | open | 2 | task | NULL | NULL | 2026-08-12T20:11:50Z | Eugene Blikh | bigbes@gmail.com | 2026-08-12T20:11:50Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | 0 | NULL | NULL | NULL | 0 | NULL | 1 | ||||||||||||||||||||||
| sr-ht-dolt-44n.6 | aad9c553cb6022751a8410ca2f3b0f3a9d6aa286508eb7d565cff42b301b5194 | Cross-database issue links in rendered text | A global-tracker issue naming artifacts-nex.2 is pointing at a row in another database, and the reader has to find it by hand. Recognise <prefix>-<suffix> in descriptions, design, acceptance criteria, notes, comments and event summaries, and link those whose prefix belongs to a database the caller may browse — prefixes come from each tracker config.issue_prefix, indexed on the same head-hash/TTL basis as /ready. | docs/DESIGN.views.md ch.5. Escape first, then wrap the matches, and only then mark the result template.HTML: marking stored text as HTML and running a regexp over it is how a stored payload becomes a rendered one. A prefix in a database the caller cannot see is not linked and its existence is not revealed. | An id in a visible database links, one in an invisible database renders as plain text, <script> in a description stays escaped, an unknown prefix is left alone. | open | 3 | task | NULL | NULL | 2026-08-12T20:11:51Z | Eugene Blikh | bigbes@gmail.com | 2026-08-12T20:11:51Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | 0 | NULL | NULL | NULL | 0 | NULL | 1 | ||||||||||||||||||||||
| sr-ht-dolt-7ta | 545df5bee637c3deb329ede8bcf297fe7cd1e3b36ad880466d8833fd53e0d9ee | The overview page echoes a raw browse error to the reader | web/handlers_repo.go renders the browse layer's error text into the overview page. Those strings carry dolt internals and on-disk paths, which nothing else on this surface discloses. Noticed while writing the MCP surface (dcdc979), which is careful never to let a store error reach a caller verbatim. | The page shows a fixed sentence; the detail goes to the log with the repo id. | open | 3 | bug | NULL | NULL | 2026-08-13T05:24:30Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T05:24:30Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | 0 | NULL | NULL | NULL | 0 | NULL | 0 | |||||||||||||||||||||||
| sr-ht-dolt-b08 | 6314ccc71fe7047ad5a1bafc0067c236a442b3cb98c13b163cf596471ce52b2e | Memory view: surface bd memories kept in the config table | `bd remember` stores agent memories in the beads `config` table as ordinary key/value rows: the key is `kv.memory.<slug>`, the value is the memory text. Today they are reachable only through the generic table browser, mixed in with the tracker's tuning knobs (`compact_*`, `issue_prefix`, ...), and every memory is squeezed into a single table cell — which is unreadable for the multi-line handoff notes that make up most of them. Give them their own view, registered the same way Beads and Milestones are: a separate `View` implementation whose tab appears next to them for any beads DB. | Shape it on web/milestones.go, which is the smallest existing companion view: - `web/memory.go`: `memoryView` registered from `init()` via `RegisterView`. `Name() == "memory"`, `Label() == "Memory"`, `Template() == "memory.html"`. - `Applies`: the beads fingerprint (reuse `(&beadsView{}).Applies`, as milestones does) plus a `config` table carrying `key` and `value` columns. `Applies` only sees table shapes, never rows, so a beads DB with no memories still gets the tab and renders an empty state — same contract milestones has. - `Build`: read `config` through `readRowsOptional`, keep rows whose key has the `kv.memory.` prefix, strip it for the display slug, sort by slug. Optional `?q=` substring filter over slug + text, and `?key=<slug>` for a single-memory detail, both parsed from the query values Build already receives. - Values are stored as written, so they carry both real newlines and literal `\n` two-character escapes (agents type them into shell strings). Normalise both into paragraphs before rendering rather than dumping one blob. - `web/templates/memory.html`: same flat todo.sr.ht idiom and inlined `<style>` block as milestones.html, with the `viewtabs` partial and `"Current" "memory"`. - Tests next to `web/milestones_test.go`: fingerprint accept/reject, prefix filtering (a `compact_batch_size` row must not show up), escape handling, filter and detail modes, empty state. | A beads DB shows a Memory tab beside Beads and Milestones; it lists every kv.memory.* config row as a readable, multi-paragraph entry keyed by its slug; non-memory config rows never appear; a DB with no memories renders an empty state instead of a broken tab. | Owns the revision walk (docs/DESIGN.views.md ch.2.1) now that browse.TableHash exists (97e0f8a): add TableHash to web/deps.go BrowseSession (and mcpsrv/ports.go if that seam exists by then), walk the log newest-first skipping commits whose config table hash is unchanged, cap the walk at 500 commits, render 'older than the last 500 commits' when a key does not resolve. browse/ tests are stdlib style, not testify — new browse-side tests live in their own file if any are needed. | open | 2 | feature | NULL | NULL | 2026-08-10T11:01:48Z | Eugene Blikh | bigbes@gmail.com | 2026-08-12T20:18:41Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | 0 | NULL | NULL | NULL | 0 | NULL | 1 | |||||||||||||||||||||
| sr-ht-dolt-m63 | 01bf9d94009de75026c5dc23458e4967ef854881497fdcd59aa564926713fdb4 | db: enumerate the databases a caller may list across owners | There is no instance-wide listing query today: db/repos.go has ListReposByOwner(owner, viewer) (the listing rule, anonymity included) and ListReposForDashboard(userID) (owned or ACL'd), and nothing that answers "every database this caller may list". Two consumers need exactly that: mcpsrv list_databases had to take an optional owner and refuse anonymous+no-owner rather than state something false about the instance (dcdc979), and the cross-database ready page cannot find the beads trackers without it. | Add the query to db/repos.go next to its two siblings, spelled with the same listing rule ListReposByOwner documents: PUBLIC to everyone, plus anything the viewer owns or holds an ACL entry on; UNLISTED and PRIVATE never listed to a stranger. Then widen mcpsrv.Repos and web's RepoStore seam to it. | A table-driven db test over PUBLIC/UNLISTED/PRIVATE x anonymous/stranger/grantee/owner; list_databases with no owner answers the caller-wide listing instead of refusing. | open | 2 | task | NULL | NULL | 2026-08-13T05:24:22Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T05:24:22Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | 0 | NULL | NULL | NULL | 0 | NULL | 0 | ||||||||||||||||||||||
| sr-ht-dolt-q8c | fe29b47daedc5dce09cbfa18c650a1c65b785e22d4f0d6f06f59e2d3d5b8c430 | loadRepoForBrowse reports a database outage as a missing database | web/router.go loadRepoForBrowse treats ANY error from GetRepoByOwnerAndName as not-found, so a Postgres outage renders the 404 page — a reader is told their database does not exist when the truth is that the service cannot answer right now. Found while writing mcpsrv/errors.go (dcdc979), which deliberately does not copy the conflation, so the two surfaces now differ on this one point. | Distinguish db.ErrNotFound from every other error: the sentinel keeps the existing 404 (and the PRIVATE masking that depends on it), anything else is a 500 through a.fail. The masking rule is untouched — a private database must still be indistinguishable from a missing one. | A fake store returning a non-sentinel error renders 500, not 404; the PRIVATE-masking tests stay green. | open | 2 | bug | NULL | NULL | 2026-08-13T05:24:29Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T05:24:29Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | 0 | NULL | NULL | NULL | 0 | NULL | 0 |