The scheduled Update dependencies run fails in the Build and test Go step.
The error is "no such module: fts5", because the tests run without the fts5 tag.
ci.yaml already passes build-tags fts5 to go-pr.yaml.
This change passes the same tag to renovate-autoupdate.yaml.
- observation_update_test.go (#69) lacked the fts5 build tag its helper
(testObservationStore, in observation_store_test.go) has, so `go vet ./...`
without tags failed with "undefined: testObservationStore".
- Client.knn (#70) concatenates its WHERE clause into the query. The clause is
built only from constant text with "?" placeholders (see nearest) and every
value goes through args, so gosec's G202 is a false positive; annotate it the
way the file already annotates G201.
Co-authored-by: Claude Sonnet 5.5 <[email protected]>
After 30 minutes without a message the idle monitor closed stdin and expected the read loop to end. On a real, blocking stdin a read already in progress is not woken by closing the file, so the server lived on, the client's next message completed that read and the one after failed with 'read /dev/stdin: file already closed', which ended the connection mid-call.
The idle shutdown is now off by default (a stdio server lives as long as its client; orphans are still caught by the parent check). CLAUDE_MNEMONIC_MCP_IDLE_TIMEOUT (a Go duration) turns it on, and then it cancels the loop's context so Run returns nil instead of closing stdin.
Co-authored-by: Claude Sonnet 5.5 <[email protected]>
A project filter was '(project = ? OR scope = global)', which vec0 rejects in a nearest-neighbour query ('A LIMIT or k = ? constraint is required'). The only caller that passes a project is the de-duplication of new observations, which treats an error as 'insert', so semantic de-duplication never took effect.
Run one search for the project and one for global documents and merge them by distance without repeats, cut to the limit. QueryMultiField asks for enough field documents and keeps the best per observation; its two skipped tests are enabled. Because de-duplication now runs, canMergeInto skips a superseded or deleted note as a merge target.
Co-authored-by: Claude Sonnet 5.5 <[email protected]>
UpdateObservation set updated_at_epoch, but the observations table has no such column, so every PUT /api/observations/{id} failed with HTTP 500 (no such column: updated_at_epoch). Remove the assignment; nothing reads an edited-at time. An update that changes nothing now returns the observation, as intended. UpdateObservation had no tests: add store and handler tests.
Co-authored-by: Claude Sonnet 5.5 <[email protected]>
The vectors table is a vec0 virtual table, where INSERT OR REPLACE does not replace, so syncing a note that already had vectors failed with a UNIQUE constraint error and the edit never reached the index. AddDocuments also shadowed err inside its loop, so a failed insert left the write transaction open and later writes failed with 'database is locked'.
Add Client.ReplaceDocuments (delete and insert in one transaction) and use it from SyncObservation and SyncSummary. The shared write function has a named result, so every failed return rolls back. Fixes#66.
Co-authored-by: Claude Sonnet 5.5 <[email protected]>
The Renovate branch changed ui/package.json only, so npm ci failed on a stale lockfile.
This commit updates package.json, package.json.tpl and package-lock.json together.
The rate limiter trusted X-Real-IP, so a client could dodge its limit by
sending a new header value on each request. It must key on the connection
peer address. The key also strips the port, so one client shares one bucket.
Drop the RealIP middleware: the worker listens on 127.0.0.1 only, and RealIP is deprecated because a client can set its own address. Log the restart error directly, since Restart only returns on failure. Remove an unused slice in a test and pass a real context instead of nil. staticcheck now reports nothing.