fix(store): reject empty observation titles before persistence#467
Open
tommanzur wants to merge 4 commits into
Open
fix(store): reject empty observation titles before persistence#467tommanzur wants to merge 4 commits into
tommanzur wants to merge 4 commits into
Conversation
Empty (or whitespace-only) titles passed to AddObservation were accepted locally but rejected by the cloud sync server (ValidateSyncMutationPayload), silently blocking the mutation queue. Validate at write time so the failure surfaces immediately and the caller gets actionable feedback. Closes Gentleman-Programming#459
Mirror the existing content check. The error message instructs the agent to provide a short, searchable title, since the previous silent success caused stuck cloud sync queues with no feedback loop. Refs Gentleman-Programming#459
Author
|
Thanks @ricardoarz-dev for the pointer to One note for a maintainer: I couldn't add the Happy to adjust the approach or split anything further if it helps review. |
Collaborator
|
#459 is now approved and this PR has the |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #459.
Empty (or whitespace-only) observation titles were accepted by
mem_saveandstore.AddObservation, persisted locally, and queued for cloud sync. The cloudserver rejects them via
ValidateSyncMutationPayload, blocking the entiremutation queue silently — the caller receives success at write time and has no
feedback to retry with a valid title.
This PR pushes the same validation up to the write path, so the failure
surfaces immediately and can be corrected.
Changes
internal/store/store.go:AddObservationrejects empty/whitespace titleswith a clear error, before any DB access. Validated after
stripPrivateTagsso it matches exactly the value that gets persisted and later pushed to the
cloud server.
internal/mcp/mcp.go:handleSavereturns an agent-actionableToolResultErrorbefore reaching the store, with an example title format sothe model knows what to provide on retry.
Why this approach
Per the suggestion on #459, reusing the rule already enforced by
ValidateSyncMutationPayload(diagnostic.go) keeps validation in one logicalplace. The fix is defensive at two layers — MCP for UX, store as the single
source of truth — so the CLI, MCP, and any future entrypoint inherit it.
Test plan
go test ./internal/store/...— new tests for empty/whitespace titles + a positive casego test ./internal/mcp/...— handler returnsToolResultError, nothing persistedgo build ./cmd/engram— binary builds cleanNotes
today, but those cases are already broken downstream (cloud sync blocks them).
The change turns a silent failure into a loud, immediate one.
stripPrivateTagsreplaces<private>…</private>with[REDACTED], not anempty string, so a title made only of private tags is not rejected — that
is intended.
Out of scope
repair tooling and the SQLite workaround documented in Reject empty observation titles before persistence #459's comments handle
that path. This PR prevents new occurrences.