Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions docs/ai/design/feature-memory-db-path-config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
---
phase: design
title: System Design & Architecture
description: Resolve memory database path from project config with default fallback
---

# System Design & Architecture

## Architecture Overview
```mermaid
graph TD
ProjectConfig[./.ai-devkit.json] --> ConfigManager
ConfigManager --> Resolver[CLI memory path resolver]
CLI[ai-devkit memory *] --> Resolver
Resolver --> MemoryAPI[@ai-devkit/memory API]
DefaultPath[~/.ai-devkit/memory.db] --> MemoryAPI
MemoryAPI --> DatabasePath[Effective DB path]
DatabasePath --> SQLite[(SQLite memory.db)]
```

- Keep `DEFAULT_DB_PATH` as the baseline fallback in the memory package.
- Add a CLI-owned resolver that can return a project override from `.ai-devkit.json`.
- Pass the resolved path from the CLI into `@ai-devkit/memory` before opening SQLite.
- Leave the standalone `@ai-devkit/memory` MCP server unchanged so it continues using `DEFAULT_DB_PATH`.

## Data Models
- Extend `DevKitConfig` with an optional memory section:
```ts
interface DevKitConfig {
memory?: {
path?: string;
};
}
```
- Extend CLI-to-memory command options with optional `dbPath?: string`.
- Resolver output is either:
- an absolute filesystem path derived from `memory.path`
- `undefined`, which means the memory package falls back to `DEFAULT_DB_PATH`

## API Design
- Add `ConfigManager.getMemoryDbPath(): Promise<string | undefined>` to read project config safely.
- Resolve `memory.path` inside the CLI command layer, not inside `packages/memory`.
- Add optional `dbPath` support to the memory package command APIs used by the CLI:
- `memoryStoreCommand(options)`
- `memorySearchCommand(options)`
- `memoryUpdateCommand(options)`
- Keep `packages/memory/src/server.ts` and the `ai-devkit-memory` binary unchanged in this feature.

## Component Breakdown
- `packages/cli/src/types.ts`
- Add optional `memory.path` typing to project config.
- `packages/cli/src/lib/Config.ts`
- Parse and validate `memory.path` from project config.
- Resolve relative paths against the config file directory.
- `packages/cli/src/commands/memory.ts`
- Load the project config once per command invocation.
- Pass resolved `dbPath` into the imported memory command API.
- `packages/memory/src/database/connection.ts`
- Continue exposing `DEFAULT_DB_PATH`.
- Accept explicit `dbPath` from callers without changing fallback semantics.
- `packages/memory/src/api.ts`
- Accept optional `dbPath` on CLI-facing command option types.
- Call `getDatabase({ dbPath })` so the explicit path only affects CLI-triggered operations that pass it.
- Tests
- Config parsing tests in CLI package.
- Memory command resolution tests in CLI and memory package.
- No standalone MCP server behavior change tests are needed beyond regression confidence.

## Design Decisions
- Keep fallback logic in the memory package and config parsing in the CLI package to preserve clear responsibilities.
- Resolve relative paths from the project root so checked-in config behaves consistently across shells and CI.
- Treat missing, blank, or non-string `memory.path` as unset and fall back silently to `DEFAULT_DB_PATH` to preserve backward compatibility.
- Keep the package boundary intact by passing `dbPath` explicitly from the CLI rather than making `packages/memory` depend on `ConfigManager`.
- Apply the configured path to `store`, `search`, and `update` so CLI memory subcommands stay consistent.

## Non-Functional Requirements
- No change to default behavior for projects without `memory.path`.
- No additional network or external service dependency.
- Path resolution must be deterministic across macOS and Linux path semantics already supported by Node's `path` module.
- Database initialization and schema migration behavior remain unchanged once the final path is selected.
- Standalone `@ai-devkit/memory` server startup and runtime behavior remain unchanged in this feature.
40 changes: 40 additions & 0 deletions docs/ai/implementation/feature-memory-db-path-config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
phase: implementation
title: Implementation Guide
description: Implementation notes for project-configurable memory database paths
---

