Files
teamai-cli/docs/designs/git-native-memory.md
Saul Moro dc233e4489 fix(votes): keep votes with the scope they were cast in (#787) (#793)
* fix(votes): keep votes with the scope they were cast in (#787)

Every scope recorded into one ~/.teamai/votes/<user>.yaml, so a vote cast in
one project (recall feedback, a recall search, a Stop whose push failed) was
pushed to the team of whichever scope synced next: the leak usage.jsonl had
before #758.

Votes now live in the data home of the scope that resolves for the session:
<dataHome>/votes/ for a project, ~/.teamai/user-votes/ for the user scope.
The Stop hook uses the config the dispatcher resolved; the pull report, recall
search, `recall feedback` and the vote view read only that scope's votes, and
the CLI readers resolve it with resolveConfigForDir, so an unreadable project
config falls back to no other scope: `recall feedback` exits 1 and the vote
view names the broken file.

The shared ~/.teamai/votes/ is never read. Its V2 `votes` map is the last
merged remote snapshot of whichever team synced, not this scope's history, and
seeding a scope from it would let `recall feedback --negative` push a
decrement and merged timestamps derived from another team. The remote
votes/<user>.yaml format is unchanged.

* fix(votes): address pre-review findings (#787)

- recall search: in a project whose config cannot be read, detection falls
  back to another scope; record no recalled count there, so the vote cannot
  reach that scope's team. Which scope the search itself uses stays #796's.
- recall feedback: with no project config and an empty or invalid user
  config, name the file and the fix (requireInit's error) instead of
  "not set up here".
- CHANGELOG: note the recall search case; the shared directory is never
  read or pushed "by this release" (an earlier release still pushes it).
- Design doc: getUserVotesDir() is the exception to "getters unchanged".

* fix(votes): address second pre-review round (#787)

- recall feedback: name an unusable user config through
  throwMissingOrInvalid (now exported) instead of re-running requireInit,
  which loaded the config twice and printed its parse error twice.
- recall search: a project detection that throws is treated like an
  unreadable config, so no recalled count lands in the fallback scope.
- The recall-search test now asserts the search ran and that neither the
  shared directory nor the broken project's votes/ was written; it fails on
  origin/main too.
- Design doc: re-wrap the edited paragraph.

* fix(votes): record recall votes from a deleted cwd in the user scope (#787)

The previous commit treated any throw from recall's project detection as an
unreadable project, including a cwd that no longer exists. Such a cwd holds
no project and resolves to the user scope everywhere else
(resolveConfigForDir, detectTeam), so its recalled counts belong there.

Tests pin that case and the single parse-error line for an invalid user
config in recall feedback.

* fix(votes): address CI review findings (#787)

- getVotesDir: a historical project-scoped ~/.teamai/config.yaml with no
  projectRoot (schema-valid, not backfilled) made getDataHome throw, so
  recall, feedback and the Stop hook recorded no vote. It lives in
  ~/.teamai, as recall and viz already treat it, so its votes go to the
  user scope's user-votes/.
- git-native-memory design doc: the local votes path is user-votes/.

* fix(votes): address CI review (#787)

- recall feedback --negative counts the upvotes the scope's own team
  already holds (its reports checkout's votes/<user>.yaml plus the
  deltas not yet pushed). A scope's file starts empty on upgrade, so a
  doc upvoted before it was rejected as not found, or as having no
  upvotes once a later recall counted it. The shared ~/.teamai/votes and
  other scopes' teams are never read.
- The adoption judge (#723, merged meanwhile) recorded into and synced
  from the user scope's votes in every scope, which pushed the user
  scope's pending votes to the project's team. It uses the scope's votes
  like the Stop handler.
- votes-scope tests: Stop transcripts prove adoption with a Read of the
  recalled file (#723), and the update.js mock keeps the real lock.
2026-09-24 20:06:35 +08:00

5.7 KiB
Raw Permalink Blame History

Git-Native Memory System (Hindsight-Inspired)

Generated by /plan-ceo-review on 2026-03-28 Branch: master | Mode: SELECTIVE EXPANSION Repo: teamai/teamai-cli Reference: vectorize-io/hindsight — Agent Memory Framework

Overview

借鉴 Hindsight 的 retain/recall/reflect 三层记忆模型,用 Git + 本地搜索索引实现团队知识的自动回忆。补全 session contribute(写入路径)缺失的"读出路径",让 AI 在工作时自动"想起"别人的经验。

Vision

把 teamai 从"文件同步工具"升级为"团队记忆系统"。知识飞轮:

写入 → 索引 → 搜索 → 投票 → 排序 → 更好的搜索

Architecture

                    ┌─────────────────────────────────┐
                    │      TEAM GIT REPO               │
                    │  learnings/                       │
                    │    ├── k8s-oom-排查-2026-03-15.md │
                    │    └── api-timeout-修复-2026-03-20.md │
                    │  votes/                           │
                    │    ├── jeff.yaml                  │
                    │    └── alice.yaml                 │
                    └──────────┬────────────────────────┘
                               │
                    ┌──────────┴──────────┐
                    │                     │
              teamai pull           teamai contribute
              + index rebuild       (existing, enhanced)
                    │                     │
                    ▼                     │
    ┌───────────────────────────┐         │
    │  ~/.teamai/               │         │
    │    learnings/ (local copy)│◀────────┘
    │    search-index.json      │
    │    user-votes/<user>.yaml │
    └──────────┬───────────────┘
               │
         teamai recall "api timeout"
               │
               ▼
         Ranked results → recalled_count++
                              │
              (adoption evidence: agent opens the doc, or
               opt-in LLM-judge) → upvoted_count++

Hindsight Mapping

Hindsight Concept TeamAI Implementation Status
Retain (store) teamai contribute → learnings/ in git + frontmatter ✅ Done (enhanced)
Recall (retrieve) teamai recall <query> → local search index (BM25 + Intl.Segmenter) 🔨 This plan
Reflect (learn) teamai reflect → LLM analyzes learnings → meta-insights ⏳ Deferred
Memory Bank isolation Per-user directories in git repo ✅ Existing
Ranking/relevance Recall bumps recalled_count; adoption evidence (agent opened the doc, or the opt-in LLM-judge) bumps upvoted_count → votes/.yaml → aggregate at pull (#723) 🔨 This plan

Key Design Decisions

# Decision Choice Rationale
1 Storage backend Git repo (no PostgreSQL/vector DB) Zero external dependencies, matches teamai philosophy
2 Search method Keyword matching + Intl.Segmenter Handles CJK text, no embedding cost, sufficient for V1
3 Index location Local-only search-index.json Rebuilt at pull time, no sync conflicts
4 Vote mechanism Per-user YAML; recall bumps recalled_count, adoption evidence (tool-use / opt-in LLM-judge) bumps upvoted_count (#723) Idempotent, zero Git conflict, knowledge self-curates
5 Frontmatter Required in SKILL.md template Structured metadata improves search precision
6 AI integration Rule injection → AI calls recall via Bash Works across all AI tools, no tool-specific integration

Implementation Phases

Phase 1: Foundation (pull sync + index)

  1. src/types.ts — LearningDoc, SearchIndex types
  2. src/utils/search-index.ts — buildIndex(), loadIndex(), search() with Intl.Segmenter
  3. src/pull.ts — syncLearnings() step + index rebuild
  4. skill-data/share/SKILL.md — frontmatter 标准化(由 teamai skill get share 提供,不再部署到各 agent)
  5. Tests: index build, search, CJK, edge cases

Phase 2: Recall + Voting

  1. src/recall.ts — teamai recall CLI command + autoUpvote()
  2. src/index.ts — register recall command
  3. rules/teamai-recall.md — Rule synced to AI tools
  4. Tests: recall CLI, upvote idempotency, vote push

Phase 3: Integration

  1. Wire votes into search ranking (pull-time aggregation)
  2. Full integration test

Scope Decisions

# Proposal Effort Decision Reasoning
1 Auto-Recall on SessionStart M SUPERSEDED 已被 teamai-recall subagent + builtin-rules 主动检索替代
2 投票机制:recalled_count + 采纳 upvote S ACCEPTED Recall 累加 recalled_count;采纳证据(工具使用 / 可选 LLM-judge)累加 upvoted_count(#723)。零冲突,飞轮反馈机制的关键一环
3 Frontmatter 标准化 S ACCEPTED 提升搜索质量,向后兼容
4 Reflect 层 L DEFERRED 知识库冷启动阶段,数据不足

Deferred to TODOS.md

  • Auto-Recall on SessionStart (P2) — 已被 teamai-recall subagent + builtin-rules 主动检索替代(#106)
  • Reflect 层 (P3) — LLM 分析 learnings 生成 meta-insights,需知识库积累到 20+ 篇