- rebuild: fold observations per fingerprint in a total order
(hcl DESC, node_id DESC, id DESC) so two nodes with identical logs
rebuild identical entries (was: arbitrary bare-column row, merge-order
dependent)
- threads: CreateThreadCluster uses INSERT OR IGNORE + existing-id
fallback — concurrent auto-threaders converge instead of hitting UNIQUE
- errors surfaced instead of swallowed: scanEntries returns rows.Err(),
Stats() fails fast on query errors, AutoLinkThreadObservations /
linkTemporalNeighbors / golden-thread linking propagate failures,
AddThreadNote + LinkObservationToThread write under one tx,
watch records session upsert failures
- gossip client: push checks HTTP status and reports errors (a broken
push direction no longer looks like a silent success); gossip diff
gets a 10s timeout so a dead peer cannot hang the CLI
- ingest: failed source sweeps (obsidian/browser/gitea) are logged,
and -d's help text now states its file-only scope
- watch --quiet: fatal errors go to stderr instead of io.Discard
- main: cobra SilenceErrors/SilenceUsage (errors print once, usage is
not dumped on runtime failures); knox mcp exits 0 on SIGINT/SIGTERM
- metrics: drop _total suffix from gauges (knox_observations,
knox_entries, knox_projects, knox_sessions, knox_peers, knox_threads);
_total stays on counters per Prometheus convention
- http: ReadHeaderTimeout + IdleTimeout on gossip, metrics, and web servers
tests: concurrent cluster-create idempotency, HCL-order rebuild fold
(both merge orders), push HTTP-error surfacing; full suite + -race pass,
gofmt clean
Applies gofmt to the 18 files that were already unformatted at HEAD (pre-existing debt — 122 insertions / 122 deletions, whitespace plus import-block reorderings only; `git diff -w` confirms no semantic changes).
Kept on its own branch so the functional change set (see the review-hardening PR) stays reviewable without formatting noise.
Verified: go build, go vet, go test ./... pass on this branch; a merge simulation with the functional branch produces a clean 3-way merge with all tests green.
Reviewed-on: #4
Co-authored-by: David Gwilliam <dhgwilliam@gmail.com>
Co-committed-by: David Gwilliam <dhgwilliam@gmail.com>
Refs #2
- /metrics served on a dedicated port (KNOX_METRICS_ADDR, default
localhost:8932) via prometheus/client_golang, with Go runtime +
process collectors
- DB-derived gauges refreshed per scrape: observations by source,
last-24h observations, entries, projects, sessions, pending
reflections, threads by status, peers, observations by origin node,
knowledge vector (max hcl per node)
- live gossip counters (pulls/pushes, observations pulled/pushed,
errors) incremented during the anti-entropy sweep; Run accepts an
optional metrics handle (nil for one-shot CLI)
- knox_node_info{node_id,name} for scrape identification
- internal/metrics package + db MetricsSnapshot; tests for snapshot,
scrape output, and counter increments