Surface aging brain/raw/ pending notes instead of relying on someone remembering to check #82

Closed
opened 2026-07-15 09:45:35 +00:00 by mathias · 3 comments
Owner

Context

Follow-up to #81 (adds the mechanism to promote/reject a pending note —
this issue is about the missing trigger to actually look). Even with
brain_reject shipped, nothing prompts a review; the queue only gets checked
if someone happens to call brain_pending manually. That's exactly how the
4 real items sitting since 2026-04-23 went unnoticed for 3 months — the tool
existed the whole time, nobody had a reason to call it.

Same shape as brain-gardener#121 (surface resolved review issues via comment,
don't auto-close — the human still decides, but the system should be the one
that remembers to ask). Same principle applies one stage earlier here: the
system should prompt "these are aging," not require someone to remember the
queue exists.

Proposal

Options (pick one, don't over-build):

  1. ntfy digest, threshold-gated. A periodic (daily/weekly) check: any
    brain/raw/*.md older than N days (e.g. 14) fires an ntfy notification
    listing filenames + age, same pattern as brain-audit's existing severity-gated
    digest (fires only when something crosses the threshold, not every run —
    avoids confirmation-fatigue).
  2. Surface via brain_context. If a session's brain_context call already
    returns "prior decisions/corrections" for a project, cheaply also note "N
    pending brain/raw/ items, oldest Xd" so it surfaces in-session without a new
    scheduled job.
  3. Both — ntfy for the out-of-band nudge, brain_context for the in-session one.

Whichever: never auto-reject on age. Aging is a trigger to ask a human, not
a verdict — an old note might still be exactly right to promote once someone
looks. Mirrors the exact reasoning issue-status-derived-surfaced-not-closed
already settled for the tracker (2026-06-30, referenced in brain-gardener#121).

Acceptance

An aging pending note (>threshold days) is surfaced to Mathias without him
having to think to call brain_pending. No note is ever auto-rejected or
auto-promoted by this mechanism.

Related

  • #81 (parent — the reject capability this surfacing feeds into)
  • brain-gardener#121 (same surfaced-not-decided pattern, one layer over)
## Context Follow-up to #81 (adds the *mechanism* to promote/reject a pending note — this issue is about the missing *trigger* to actually look). Even with `brain_reject` shipped, nothing prompts a review; the queue only gets checked if someone happens to call `brain_pending` manually. That's exactly how the 4 real items sitting since 2026-04-23 went unnoticed for 3 months — the tool existed the whole time, nobody had a reason to call it. Same shape as brain-gardener#121 (surface resolved review issues via comment, don't auto-close — the human still decides, but the *system* should be the one that remembers to ask). Same principle applies one stage earlier here: the system should prompt "these are aging," not require someone to remember the queue exists. ## Proposal Options (pick one, don't over-build): 1. **ntfy digest, threshold-gated.** A periodic (daily/weekly) check: any `brain/raw/*.md` older than N days (e.g. 14) fires an ntfy notification listing filenames + age, same pattern as brain-audit's existing severity-gated digest (fires only when something crosses the threshold, not every run — avoids confirmation-fatigue). 2. **Surface via `brain_context`.** If a session's `brain_context` call already returns "prior decisions/corrections" for a project, cheaply also note "N pending brain/raw/ items, oldest Xd" so it surfaces in-session without a new scheduled job. 3. **Both** — ntfy for the out-of-band nudge, `brain_context` for the in-session one. Whichever: never auto-reject on age. Aging is a trigger to *ask a human*, not a verdict — an old note might still be exactly right to promote once someone looks. Mirrors the exact reasoning `issue-status-derived-surfaced-not-closed` already settled for the tracker (2026-06-30, referenced in brain-gardener#121). ## Acceptance An aging pending note (>threshold days) is surfaced to Mathias without him having to think to call `brain_pending`. No note is ever auto-rejected or auto-promoted by this mechanism. ## Related - #81 (parent — the reject capability this surfacing feeds into) - brain-gardener#121 (same surfaced-not-decided pattern, one layer over)
Author
Owner

Shipped option 2 — 3e537bd. task check green.

brain_context now returns a pending_review block when anything in brain/raw/ is older than 14 days:

{"pending": 4, "aging": 4, "oldest": "….md", "oldest_days": 117,
 "hint": "call brain_pending to review; nothing is promoted or rejected automatically"}

Why option 2 alone, not 1 or 3

The issue said pick one and don't over-build. Option 2 is the only one that adds no new thing to keep running — no scheduled job, no ntfy wiring, no threshold config to drift. It rides on a call sessions already make, which matches the diagnosis: the capability was never missing, the prompt was.

Option 1 stays worth doing if this proves too passive — a nudge only fires when a session calls brain_context, so a fortnight with no such session is a fortnight of silence. That is a real gap, and it is the one an ntfy digest closes. Worth knowing before adding it: this one costs nothing to keep, and a second channel firing on the same threshold is how notification fatigue starts.

Three things I made explicit that the issue implied

Threshold gates whether it speaks, not what it counts. Once something ages past 14 days it reports the whole queue — pending: 4, aging: 2. Someone opening the queue should see the queue, not a filtered slice of it.

Silence below the threshold is the feature. A block on every context call is one people learn to skip, which reproduces this exact failure with extra steps. Tests pin the silent cases first, before the reporting one.

It cannot decide. No promote, no reject, no reorder — and a test asserts the raw dir is byte-for-byte unchanged after a nudge, plus that the payload carries a hint rather than an action. That is issue-status-derived-surfaced-not-closed applied one stage earlier, as you noted.

Also: an unreadable raw/ degrades to silence rather than failing the call. brain_context is a hot path, and a broken review queue must not take project context down with it.

Verification honesty

Unit-tested end to end through brainContext itself, so the wiring is proven, not just the summary. What is not verified is the thing that actually matters — that you see it in a real session, since that depends on how each harness renders extra keys in a tool result. The four items from 2026-04-23 are still in the live queue and should trigger it on your next brain_context call; if they do not surface visibly, the gap is presentation, not detection, and that is worth a follow-up rather than a bigger threshold.

Leaving open until you have actually seen it fire. Related: #81 is the reject capability this feeds.

Shipped **option 2** — `3e537bd`. `task check` green. `brain_context` now returns a `pending_review` block when anything in `brain/raw/` is older than 14 days: ```json {"pending": 4, "aging": 4, "oldest": "….md", "oldest_days": 117, "hint": "call brain_pending to review; nothing is promoted or rejected automatically"} ``` ### Why option 2 alone, not 1 or 3 The issue said pick one and don't over-build. Option 2 is the only one that adds **no new thing to keep running** — no scheduled job, no ntfy wiring, no threshold config to drift. It rides on a call sessions already make, which matches the diagnosis: the capability was never missing, the prompt was. Option 1 stays worth doing if this proves too passive — a nudge only fires when a session calls `brain_context`, so a fortnight with no such session is a fortnight of silence. That is a real gap, and it is the one an ntfy digest closes. Worth knowing before adding it: this one costs nothing to keep, and a second channel firing on the same threshold is how notification fatigue starts. ### Three things I made explicit that the issue implied **Threshold gates whether it speaks, not what it counts.** Once something ages past 14 days it reports the whole queue — `pending: 4, aging: 2`. Someone opening the queue should see the queue, not a filtered slice of it. **Silence below the threshold is the feature.** A block on every context call is one people learn to skip, which reproduces this exact failure with extra steps. Tests pin the silent cases first, before the reporting one. **It cannot decide.** No promote, no reject, no reorder — and a test asserts the raw dir is byte-for-byte unchanged after a nudge, plus that the payload carries a *hint* rather than an action. That is `issue-status-derived-surfaced-not-closed` applied one stage earlier, as you noted. Also: an unreadable `raw/` degrades to silence rather than failing the call. `brain_context` is a hot path, and a broken review queue must not take project context down with it. ### Verification honesty Unit-tested end to end through `brainContext` itself, so the wiring is proven, not just the summary. What is not verified is the thing that actually matters — that **you** see it in a real session, since that depends on how each harness renders extra keys in a tool result. The four items from 2026-04-23 are still in the live queue and should trigger it on your next `brain_context` call; if they do not surface visibly, the gap is presentation, not detection, and that is worth a follow-up rather than a bigger threshold. Leaving open until you have actually seen it fire. Related: #81 is the reject capability this feeds.
mathias added the risk/lowsize/stype/feat labels 2026-08-27 05:25:42 +00:00
Author
Owner

Verified live in this session — the missing piece per the shipping comment (implementation done 2026-08-17, 3e537bd, left open pending confirmation the nudge actually renders in a real session).

brain_context call from this session returned:

"pending_review": {"pending": 11, "aging": 7, "oldest": "Using sentiment analysis to capture monetary policy decisions.md", "oldest_days": 152, "hint": "call brain_pending to review; nothing is promoted or rejected automatically"}

The queue has grown from the original 4 items to 11 (7 aging past the 14-day threshold) — the surfacing works exactly as designed, and separately confirms the underlying problem is real and ongoing (the oldest item is now 152 days old). Closing on this evidence; the growing queue itself is a separate concern for whoever reviews brain_pending next, not a gap in this mechanism.


Created via git-mcp on behalf of @mathias

Verified live in this session — the missing piece per the shipping comment (implementation done 2026-08-17, `3e537bd`, left open pending confirmation the nudge actually renders in a real session). `brain_context` call from this session returned: ```json "pending_review": {"pending": 11, "aging": 7, "oldest": "Using sentiment analysis to capture monetary policy decisions.md", "oldest_days": 152, "hint": "call brain_pending to review; nothing is promoted or rejected automatically"} ``` The queue has grown from the original 4 items to 11 (7 aging past the 14-day threshold) — the surfacing works exactly as designed, and separately confirms the underlying problem is real and ongoing (the oldest item is now 152 days old). Closing on this evidence; the growing queue itself is a separate concern for whoever reviews `brain_pending` next, not a gap in this mechanism. --- _Created via git-mcp on behalf of @mathias_
Author
Owner

Already shipped 2026-08-18 (commit 3e537bd, "feat(brain): surface an aging review queue in brain_context (#82)") — issue just never got closed alongside it.

Option 2 from this issue's own proposal was chosen: ingestion/internal/mcp/pending_nudge.go + wiring into tools_context.go. brain_context now returns a pending_review block ({pending, aging, oldest, oldest_days, hint}) whenever any raw/ note exceeds a 14-day threshold — silent below it, reports the whole queue once triggered. No auto-reject/auto-promote, matches this issue's acceptance criterion exactly.

Verified live on the corpus today (via #134's triage work): the mechanism correctly surfaced the aging queue (11 pending / 7 aging / oldest 152 days at the time), confirming both that it works and that the underlying problem it targets is real.

🤖 Generated with Claude Code


Created via git-mcp on behalf of @mathias

Already shipped 2026-08-18 (commit `3e537bd`, "feat(brain): surface an aging review queue in brain_context (#82)") — issue just never got closed alongside it. Option 2 from this issue's own proposal was chosen: `ingestion/internal/mcp/pending_nudge.go` + wiring into `tools_context.go`. `brain_context` now returns a `pending_review` block (`{pending, aging, oldest, oldest_days, hint}`) whenever any `raw/` note exceeds a 14-day threshold — silent below it, reports the whole queue once triggered. No auto-reject/auto-promote, matches this issue's acceptance criterion exactly. Verified live on the corpus today (via #134's triage work): the mechanism correctly surfaced the aging queue (11 pending / 7 aging / oldest 152 days at the time), confirming both that it works and that the underlying problem it targets is real. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- _Created via git-mcp on behalf of @mathias_
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mathias/hyperguild#82