Files
poimen-memory/tasks/M3.5.9-git-aware-references.md

6.6 KiB
Raw Permalink Blame History

M3.5.9 — Git-aware memory references: lookup by code location

Field Value
Phase M3.5 — Distributed API Layer
Size M — 13 days
Status Not started
Flags
Spec inlined below
Blocks
Depends M3.5.2 (git enrichment in ingest), M3.5.3 (query endpoint)

Goal

Enable agents to find and cite memory entries by code location (file:line, commit, author). Unifies memory log with git history. Agents reference: "Per src/kong/buffer.rs:42 (commit abc123)..." → lookup via git blame, return L0 evidence + L1 memory.

Design

New database columns (extend memory_node from M2.3):

ALTER TABLE memory_node ADD COLUMN git_context JSONB;
-- {file, line, commit_sha, commit_msg, author, author_date}

-- Index for git-based lookup
CREATE INDEX ON memory_node USING GIN (git_context);

Three lookup modes:

  1. By git location (file:line):
POST /memory/nodes/by-git
{
  "repo": "github.com/org/poimen",
  "file": "src/kong/buffer.rs",
  "line": 42,
  "project": "poimen"
}
→ 200 {
  "nodes": [
    {
      "sha256": "...",
      "level": "L0",
      "text": "Kong body buffer raised to 16MB...",
      "git_context": {commit_sha, commit_msg, author},
      "created_at": "2026-08-20T..."
    }
  ]
}
  1. By commit (evidence from this commit):
POST /memory/nodes/by-commit
{
  "repo": "github.com/org/poimen",
  "commit_sha": "abc123def",
  "project": "poimen"
}
→ nodes from this commit + parent L1/L2 memories
  1. By author (what did person X discover):
POST /memory/nodes/by-author
{
  "author": "[email protected]",
  "project": "poimen"
}
→ L0 nodes created during commits from alice

Query endpoint extension (M3.5.3): Add optional git_repo param:

GET /memory/query?query=Kong&git_repo=github.com/org/poimen&project=poimen
→ results enriched with git_context (file, commit, author)

Response format (all modes):

{
  "nodes": [
    {
      "sha256": "abc...",
      "level": "L0|L1|L2",
      "brief": "Kong body buffer raised",
      "git_ref": "src/kong/buffer.rs:42",
      "git_commit": {
        "sha": "abc123def",
        "message": "Increase body buffer to 16MB",
        "author": "[email protected]",
        "date": "2026-08-15T10:30:00Z"
      },
      "parents": [...]
    }
  ],
  "repo": "github.com/org/poimen"
}

Steps

  1. POST /memory/nodes/by-git handler:

    • Parse file, line, project
    • Query: SELECT * FROM memory_node WHERE project = $1 AND git_context->>'file' = $2 AND (git_context->>'line')::int = $3
    • Walk edges to include parent L1/L2 nodes
    • Sort by created_at desc
  2. POST /memory/nodes/by-commit handler:

    • Parse commit_sha, project
    • Query: SELECT * FROM memory_node WHERE project = $1 AND git_context->>'commit_sha' = $2
    • Include all L0 from this commit + transitive parents (L1/L2)
  3. POST /memory/nodes/by-author handler:

    • Parse author, project
    • Query: SELECT * FROM memory_node WHERE project = $1 AND git_context->>'author' = $2 AND level = 'L0'
    • Walk edges to L1 parents
  4. Extend M3.5.3 query handler:

    • Add optional git_repo query param
    • If provided, enrich response with git_context from each result node
    • Include git_ref in brief (file:line) for agent citation
  5. Deduplication by git:

    • L0 evidence from same (file, line, commit) = same memory entry
    • Idempotency: ingesting same commit twice doesn't duplicate L0 nodes
    • Check: (file, line, commit_sha) tuple uniqueness constraint

Acceptance

  • by-git lookup returns correct L0 evidence + parent memories
  • by-commit returns all evidence from that commit
  • by-author returns all discoveries by that author
  • Query results enriched with git_context when repo provided
  • Same evidence never duplicated (idempotent by git tuple)
  • Agents can cite by code location: "src/kong/buffer.rs:42 (commit abc123)"

Verify

Harness: Integration tests with git history fixture.

Setup: Create test repo with commits:

  • commit abc123: modify src/kong/buffer.rs:42 (message: "Increase buffer")
  • commit def456: modify src/kong/handler.rs:10 (message: "Handle large bodies")
  • Create memory nodes with git_context from these commits

Integration testtests/it_git_references.rs:

  1. a1_by_git_lookup — POST /nodes/by-git with file=buffer.rs, line=42 returns L0 from commit abc123.
  2. a2_by_commit_lookup — POST /nodes/by-commit with abc123 returns both L0 + parent L1/L2.
  3. a3_by_author_lookup — POST /nodes/by-author with alice@org returns all L0 from alice's commits.
  4. a4_query_enriched_with_git — GET /query?query=buffer&git_repo=... returns results with git_context populated.
  5. a5_git_ref_in_brief — result.git_ref = "src/kong/buffer.rs:42" (human-readable).
  6. a6_idempotent_by_git_tuple — ingest same commit twice, L0 nodes count stays 1 (no duplicates).
  7. a7_edge_walk_preserves_git — L1 parent of L0 node includes L0's git_context in parents array.
  8. a8_cross_commit_correlation — two commits affecting same file, both return from by-git lookup (line=0 or range?).
  9. a9_author_query_filters_correctly — two authors, by-author for alice returns only alice's L0.
  10. a10_missing_git_context_graceful — old L0 nodes without git_context (from before M3.5.2) still return but git_ref is null.

Command: cargo test -p mem-cli git_references

False pass:

  • Git context populated in fixture but never actually extracted from repo.git during ingest (M3.5.2). Test only checks stored data, not enrichment.
  • by-git returns results but never walks edges to L1. Parent L1 discoveries are invisible.
  • Query enrichment tested only with one repo. Multiple repos with overlapping filenames may return wrong results.
  • Idempotency tested with same commit but different git_repo URLs (github.com vs gitlab.com). Should be treated differently but test may not catch it.

Traps

  • Git blame is expensive. Caching blames by (file, commit_sha) pair is necessary for repeated queries.
  • Line numbers shift with edits. Reference to "line 42" in commit ABC may not match "line 42" in HEAD. Store commit hash, not line number, as primary key.
  • JSONB queries in PostgreSQL are slower than indexed columns. Consider denormalizing git_file, git_commit, git_author as separate columns if query volume is high.
  • Author name varies (alice@org vs alice.smith@org). Normalize email in ingest or handle fuzzy matching in by-author.
  • Cross-repo scenarios: same code in two repos (fork, mirror). git_repo must be part of uniqueness constraint.

Background: DESIGN.md § Distributed API Layer