# Implementation Guide

## Development Setup
- Use the feature worktree `feature-memory-db-path-config`.
- Install dependencies with `npm ci` from the worktree root.

## Code Structure
- Config shape and parsing live in the CLI package.
- Effective database path selection is resolved in the CLI and passed explicitly into the memory package.

## Implementation Notes
### Core Features
- Add typed support for `memory.path` in project config.
- Resolve relative configured paths from the project root.
- Pass the resolved path into `ai-devkit memory store`, `search`, and `update`.

### Patterns & Best Practices
- Keep `DEFAULT_DB_PATH` as the fallback constant.
- Avoid duplicating path-resolution logic across CLI command handlers.

## Integration Points
- `.ai-devkit.json`
- `ConfigManager`
- memory CLI command adapters

## Error Handling
- Invalid or absent `memory.path` should not break memory commands; fall back to the default path.

## Performance Considerations
- Path resolution should happen once per CLI command invocation before opening the database.

## Security Notes
- Treat `memory.path` as a filesystem path only; no shell execution or interpolation.
- Standalone `@ai-devkit/memory` server behavior remains unchanged in this feature.
58 changes: 58 additions & 0 deletions docs/ai/planning/feature-memory-db-path-config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
phase: planning
title: Project Planning & Task Breakdown
description: Task breakdown for project-configurable memory database paths
---

# Project Planning & Task Breakdown

## Milestones
- [x] Milestone 1: Project config schema and parsing support `memory.path`
- [x] Milestone 2: CLI memory command flows consume resolved database path
- [x] Milestone 3: Tests cover configured path and fallback behavior

## Task Breakdown

### Phase 1: Config Support
- [x] Task 1.1: Extend `packages/cli/src/types.ts` to type optional `memory.path`
- [x] Task 1.2: Add `ConfigManager.getMemoryDbPath()` in `packages/cli/src/lib/Config.ts`
- [x] Task 1.3: Add unit tests for project config parsing, including missing, invalid, absolute, and relative path cases

### Phase 2: Memory Path Wiring
- [x] Task 2.1: Introduce a CLI-owned path-resolution flow that combines project config override with `DEFAULT_DB_PATH`
- [x] Task 2.2: Update `packages/memory/src/api.ts` and CLI entry points so store/search/update use the resolved path consistently
- [x] Task 2.3: Removed from scope during Phase 2 review. Standalone `@ai-devkit/memory` MCP server remains unchanged for this feature.

### Phase 3: Verification
- [x] Task 3.1: Add or update CLI tests covering memory commands with configured `memory.path`
- [x] Task 3.2: Add or update memory package tests covering explicit `dbPath` wiring and configured-path persistence
- [x] Task 3.3: Run targeted verification for docs lint and relevant automated tests

## Dependencies
- Task 1.1 precedes Task 1.2 because config typing should match the new parser surface.
- Task 1.2 precedes Task 2.1 and Task 2.2 because runtime resolution depends on the config accessor.
- Task 2.1 should land before Task 2.2 so CLI and memory API use one resolution rule.
- Verification tasks depend on both config support and runtime wiring being complete.

## Timeline & Estimates
- Phase 1: Small, low-risk change
- Phase 2: Medium effort because path selection currently sits below config loading boundaries
- Phase 3: Small to medium effort depending on current test coverage for memory command setup

## Risks & Mitigation
- Risk: CLI commands honor config but the standalone MCP server still uses the default database.
Mitigation: This is intentional and documented as out of scope for the feature.
- Risk: Relative paths resolve from process cwd instead of project root.
Mitigation: Resolve from the config file directory and add explicit unit tests.
- Risk: Invalid config values break existing users.
Mitigation: Treat invalid values as unset and retain `DEFAULT_DB_PATH`.

