main · last commit
6 hours ago ·
ti41arbu
sr-ht-dolt-b08 Memory view: surface bd memories kept in the config table
Past Stand
bd reopen sr-ht-dolt-b08
| Created by | Eugene Blikh |
| Owner | bigbes@gmail.com |
| Created | 2026-08-10T11:01:48Z |
| Updated | 2026-08-13T05:53:37Z |
| Closed | 2026-08-13T05:53:37Z |
`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).
sr-ht-dolt-44n.2
— Freshness line in the beads/milestones/memory header
blocks
closed
sr-ht-dolt-44n
— Beads views, round two: stream, memory, freshness, cross-database
parent-child
closed
sr-ht-dolt-44n.3
— browse: TableHash and the memory revision walk
blocks
closed
sr-ht-dolt-0qf.8
— mcpsrv: list_memories over the shared memory projection
blocks
sr-ht-dolt-44n.2
— Freshness line in the beads/milestones/memory header
blocks
closed
sr-ht-dolt-44n
— Beads views, round two: stream, memory, freshness, cross-database
parent-child
closed
sr-ht-dolt-44n.3
— browse: TableHash and the memory revision walk
blocks
closed
| id | sr-ht-dolt-b08 |
| content_hash | 6314ccc71fe7047ad5a1bafc0067c236a442b3cb98c13b163cf596471ce52b2e |
| title | Memory view: surface bd memories kept in the config table |
| description | `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. |
| design | 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. |
| acceptance_criteria | 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. |
| notes | 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). |
| status | closed |
| priority | 2 |
| issue_type | feature |
| assignee | NULL |
| estimated_minutes | NULL |
| created_at | 2026-08-10T11:01:48Z |
| created_by | Eugene Blikh |
| owner | bigbes@gmail.com |
| updated_at | 2026-08-13T05:53:37Z |
| closed_at | 2026-08-13T05:53:37Z |
| closed_by_session | |
| external_ref | NULL |
| spec_id | |
| compaction_level | 0 |
| compacted_at | NULL |
| compacted_at_commit | NULL |
| original_size | NULL |
| sender | |
| ephemeral | 0 |
| wisp_type | |
| pinned | 0 |
| is_template | 0 |
| mol_type | |
| work_type | |
| source_system | |
| metadata | �{} |
| source_repo | |
| close_reason | 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. |
| event_kind | |
| actor | |
| target | |
| payload | |
| await_type | |
| await_id | |
| timeout_ns | 0 |
| waiters | |
| hook_bead | |
| role_bead | |
| agent_state | |
| last_activity | NULL |
| role_type | |
| rig | |
| due_at | NULL |
| defer_until | NULL |
| no_history | 0 |
| started_at | NULL |
| is_blocked | 0 |
| id | 159d7664-c9ff-5503-8242-3d7633189c2a |
| issue_id | sr-ht-dolt-b08 |
| type | blocks |
| created_at | 2026-08-12T23:12:59Z |
| created_by | Eugene Blikh |
| metadata | �{} |
| thread_id | |
| depends_on_issue_id | sr-ht-dolt-44n.2 |
| depends_on_wisp_id | NULL |
| depends_on_external | NULL |
| id | 1f5dd9d1-f671-59f1-a3df-1acb27bdf38b |
| issue_id | sr-ht-dolt-b08 |
| type | parent-child |
| created_at | 2026-08-12T23:12:48Z |
| created_by | Eugene Blikh |
| metadata | �{} |
| thread_id | |
| depends_on_issue_id | sr-ht-dolt-44n |
| depends_on_wisp_id | NULL |
| depends_on_external | NULL |
| id | af40295d-d71d-5be8-bd2c-f43203cd220b |
| issue_id | sr-ht-dolt-0qf.8 |
| type | blocks |
| created_at | 2026-08-13T08:46:42Z |
| created_by | Eugene Blikh |
| metadata | �{} |
| thread_id | |
| depends_on_issue_id | sr-ht-dolt-b08 |
| depends_on_wisp_id | NULL |
| depends_on_external | NULL |
| id | bdc826cd-af62-5e04-aaa7-3e0e2a43f929 |
| issue_id | sr-ht-dolt-b08 |
| type | blocks |
| created_at | 2026-08-12T23:12:58Z |
| created_by | Eugene Blikh |
| metadata | �{} |
| thread_id | |
| depends_on_issue_id | sr-ht-dolt-44n.3 |
| depends_on_wisp_id | NULL |
| depends_on_external | NULL |
| id | 019feb55-f7ea-7a60-b82f-87ec2454dee2 |
| issue_id | sr-ht-dolt-b08 |
| event_type | created |
| actor | Eugene Blikh |
| old_value | |
| new_value | |
| comment | NULL |
| created_at | 2026-08-10T14:01:47Z |
| id | 019ff7a0-8706-7c9e-9c11-d2bb6d66b5b4 |
| issue_id | sr-ht-dolt-b08 |
| event_type | updated |
| actor | Eugene Blikh |
| old_value | {"id":"sr-ht-dolt-b08","title":"Memory view: surface bd memories kept in the config table","description":"`bd remember` stores agent memories in the beads `config` table as ordinary\nkey/value rows: the key is `kv.memory.\u003cslug\u003e`, the value is the memory text.\nToday they are reachable only through the generic table browser, mixed in with\nthe tracker's tuning knobs (`compact_*`, `issue_prefix`, ...), and every memory\nis squeezed into a single table cell — which is unreadable for the multi-line\nhandoff notes that make up most of them.\n\nGive them their own view, registered the same way Beads and Milestones are: a\nseparate `View` implementation whose tab appears next to them for any beads DB.\n","design":"Shape it on web/milestones.go, which is the smallest existing companion view:\n\n- `web/memory.go`: `memoryView` registered from `init()` via `RegisterView`.\n `Name() == \"memory\"`, `Label() == \"Memory\"`, `Template() == \"memory.html\"`.\n- `Applies`: the beads fingerprint (reuse `(\u0026beadsView{}).Applies`, as\n milestones does) plus a `config` table carrying `key` and `value` columns.\n `Applies` only sees table shapes, never rows, so a beads DB with no memories\n still gets the tab and renders an empty state — same contract milestones has.\n- `Build`: read `config` through `readRowsOptional`, keep rows whose key has the\n `kv.memory.` prefix, strip it for the display slug, sort by slug. Optional\n `?q=` substring filter over slug + text, and `?key=\u003cslug\u003e` for a single-memory\n detail, both parsed from the query values Build already receives.\n- Values are stored as written, so they carry both real newlines and literal\n `\\n` two-character escapes (agents type them into shell strings). Normalise\n both into paragraphs before rendering rather than dumping one blob.\n- `web/templates/memory.html`: same flat todo.sr.ht idiom and inlined\n `\u003cstyle\u003e` block as milestones.html, with the `viewtabs` partial and\n `\"Current\" \"memory\"`.\n- Tests next to `web/milestones_test.go`: fingerprint accept/reject, prefix\n filtering (a `compact_batch_size` row must not show up), escape handling,\n filter and detail modes, empty state.\n","acceptance_criteria":"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.","status":"open","priority":2,"issue_type":"feature","owner":"bigbes@gmail.com","created_at":"2026-08-10T11:01:48Z","created_by":"Eugene Blikh","updated_at":"2026-08-10T11:01:48Z"} |
| new_value | {"notes":"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."} |
| comment | NULL |
| created_at | 2026-08-12T23:18:40Z |
| id | 019ff997-b643-7d00-a48f-7bca66a19632 |
| issue_id | sr-ht-dolt-b08 |
| event_type | updated |
| actor | Eugene Blikh |
| old_value | {"id":"sr-ht-dolt-b08","title":"Memory view: surface bd memories kept in the config table","description":"`bd remember` stores agent memories in the beads `config` table as ordinary\nkey/value rows: the key is `kv.memory.\u003cslug\u003e`, the value is the memory text.\nToday they are reachable only through the generic table browser, mixed in with\nthe tracker's tuning knobs (`compact_*`, `issue_prefix`, ...), and every memory\nis squeezed into a single table cell — which is unreadable for the multi-line\nhandoff notes that make up most of them.\n\nGive them their own view, registered the same way Beads and Milestones are: a\nseparate `View` implementation whose tab appears next to them for any beads DB.\n","design":"Shape it on web/milestones.go, which is the smallest existing companion view:\n\n- `web/memory.go`: `memoryView` registered from `init()` via `RegisterView`.\n `Name() == \"memory\"`, `Label() == \"Memory\"`, `Template() == \"memory.html\"`.\n- `Applies`: the beads fingerprint (reuse `(\u0026beadsView{}).Applies`, as\n milestones does) plus a `config` table carrying `key` and `value` columns.\n `Applies` only sees table shapes, never rows, so a beads DB with no memories\n still gets the tab and renders an empty state — same contract milestones has.\n- `Build`: read `config` through `readRowsOptional`, keep rows whose key has the\n `kv.memory.` prefix, strip it for the display slug, sort by slug. Optional\n `?q=` substring filter over slug + text, and `?key=\u003cslug\u003e` for a single-memory\n detail, both parsed from the query values Build already receives.\n- Values are stored as written, so they carry both real newlines and literal\n `\\n` two-character escapes (agents type them into shell strings). Normalise\n both into paragraphs before rendering rather than dumping one blob.\n- `web/templates/memory.html`: same flat todo.sr.ht idiom and inlined\n `\u003cstyle\u003e` block as milestones.html, with the `viewtabs` partial and\n `\"Current\" \"memory\"`.\n- Tests next to `web/milestones_test.go`: fingerprint accept/reject, prefix\n filtering (a `compact_batch_size` row must not show up), escape handling,\n filter and detail modes, empty state.\n","acceptance_criteria":"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.","notes":"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.","status":"open","priority":2,"issue_type":"feature","owner":"bigbes@gmail.com","created_at":"2026-08-10T11:01:48Z","created_by":"Eugene Blikh","updated_at":"2026-08-12T20:18:41Z"} |
| new_value | {"notes":"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.\nThe '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)."} |
| comment | NULL |
| created_at | 2026-08-13T08:28:17Z |
| id | 019ff9ae-e7f9-7687-bead-7c487abc0047 |
| issue_id | sr-ht-dolt-b08 |
| event_type | closed |
| actor | Eugene Blikh |
| old_value | |
| new_value | 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. |
| comment | NULL |
| created_at | 2026-08-13T08:53:37Z |
No comments.
Close reason