feat(brain): add brain_reject — the missing third option for raw/ notes
CI / Lint / Test / Vet (pull_request) Successful in 45s
CI / Mirror to GitHub (pull_request) Skipped

hyperguild#81. brain_pending lists brain/raw/ notes awaiting review;
brain_promote moves one into the wiki. There was no way to say "reviewed,
not worth promoting" — the only options were promote it or let it sit
forever. Live consequence, confirmed this session: the pending queue has
grown to 11 items, the oldest 152 days old, several of which are generic
web scrapes nobody is ever going to promote but nobody could clear either
except an un-audited rm bypassing the tool surface entirely.

RejectNote (internal/api/promote.go) mirrors PromoteNote's exact safety
shape: same basename-only filename validation, same write-then-delete
ordering (the source survives any write failure), same collision check
(never silently overwrite an existing rejected note under the same
name). Stamps rejected_at (+ reject_reason if given) into frontmatter,
moves brain/raw/<filename> -> brain/raw/rejected/<filename>. No index
rebuild or auto-tunnel -- a rejected note never entered the wiki, so
there's nothing to index. raw/rejected/ is a subdirectory ListPending's
non-recursive os.ReadDir never walks into, so a rejected note is never
re-surfaced as pending -- the human decision, once made, stays made.

brain_reject wired into the MCP tool list and dispatch, mirroring
brain_promote's schema shape (filename required, reason optional).
Human-invoked only, same as promote -- never called automatically.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-23 07:59:43 +02:00
co-authored by Claude Sonnet 5
parent 9a37881441
commit 2d5bed1e90
6 changed files with 210 additions and 1 deletions
+1 -1
View File
@@ -58,7 +58,7 @@ func TestServerToolsList(t *testing.T) {
}
assert.ElementsMatch(t, []string{
"brain_query", "brain_write", "brain_update", "brain_get",
"brain_pending", "brain_promote",
"brain_pending", "brain_promote", "brain_reject",
"brain_read", "brain_edit",
"brain_tunnel",
"brain_ingest_raw", "brain_ingest",