## Resources Needed
- Existing config loading utilities in `packages/cli/src/lib/Config.ts`
- Existing database connection behavior in `packages/memory/src/database/connection.ts`
- Existing memory command tests in `packages/cli/src/__tests__/commands/memory.test.ts`

## Progress Summary
- Completed implementation for project-configured `memory.path` in `ai-devkit` CLI flows.
- Preserved standalone `@ai-devkit/memory` behavior as approved during requirements review.
- Verified with targeted CLI tests, memory integration tests, feature doc lint, package builds, and a real built-CLI store/search run against a temporary project config.
51 changes: 51 additions & 0 deletions docs/ai/requirements/feature-memory-db-path-config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
phase: requirements
title: Requirements & Problem Understanding
description: Allow project config to override the default memory database path
---

# Requirements & Problem Understanding

## Problem Statement
- Memory storage currently defaults to `~/.ai-devkit/memory.db` via `packages/memory/src/database/connection.ts`.
- Projects cannot pin memory storage to a repo-specific database, so contributors working in the same repository may read and write different global state.
- Users who want isolated project memory have no supported configuration path in `.ai-devkit.json`.

## Goals & Objectives
- Allow project `.ai-devkit.json` to define `memory.path`.
- Keep the existing default database path as `~/.ai-devkit/memory.db` when no project override is configured.
- Make memory commands use the configured project path consistently for store, search, and update flows.
- Scope the change to `ai-devkit` project commands and avoid changing standalone `@ai-devkit/memory` package behavior.

## Non-Goals
- Adding a global `memory.path` override in `~/.ai-devkit/.ai-devkit.json`.
- Redesigning unrelated `.ai-devkit.json` sections.
- Changing the default database filename or directory.
- Making standalone `@ai-devkit/memory` automatically read project `.ai-devkit.json`.

## User Stories & Use Cases
- As a project maintainer, I can commit `"memory": { "path": ".ai-devkit/project-memory.db" }` to `.ai-devkit.json` so everyone on the repository uses the same project-local memory database.
- As a developer without project memory config, I continue using `~/.ai-devkit/memory.db` with no behavior change.
- As a user running `ai-devkit memory search`, `store`, or `update` inside a configured project, I want all commands to resolve the same configured database path automatically.
- As a user running the standalone `@ai-devkit/memory` MCP server directly, I continue using its package default path unless a later feature adds separate config support.

## Success Criteria
- Project `.ai-devkit.json` accepts a `memory.path` string.
- When `memory.path` is present in project config, `ai-devkit memory` operations use that path instead of `~/.ai-devkit/memory.db`.
- When `memory.path` is absent, empty, or invalid, memory operations fall back to `~/.ai-devkit/memory.db`.
- Relative configured paths are resolved deterministically from the project root containing `.ai-devkit.json`.
- Tests cover configured path resolution and default fallback behavior.
- Standalone `@ai-devkit/memory` behavior remains unchanged in this feature.

## Constraints & Assumptions
- `ConfigManager` already owns project `.ai-devkit.json` loading in `packages/cli/src/lib/Config.ts`.
- The current memory package hard-codes the default path in `packages/memory/src/database/connection.ts`; implementation must preserve that default for non-project-aware callers.
- The project config shape currently allows additive extension without a broader schema migration.
- The configured path should remain a plain filesystem path string; no environment-variable expansion is required unless existing config code already supports it.
- `packages/memory` should not gain a dependency on the CLI package just for this feature.

## Questions & Open Items
- The config key will be `memory.path` in project `.ai-devkit.json`.
- Relative paths will be interpreted relative to the directory containing `.ai-devkit.json`, not the shell's current working directory.
- Scope decision: only `ai-devkit` project commands will honor `memory.path`; standalone `@ai-devkit/memory` is out of scope.
- No additional blocking questions remain for implementation.
61 changes: 61 additions & 0 deletions docs/ai/testing/feature-memory-db-path-config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
---
phase: testing
title: Testing Strategy
description: Testing plan for project-configurable memory database paths
---

