3b12jq29j2urdlg4lqlss34kf4kqc41o · 34 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-0df | 0c716954c4783ebf0507ecd5bb1c7602f17a83be2759160610f250d38002bcfb | A stored "NULL" string is indistinguishable from a real NULL | browse renders a real NULL cell as the literal string "NULL" (placeholderNull), so a row that genuinely stores the text NULL reads identically. beads.cell() then flattens both to the empty string. Harmless on a rendered page, misleading through the MCP read_rows tool, where an agent gets strings and no schema hint (7a77409 states it in the tool description rather than papering over it). | Options, cheapest first: keep the placeholder for the HTML pages and give RowPage a parallel per-cell null mask that read_rows exposes; or render JSON null through the tool path. Whatever is chosen, the beads projection must keep treating a real NULL as empty — that behaviour is depended on. | closed | 3 | bug | NULL | NULL | 2026-08-13T05:46:26Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T07:11:43Z | 2026-08-13T07:11:43Z | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | browse half landed in 5b00a51: RowPage.Nulls parallel to Rows, filled from the td.IsNull the renderer already called (no extra tuple read). Rendered strings unchanged, so every existing consumer keeps reading what it read. Mutation-checked by making the mask believe the rendered string. Adoption by mcpsrv and beads is sr-ht-dolt-3s9. | 0 | NULL | NULL | NULL | 0 | 2026-08-13T07:06:40Z | 0 | ||||||||||||||||||||||
| 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. | closed | 1 | epic | NULL | NULL | 2026-08-12T20:10:04Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T07:07:08Z | 2026-08-13T07:07:08Z | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | All eight tasks landed: the beads/ extraction, the bearer plane, the mcpsrv skeleton, the generic tools, the beads tools, the daemon wiring, list_memories and ready_work. docs/DESIGN.mcp.md is implemented end to end. | 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. | closed | 1 | task | NULL | NULL | 2026-08-12T20:11:37Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T06:05:35Z | 2026-08-13T06:05:35Z | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | Landed in f9c82b0 (pure move: 77 PASS lines preserved, the sorted set of test names byte-identical to the baseline) plus 7d799ed, which dropped the Bead/Beads prefix from the moved types before any consumer existed. | 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. | closed | 1 | task | NULL | NULL | 2026-08-12T20:11:44Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T05:24:51Z | 2026-08-13T05:24:51Z | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | Landed in dcdc979: stateless streamable transport, Host allowlist replacing the SDK rebinding guard, bearer middleware with the 401/403/503 split, grant gate on core.GrantRead, seams in ports.go, list_databases. 59 tests; the identity matrix was verified to FAIL under stateless=false before being reverted. | 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. | closed | 2 | task | NULL | NULL | 2026-08-12T20:11:45Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T05:46:43Z | 2026-08-13T05:46:43Z | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | Landed in 7a77409: list_branches, list_tables, read_rows, get_commit_log, get_commit_diff in mcpsrv/browse.go. Caps clamp and say so (limit echoes what was applied); a masked database and a missing one share a byte-identical sentence; a bad ref/table is a plain answer, not the mask. 176 tests, cap test mutation-checked. | 0 | NULL | NULL | NULL | 0 | 2026-08-13T05:27:34Z | 0 | |||||||||||||||||||||
| 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. | closed | 2 | task | NULL | NULL | 2026-08-12T20:11:46Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T06:05:35Z | 2026-08-13T06:05:35Z | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | Landed in e4bc922: list_issues, get_issue, list_milestones over beads.Build/BuildMilestones. The no-bodies rule is structural — the card JSON type has no field a body could arrive in, mutation-checked by adding an empty description field and watching the guard fire. A non-beads database gets an explanatory refusal distinguishable from both the mask and an internal error. 270 tests. | 0 | NULL | NULL | NULL | 0 | 2026-08-13T05:47:34Z | 0 | |||||||||||||||||||||
| 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. | closed | 2 | task | NULL | NULL | 2026-08-12T20:11:47Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T06:25:23Z | 2026-08-13T06:25:23Z | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | Landed in 57adcc0: /mcp mounted on the web listener before web.Register and outside its CSRF group, bearer validator from [tokens.sr.ht] (absent = nil validator, daemon boots, working tokens refused), config.example.ini and README documented, authn/ctx.go now names four flows. Measured: anonymous tools/list POST to /mcp = 200 even with a foreign Origin; a cross-origin POST to /create = 403. | 0 | NULL | NULL | NULL | 0 | 2026-08-13T06:07:15Z | 0 | ||||||||||||||||||||
| 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. | closed | 3 | task | NULL | NULL | 2026-08-12T20:11:52Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T06:44:15Z | 2026-08-13T06:44:15Z | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | Landed in 4038ec2: ready_work with both arms over the shared beads.ReadyCache (one per server, built in New). The arms are proved to agree by decoding both answers and comparing the whole group struct. Two mutation checks: a per-call cache reddens the head-hash-gate test with counted reads, and disabling core.Allowed reddens the access-rule test. | 0 | NULL | NULL | NULL | 0 | 2026-08-13T06:27:32Z | 0 | |||||||||||||||||||||
| sr-ht-dolt-0qf.8 | 1c93d2f307eb4417b5d5370df5995025d716ffb0161f23f679c44519dbb23cde | mcpsrv: list_memories over the shared memory projection | The MCP beads tools ship without list_memories because the memory projection and its revision walk are landing in beads/ under sr-ht-dolt-b08 at the same time. Add the tool once that API exists: slug, text, and the revision each memory was last written at, with an optional q substring filter — the same reading the Memory view renders, not a second one. | docs/DESIGN.mcp.md §9.2. Share beads/ with the web view; the walk is bounded there and this surface inherits the bound rather than restating it. | closed | 2 | task | NULL | NULL | 2026-08-13T05:46:27Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T06:25:30Z | 2026-08-13T06:25:30Z | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | Landed in dba72f5: list_memories over beads.BuildMemories. An unresolved revision is JSON null beside a null age_days, never a zero-valued object (mutation-checked); staleness carried three ways so the threshold is visible. 302 tests. | 0 | NULL | NULL | NULL | 0 | 2026-08-13T06:07:21Z | 0 | ||||||||||||||||||||||
| sr-ht-dolt-0qf.9 | de3c132a24997feef8b797370c5c91f3fa20b518a05f408efaa08eb32e7ddc34 | mcpsrv: carry the per-table clip list on list_issues | The web board now names every clipped table it draws from and what each clip costs (beads.Data.Clipped, commit 96b5e53). mcpsrv list_issues still reports only data.Truncated as table_truncated, so an MCP client sees nothing about a clipped labels or custom_statuses read — the same blind spot the board just lost. Data.Clipped is already there to be carried. | closed | 3 | task | NULL | NULL | 2026-08-13T08:12:18Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T08:22:57Z | 2026-08-13T08:22:57Z | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | Landed in 07c2a63: list_issues carries clipped[] with table/shown/total/effect, empty list rather than null on a complete read. The agent added a dedicated fixture instead of growing the shared bulk one (whose exact counts other tests assert), which also isolates the case that matters: a labels-only clip fires 'clipped' while table_truncated stays false. | 0 | NULL | NULL | NULL | 0 | 2026-08-13T08:14:38Z | 0 | |||||||||||||||||||||||
| 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. | closed | 2 | feature | NULL | NULL | 2026-08-10T11:13:36Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T08:27:44Z | 2026-08-13T08:27:44Z | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | Landed in 60fdb6d: beads.RawTable/RawRow/RawCell carried in detail and epic mode, rendered as a collapsed <details> section. The three states (absent / stored "NULL" / empty) are three distinct renderings, and rowCells.isNull became the single site deciding whether a cell holds a value, so the raw view cannot drift from the fields. Linkification deliberately NOT applied — a rewritten value is not the stored value — and a test proves that is a choice, not a broken linkifier. | 0 | NULL | NULL | NULL | 0 | 2026-08-13T08:14:30Z | 0 | |||||||||||||||||||||
| sr-ht-dolt-2wo | a033adbfe134dfe67605d81f37366dc2f9160455e78098614617bb45320d2d91 | The detail and milestone projections drop the truncation signal | beads.Build's detail branch never sets Data.Truncated and BuildMilestones discards the table totals with _, so on a tracker larger than beads.Max (2000 rows) an id in the tail reads as simply absent and a milestone rollup is computed over the first 2000 rows — with nothing saying so. The board path does report its clip; these two do not. Found while building the MCP get_issue and list_milestones tools (e4bc922), which cannot detect it without a second row read and state the limitation in a package comment instead. | Return the totals from those two entry points the way the board path already does, and let both surfaces render them. The alternative — each surface re-reading to check — is the second reading of the schema the beads package exists to prevent. | A fixture tracker past the cap: get_issue on a tail id says the read was clipped rather than claiming the issue does not exist; a milestone rollup over a clipped read is marked. | closed | 2 | bug | NULL | NULL | 2026-08-13T06:05:05Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T07:17:39Z | 2026-08-13T07:17:39Z | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | Landed in ebbd30f: Truncated/ShownOf are now set in every mode (no new fields, no changed meanings), plus IssuesClipped/Missing/MissingBeyondCap so a surface can tell 'no such issue' from 'not in the rows I read'. Fixture clips through a seam that honours limit rather than lowering Max. | 0 | NULL | NULL | NULL | 0 | 2026-08-13T07:08:28Z | 0 | |||||||||||||||||||||
| sr-ht-dolt-3s9 | dce98d223440919c25ba0e8e76711bd6f573a359b6c581ba922a0b73f56fd3fc | Adopt browse's NULL mask in the readers | Once browse can say which cells are actually NULL (sr-ht-dolt-0df), the readers should use it: mcpsrv read_rows should render a real NULL as JSON null instead of the string "NULL" and drop the warning from its tool description, and beads.cell() should keep treating a real NULL as empty while no longer flattening a stored "NULL" string to empty. The browse half is deliberately separate so the placeholder rendering the HTML pages depend on does not change under them. | closed | 3 | task | NULL | NULL | 2026-08-13T07:06:41Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T07:36:37Z | 2026-08-13T07:36:37Z | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | Landed in 6307350 (read_rows cells are [][]*string — a real NULL is JSON null on the wire, asserted on the marshalled payload; the description's warning removed) and c82f106 (beads rowCells binds a row to its mask, so cell() reads the mask and ~100 call sites did not move). A hand-built page with no mask keeps the older reading, documented and pinned rather than left implicit. | 0 | NULL | NULL | NULL | 0 | 2026-08-13T07:18:50Z | 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. | closed | 2 | epic | NULL | NULL | 2026-08-12T20:10:11Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T07:07:08Z | 2026-08-13T07:07:08Z | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | All six chapters of docs/DESIGN.views.md landed: the stream layout, the memory view with its revision walk, the freshness line, the /ready page, cross-database links and the copy-ready bd commands. | 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. | closed | 2 | task | NULL | NULL | 2026-08-12T20:11:48Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T05:28:23Z | 2026-08-13T05:28:23Z | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | Landed in 6459298: Head *browse.CommitInfo on the handleView envelope, the beadsHead partial, ago with a swappable clock. Empty history and a failing Log both degrade to no line and a 200 — the decoration can never be the reason a reader loses the board. | 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. | closed | 3 | task | NULL | NULL | 2026-08-12T20:11:50Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T05:39:13Z | 2026-08-13T05:39:13Z | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | Landed in 3b06523: status-following bd commands under the issue header, user-select: all per line, no JavaScript. Verified after the fact that 'bd reopen' exists and is the preferred spelling for a closed issue (its help says it is more explicit than 'update --status open' and emits a Reopened event), so the closed branch stands as written. | 0 | NULL | NULL | NULL | 0 | 2026-08-13T05:32:52Z | 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. | closed | 2 | task | NULL | NULL | 2026-08-12T20:11:50Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T06:44:08Z | 2026-08-13T06:44:08Z | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | Landed in 043b0fd: GET /ready over beads.ReadyAcross with the three bounds (head-hash gate, 60s TTL, 64-database ceiling), per-group freshness, filters. Mutation-checked by dropping the cache consultation and watching the read counters go 4->8. | 0 | NULL | NULL | NULL | 0 | 2026-08-13T05:55:14Z | 0 | |||||||||||||||||||||
| 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. | closed | 3 | task | NULL | NULL | 2026-08-12T20:11:51Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T07:07:07Z | 2026-08-13T07:07:07Z | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | Landed in dc91829: PrefixesAcross + PrefixIndex.Scan, escape-then-wrap rendering, the index bounded by the same projectionCache the ready page uses (ReadyCache was refactored onto it, so the numbers exist once). A database the caller may not browse is never opened and its ids render as plain text indistinguishable from an unknown prefix. An ambiguous prefix links to neither — a guess rendered as a fact is worse than plain text. | 0 | NULL | NULL | NULL | 0 | 2026-08-13T06:27:39Z | 0 | |||||||||||||||||||||
| sr-ht-dolt-4y6 | 5883109e90619d5dac3d0c721a5bfdb000b1c91bef5d21879ca9d247addadceb | The milestones page presents a partial rollup as whole-tracker arithmetic | web/templates/milestones.html renders MilestoneView with no clip notice, so on a tracker past the 2000-row cap the per-milestone totals read as facts about the whole tracker. beads reports the clip (ebbd30f) and the other two surfaces render it (82d997d, a419499); this is the third and last one. | closed | 3 | bug | NULL | NULL | 2026-08-13T07:57:01Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T08:12:17Z | 2026-08-13T08:12:17Z | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | Landed in bbaaa1f: the detail pane's sentence and markup verbatim, placed outside the milestones/no-milestones branch — 'No milestones.' over a clipped read is the reading most easily mistaken for a fact. | 0 | NULL | NULL | NULL | 0 | 2026-08-13T07:58:03Z | 0 | |||||||||||||||||||||||
| sr-ht-dolt-5s7 | 013f271f2040f96efdc45e4c0a9e0aa074805cd0a5e3392d06cc14a5e77c99b0 | Rename a database from its settings page | Owners can change a database's description and visibility but not its name; the only way to rename today is delete + recreate + re-push, which loses the ACLs and the history. Add a rename action: move the metadata row (name + path, both unique) and the on-disk NBS store together, evicting the served handle for the old path. | Owner-only rename form on /~user/db/settings; name validated with core.ValidateName; a collision answers 409 and changes nothing; the row and the store dir move together (row rolled back if the move fails); the cached remotesapi handle for the old path is evicted; the browser lands on the renamed database. | in_progress | 2 | feature | Eugene Blikh | NULL | 2026-08-15T08:35:07Z | Eugene Blikh | bigbes@gmail.com | 2026-08-15T08:35:21Z | NULL | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | 0 | NULL | NULL | NULL | 0 | 2026-08-15T08:35:21Z | 0 | |||||||||||||||||||||||
| sr-ht-dolt-5yw | be8e59de82460303f6bd9a46ea35a180588591706ffee95ef79617e39cfa315c | A bad commit-log cursor is reported without naming the cursor | In mcpsrv get_commit_log, when from is set the ref is never resolved (it is only resolved when from is empty), so the miss message reads: ~alice/notes has no branch or commit "" — it names an empty string instead of the cursor the caller actually sent. The classification is right (an ordinary miss since cdb9195); the sentence is unhelpful. Found while pinning that classification. | Name what was actually asked for: when from is set, the miss is about the cursor, not about a branch. Two different sentences, or one that carries whichever value was supplied. | closed | 3 | bug | NULL | NULL | 2026-08-13T07:10:11Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T07:16:04Z | 2026-08-13T07:16:04Z | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | Landed in c1d1a17: a cursor miss gets its own sentence naming the cursor and pointing at the 'next' hash a previous page returned; a ref miss keeps naming the ref and pointing at list_branches. The ref is still not resolved just to have something to print. | 0 | NULL | NULL | NULL | 0 | 2026-08-13T07:12:43Z | 0 | ||||||||||||||||||||||
| 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. | closed | 3 | bug | NULL | NULL | 2026-08-13T05:24:30Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T07:19:41Z | 2026-08-13T07:19:41Z | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | Landed in 11c622f: the overview carries a bool, not an error string, so no browse text can reach the dot; the page says 'Could not read history.' and the detail goes to the log with the database id. The empty-database state (No commits./No branches.) was kept — it was never the error path. | 0 | NULL | NULL | NULL | 0 | 2026-08-13T07:08:28Z | 0 | ||||||||||||||||||||||
| sr-ht-dolt-9c6 | 771e917e7a1f542d45b988a524089b9b8035acd0dbd0b2f57120017b67ed04ef | The settings POST writes store paths into the response | web/handlers_settings.go:201,206 responds with "database record removed but store deletion failed: "+err.Error() and "store deleted but cache eviction failed: "+err.Error(). That is the same leak 11c622f removed from the overview, one path along: the browse/storage error text carries on-disk paths, and the owner is shown them. Found while fixing the overview. | Same shape as 11c622f: a fixed sentence to the reader, the detail to slog with the database id. The distinction that matters to the owner — the record is gone but the store may not be — should survive in the sentence without the path. | closed | 3 | bug | NULL | NULL | 2026-08-13T07:19:41Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T07:26:37Z | 2026-08-13T07:26:37Z | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | Landed in 35875ff: two fixed sentences that keep the distinction the owner needs (record gone but store may remain / store gone but a cached handle may survive), detail to slog with the database id. The agent also checked handlers_keys.go and left its 'Invalid public key: <err>' alone — those errors describe the caller's own submitted string, not the storage layer, which is a different class. | 0 | NULL | NULL | NULL | 0 | 2026-08-13T07:21:10Z | 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, walk the log newest-first skipping commits whose config table hash is unchanged, cap at 500 commits, render 'older than the last 500 commits' when a key does not resolve. The 'ago' func landed in 6459298 with chrome's unit ladder: it says '2 months ago' where ch.2.2's mockup wants 'written 71 days ago'. For judging staleness days are the informative unit, so this view needs a day-resolution spelling of its own rather than a change to 'ago' (which is shared with the freshness line). | closed | 2 | feature | NULL | NULL | 2026-08-10T11:01:48Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T05:53:37Z | 2026-08-13T05:53:37Z | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | Landed in 231b776: beads.BuildMemories with the bounded revision walk, the memory View after Milestones, agoDays for day-resolution staleness, stale? at 60 days. The walk was proven to skip rather than read (reads recorded at three refs out of five commits; 501 untouched commits cost one read). Real-data smoke: sourcehut-artifacts 9 memories attributed to distinct commits in 16.5 ms. Follow-up 0190aab replaced the init-order trick with an explicit registration list in views.go. | 0 | NULL | NULL | NULL | 0 | NULL | 0 | ||||||||||||||||||||
| sr-ht-dolt-bcp | f9946f3bc8095377e0620dd72e6d2d1aa8ab9d488b7cdfe2ff1249a206fda1ba | The ready, memory and prefix projections discard their row totals | beads/ready.go, beads/memory.go and beads/prefixes.go still drop the table totals with _, so a clipped read is invisible in the cross-database ready set, in the memory list and in the prefix index. Same shape as ebbd30f fixed for the detail and milestone paths; each has its own view struct, so each needs its own field rather than a shared one (ReadyView.Capped is a different cap — it counts databases). | closed | 4 | bug | NULL | NULL | 2026-08-13T07:17:47Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T07:49:39Z | 2026-08-13T07:49:39Z | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | Landed in 8dfe078: per-database ReadyTruncation (recorded BEFORE the empty-group skip, so a tracker whose whole ready set sits past the cap is still named, and surviving a cache hit — both pinned), MemoryView.ConfigTruncated/ConfigShownOf named after the table so they cannot be confused with WalkTruncated (a bound in commits), PrefixIndex.Truncated. Minor known duplication: readyRead mirrors build.go's readClip because the file boundary I set forbade widening the latter's doc comment. | 0 | NULL | NULL | NULL | 0 | 2026-08-13T07:38:29Z | 0 | |||||||||||||||||||||||
| sr-ht-dolt-djw | f4cc5b3208357590da32454d921be996c703f6fd12be9dbc63ee0114111dbb42 | Render the clipped-read signal on the two surfaces | beads now reports a clipped read from the detail and milestone projections (ebbd30f) and can tell "not in what was read" from "does not exist" (Data.MissingBeyondCap). Nothing renders it yet: mcpsrv get_issue still answers a tail id with the flat noSuchIssue sentence, and the web detail pane draws no banner (the board banner is inside the board branch). Both should say the read was partial rather than claim absence. | closed | 3 | task | NULL | NULL | 2026-08-13T07:17:46Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T07:56:54Z | 2026-08-13T07:56:54Z | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | Landed in a419499 (mcpsrv: get_issue answers issue:null with table_truncated/table_total for an id past the cap, and the two misses are told apart by the payload rather than by prose — the ordinary miss carries no structured content at all) and 82d997d (the web detail pane says the read was clipped, and the miss says the id may sit in the tail this page never saw). Spec amended in the follow-up commit. | 0 | NULL | NULL | NULL | 0 | 2026-08-13T07:38:21Z | 0 | |||||||||||||||||||||||
| 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. | closed | 2 | task | NULL | NULL | 2026-08-13T05:24:22Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T05:31:43Z | 2026-08-13T05:31:43Z | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | Landed in e6125fc: ListReposForViewer — ListReposByOwner's predicate minus the owner filter, anonymity spelled as viewer id 0 (unsatisfiable in both non-PUBLIC branches). Matrix asserts exact ordered listings for anonymous/stranger/grantee/both owners; mutation-checked. | 0 | NULL | NULL | NULL | 0 | 2026-08-13T05:27:41Z | 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. | closed | 2 | bug | NULL | NULL | 2026-08-13T05:24:29Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T07:19:34Z | 2026-08-13T07:19:34Z | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | Landed in bee2050: repoLookupFailed splits db.ErrNotFound (404, masking untouched) from every other error (500, detail logged and never rendered). The same conflation in loadRepoForAdmin was fixed with it. Mutation check: routing the PRIVATE arm through the 500 path reddens three masking tests. | 0 | NULL | NULL | NULL | 0 | 2026-08-13T07:08:20Z | 0 | |||||||||||||||||||||
| sr-ht-dolt-tci | a5b3bd37012658f7317a5085993430f2a209f6a80b8ae8811962d6e3cfd71ba4 | mcpsrv: the get_commit_log cursor comment is now stale | mcpsrv/browse.go:527 says browse classifies an unparseable from-hash as a fault of its own "(it has no sentinel for it)", so a hand-written cursor takes the protocol arm. That stopped being true in 2c8903f: browse.Log now wraps it in ErrRefNotFound, and the call already routes through refMiss, so the behaviour is already right — only the comment is wrong. Fix the comment and add the test that pins the new behaviour (a garbage cursor is a tool-result miss, not an internal error). | A comment next to code is a claim, and this one now reads as a limitation the code no longer has. | closed | 3 | task | NULL | NULL | 2026-08-13T06:35:06Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T07:10:04Z | 2026-08-13T07:10:04Z | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | Landed in cdb9195. The agent also found the mcpsrv fake itself was wrong — its Log returned an unwrapped error for a bad cursor, i.e. it reproduced the very bug the stale comment described, so the comment fix alone would not have made the new test pass. | 0 | NULL | NULL | NULL | 0 | 2026-08-13T07:06:29Z | 0 | ||||||||||||||||||||||
| sr-ht-dolt-ux7 | 4b1926735da5ca79103be3182a885d250e69d467de48e359793621e66cb29728 | browse.Log reports an unparseable start hash as an internal failure | browse.Log classifies a from-hash that is not a parseable dolt hash with a plain fmt.Errorf and has no sentinel for it, so a caller that hands over a mistyped cursor is told the service broke rather than that the ref does not exist. Found while building the MCP get_commit_log cursor (7a77409): mcpsrv cannot classify it without parsing a hash format that browse/ owns, so the fix belongs in browse/. | Wrap the MaybeParse arm of Log in ErrRefNotFound, the sentinel the package already uses for "this ref names nothing". mcpsrv then answers it as the ordinary miss it is, through the refMiss classifier that already exists. | browse test: a garbage from-hash returns an error satisfying errors.Is(err, ErrRefNotFound); the MCP tool answers it as a miss rather than an internal error. | closed | 3 | bug | NULL | NULL | 2026-08-13T05:46:20Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T06:35:00Z | 2026-08-13T06:35:00Z | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | Landed in 2c8903f: the MaybeParse arm plus two more the agent found by testing rather than inspection — a well-formed but nonexistent from-hash reaching the topological iterator, and the same shape in resolveCommit — all wrapped in ErrRefNotFound via datas.ErrCommitNotFound. Genuine failures stay unwrapped, so 'not there' and 'could not answer' remain distinguishable. | 0 | NULL | NULL | NULL | 0 | 2026-08-13T06:27:39Z | 0 | |||||||||||||||||||||
| sr-ht-dolt-xsc | 434e870e68beb866ff78324b80edf5e757977794d577a8b7851b7eeca021da92 | A clipped labels table degrades the board silently | The board raises Truncated for a clipped issues or dependencies table, but a clipped labels table degrades every card and the label filter with nothing said. Noticed while making the other projections honest (ebbd30f), which deliberately left the board rule byte-for-byte unchanged and pinned it with a test. | closed | 3 | bug | NULL | NULL | 2026-08-13T07:17:46Z | Eugene Blikh | bigbes@gmail.com | 2026-08-13T08:12:10Z | 2026-08-13T08:12:10Z | NULL | 0 | NULL | NULL | NULL | 0 | 0 | 0 | �{} | Landed in 96b5e53: Data.Clipped []ClippedTable (table, shown, total, and the effect written at the read), board mode only. Truncated/ShownOf keep their exact meaning, so mcpsrv's table_truncated is untouched. The board now names each clipped table it draws from and what that costs; comments never appears because the board does not read it. One behaviour change beyond addition: the count line is gated on IssuesClipped, so a deps-only clip no longer prints 'the first 4 of 4 issues'. | 0 | NULL | NULL | NULL | 0 | 2026-08-13T07:57:56Z | 0 |