Files
flynn/docs/plans/phase1-pr3-memory-structure-checklist.md
2026-02-12 22:47:28 -08:00

5.6 KiB

Phase 1 PR #3 Checklist: Memory Category Structure

Created: 2026-02-12 Owner: Flynn core Status: ready to implement

Goal

Introduce structured memory categories while preserving current memory behavior.

Categories:

  • facts
  • preferences
  • decisions
  • projects

This PR is infrastructure-only: no new user-facing commands yet.

PR Boundary

In scope:

  • Add category types/constants/utilities
  • Add category-aware MemoryStore APIs
  • Keep existing read/write/search/getContextForPrompt behavior intact
  • Add category-aware retrieval helpers for follow-on PRs
  • Unit tests for compatibility and correctness

Out of scope:

  • Auto-categorization/extraction heuristics
  • New slash commands (/memory add --category ...)
  • Migration CLI that rewrites existing files
  • UI/dashboard for category browsing

Compatibility Model

Existing flat namespaces remain valid:

  • user
  • global
  • sessions/<id>

Category namespaces are additive and path-based:

  • user/facts
  • user/preferences
  • global/decisions
  • sessions/<id>/projects

No destructive migration in this PR.

File-by-File Diff Plan

  1. src/memory/categories.ts (new)
  • Add category constants and helpers.
export const MEMORY_CATEGORIES = ['facts', 'preferences', 'decisions', 'projects'] as const;
export type MemoryCategory = (typeof MEMORY_CATEGORIES)[number];

export function isMemoryCategory(value: string): value is MemoryCategory {
  return (MEMORY_CATEGORIES as readonly string[]).includes(value);
}

export function categoryNamespace(baseNamespace: string, category: MemoryCategory): string {
  return `${baseNamespace}/${category}`;
}
  1. src/memory/store.ts (modify)
  • Add category-aware methods without changing existing API behavior.

New methods:

  • readCategory(baseNamespace: string, category: MemoryCategory): string
  • writeCategory(baseNamespace: string, category: MemoryCategory, content: string, mode: 'append' | 'replace'): void
  • listCategories(baseNamespace: string): MemoryCategory[]
  • readAllCategories(baseNamespace: string): Partial<Record<MemoryCategory, string>>
  • search(query: string, opts?: { categories?: MemoryCategory[]; baseNamespacePrefix?: string }): SearchResult[]

Notes:

  • Keep old search(query: string) call pattern working via optional opts.
  • Ensure dirty namespace tracking marks category namespaces too.
  • Keep getContextForPrompt() backward compatible: include legacy sections first, then category sections if present and token budget allows.
  1. src/memory/index.ts (modify)
  • Export category types/utilities.
export * from './categories.js';
  1. src/memory/categories.test.ts (new)
  • Validate category constants/helpers:
    • isMemoryCategory true/false paths
    • namespace composition correctness
  1. src/memory/store.test.ts (modify/add)
  • Add category coverage:
    • category read/write/append/replace
    • list/readAll categories
    • filtered search by category
    • backward compatibility for legacy namespaces
    • getContextForPrompt() includes legacy + category content under token budget
  1. src/tools/builtin/memory.ts (modify docs-only or no-op code)
  • If tool schemas/docs mention namespaces, document category namespace pattern so next PR can add command-level category args cleanly.

Implementation Steps

  1. Add categories.ts with constants/types/helpers.
  2. Extend MemoryStore with category methods (additive only).
  3. Extend search to support optional category filters.
  4. Update prompt context composition to include categories safely.
  5. Export new memory APIs from memory index barrel.
  6. Add unit tests for category + compatibility behavior.
  7. Run full validation.

Validation Commands

pnpm typecheck
pnpm test:run src/memory/categories.test.ts
pnpm test:run src/memory/store.test.ts
pnpm test:run
pnpm lint
pnpm build

Acceptance Criteria

  • Existing memory paths (user, global, sessions/<id>) still work unchanged.
  • Category APIs function for all four categories.
  • Search works both with and without category filters.
  • No data loss or rewrite required for existing memory files.
  • getContextForPrompt() remains stable and token-bounded.
  • Dirty namespace/indexing behavior remains correct for new category paths.
  • All existing tests pass; new memory tests added.

Quality Gates

  • Backward compatibility:
    • Legacy reads/writes/searches unchanged.
    • Old memory files remain readable with zero migration.
  • Retrieval correctness:
    • Category-filtered searches return only matching namespaces.
    • Unfiltered searches still span all namespaces.
  • Performance:
    • No meaningful regression for unfiltered search/list operations.
    • Category filtering avoids unnecessary extra scans where possible.
  • Reliability:
    • Missing category files return empty strings (not errors).
    • Invalid categories are rejected at type-level and guarded in runtime helper paths.

Risks and Mitigations

  • Risk: subtle prompt-context ordering changes.
    • Mitigation: preserve legacy section order, append category sections after legacy content.
  • Risk: token budget overrun from extra sections.
    • Mitigation: enforce existing truncation logic after composing all sections.
  • Risk: search API break due to signature change.
    • Mitigation: keep opts optional and maintain old call contract.

Suggested Commit Message

feat(memory): add structured category namespaces with backward-compatible APIs

Follow-up PRs

  1. Add category-aware memory tool arguments and slash command UX.
  2. Add auto-extraction into categories during compaction/memory pipeline.
  3. Add migration/normalization utility for legacy memory into categories.