# Testing Strategy

## Test Coverage Goals
- Cover 100% of new and changed code related to config parsing and path resolution.
- Verify both configured-path and default-path flows.
- Keep standalone `@ai-devkit/memory` server behavior unchanged.

## Unit Tests
### Config parsing
- [x] Reads `memory.path` when it is a non-empty string
- [x] Ignores missing, blank, and non-string `memory.path`
- [x] Resolves relative `memory.path` from the project config directory
Implemented in `packages/cli/src/__tests__/lib/Config.test.ts`

### Memory command resolution
- [x] `memory store` uses configured path when project config exists
- [x] `memory search` uses configured path when project config exists
- [x] `memory update` uses configured path when project config exists
- [x] Commands fall back to `~/.ai-devkit/memory.db` when no project override exists
Verified by default `dbPath: undefined` expectations and configured-path expectations in `packages/cli/src/__tests__/commands/memory.test.ts`

## Integration Tests
- [x] Schema initialization succeeds when the configured path points to a new file
- [x] Memory API store/search/update calls use an explicit configured `dbPath`
Implemented in `packages/memory/tests/integration/api.test.ts`
- [x] Standalone memory MCP server remains out of scope and unchanged
Covered by design/requirements scope, not by new behavior tests

## End-to-End Tests
- [x] Automated CLI e2e test uses a temp-project `.ai-devkit.json` with repo-local `memory.path`
Implemented in `e2e/cli.e2e.ts`
- [x] Manual smoke test with a checked-in `.ai-devkit.json` using a repo-local memory DB
Verified via built CLI store/search run in a temporary project directory with `.ai-devkit.json` pointing to `.ai-devkit/project-memory.db`

## Test Data
- Temporary project directories with generated `.ai-devkit.json`
- Temporary database file paths for isolated runs

## Test Reporting & Coverage
- Ran `npm test -- --runInBand Config.test.ts memory.test.ts` in `packages/cli`
- Ran `npm test -- --runInBand tests/integration/api.test.ts` in `packages/memory`
- Ran `npm run test:e2e -- cli.e2e.ts`
- Ran `npx ai-devkit@latest lint --feature memory-db-path-config`
- Did not run a full coverage report command in this phase; targeted suites were used for feature verification

## Manual Testing
- Confirmed a repo-local configured DB file is created on first write
- Confirmed built CLI search reads back from the configured repo-local DB
- Default fallback is covered by unit tests rather than a separate manual run

## Performance Testing
- No dedicated performance testing required beyond regression confidence

## Bug Tracking
- Watch for regressions where one CLI memory subcommand omits `dbPath` and reverts to `~/.ai-devkit/memory.db`
13 changes: 13 additions & 0 deletions e2e/cli.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,22 @@ describe('lint command', () => {
describe('memory commands', () => {
let projectDir: string;
let uid: string;
let projectMemoryDbPath: string;

beforeEach(() => {
projectDir = createTempProject();
uid = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
projectMemoryDbPath = join(projectDir, '.ai-devkit', 'memory.db');
writeConfigFile(projectDir, {
version: '1.0.0',
environments: [],
phases: [],
memory: {
path: '.ai-devkit/memory.db'
},
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString()
});
});

afterEach(() => {
Expand All @@ -168,6 +180,7 @@ describe('memory commands', () => {
const stored = JSON.parse(storeResult.stdout.trim());
expect(stored.success).toBe(true);
expect(stored.id).toBeDefined();
expect(existsSync(projectMemoryDbPath)).toBe(true);

const searchResult = run(`memory search -q "${title}"`, { cwd: projectDir });
expect(searchResult.exitCode).toBe(0);
Expand Down
Loading
Loading