stats: total_links under-counts entity links in 1.x (sum is missing the per-unit factor n)

Open Beginner friendly
#6,430 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
75/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
postgresql, python

Research direction

Start with hindsight-api-slim/hindsight_api/engine/memories/pg/counts.py near line 112 and inspect how the entity-link estimate feeds GET /v1/{ns}/banks/{bank}/stats. The issue describes a regression test against real Postgres that checks directed-neighbour counts, the 10-neighbour cap, bank isolation, and an empty bank; the reporter says they can share it. Done means the estimate matches direct counts, including the reported 144-link example.

Written by the indexing model from the issue text.

Description

core
Bug Description

GET /v1/{ns}/banks/{bank}/stats under-reports total_links in 1.x. After upgrading a bank from 0.7.x to 1.2.0, total_links drops sharply although the raw memory_links row count and the node and document counts are unchanged. Only the reported statistic is wrong. Stored links are unaffected.

The cause is the entity-link estimate in hindsight-api-slim/hindsight_api/engine/memories/pg/counts.py (line 112 on main):

SELECT COALESCE(SUM(LEAST(n - 1, $2)), 0)::bigint AS count

n is the number of memory units mentioning an entity, and $2 is the per-unit neighbour cap (10). Each of those n units links to up to LEAST(n - 1, cap) other units via that entity, so the sum is missing the factor n:

SELECT COALESCE(SUM(n * LEAST(n - 1, $2)), 0)::bigint AS count

This matches the 0.7 per-unit count, which equals the raw memory_links total on the same bank.

Steps to Reproduce
  1. Create a bank with entities mentioned by 2, 4 and 13 memory units (neighbour cap 10).
  2. Call GET /v1/{ns}/banks/{bank}/stats.
  3. Compare total_links with a direct count of directed entity links, or SELECT count(*) FROM memory_links for entity links in that bank.
Expected Behavior

2×1 + 4×3 + 13×10 = 144 entity links, matching the direct enumeration and the 0.7 result.

Actual Behavior

1 + 3 + 10 = 14. Each entity contributes its capped neighbour count once, instead of once per memory unit.

Version

1.2.0 (upgraded from 0.7.0). Still present on main as of 2026-11-07.

Additional notes

We have a one-line patch and a regression test against real Postgres. The test enumerates directed neighbours directly and covers the 10-neighbour cap, bank isolation and an empty bank. It fails on stock 1.2.0 and passes with n * added. We're happy to share the test if useful, since external PRs aren't accepted. Impact is display and monitoring only, but upgrade checks that compare total_links before and after a migration see a large false drop.

Dominant language
Python
Stars
45.2k
Forks
5.9k
Avg merge
3h 44m
Merged PRs (30d)
491

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from vectorize-io/hindsight

All issues in vectorize-io/hindsight

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.