From b233c4a2ad1344d531b13026c81eed6c14d1da3d Mon Sep 17 00:00:00 2001 From: Tony Casey Date: Sat, 14 Feb 2026 19:17:26 +0000 Subject: [PATCH 1/2] feat: update init.ts to write YAML config (GIT-90) - Create .git-mem/ directory if it doesn't exist - Write config as YAML to .git-mem/.git-mem.yaml - Update .gitignore to ignore .git-mem/ directory - Parse existing config as YAML when merging Co-Authored-By: Claude Opus 4.5 AI-Agent: Claude-Code/2.1.42 AI-Model: claude-opus-4-5-20251101 AI-Decision: update init.ts to write YAML config (GIT-90). - Create .git-mem/ directory if it doesn't exist AI-Confidence: medium AI-Tags: commands, typescript AI-Lifecycle: project AI-Memory-Id: 4c2e5a59 AI-Source: heuristic --- src/commands/init.ts | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/commands/init.ts b/src/commands/init.ts index 78e8366f..b0b8d12a 100644 --- a/src/commands/init.ts +++ b/src/commands/init.ts @@ -9,6 +9,7 @@ import { existsSync, readFileSync, writeFileSync, appendFileSync, mkdirSync } fr import { execFileSync } from 'child_process'; import { join } from 'path'; import prompts from 'prompts'; +import { parse as parseYaml, stringify as stringifyYaml } from 'yaml'; import type { ILogger } from '../domain/interfaces/ILogger'; import { getSettingsPath, @@ -24,6 +25,7 @@ import { installPostCommitHook, uninstallPostCommitHook } from '../hooks/post-co import { installCommitMsgHook, uninstallCommitMsgHook } from '../hooks/commit-msg'; import { createContainer } from '../infrastructure/di'; import { createStderrProgressHandler } from './progress'; +import { getConfigPath, getConfigDir } from '../hooks/utils/config'; interface IInitCommandOptions { yes?: boolean; @@ -245,14 +247,18 @@ export async function initCommand(options: IInitCommandOptions, logger?: ILogger writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n'); console.log(`✓ Created ${settingsPath}`); - // .git-mem.json - const gitMemConfigPath = join(cwd, '.git-mem.json'); - const existingGitMemConfig = existsSync(gitMemConfigPath) - ? (() => { try { return JSON.parse(readFileSync(gitMemConfigPath, 'utf8')) as Record; } catch { return {}; } })() + // .git-mem/.git-mem.yaml + const configDir = getConfigDir(cwd); + const configPath = getConfigPath(cwd); + if (!existsSync(configDir)) { + mkdirSync(configDir, { recursive: true }); + } + const existingGitMemConfig = existsSync(configPath) + ? (() => { try { return parseYaml(readFileSync(configPath, 'utf8')) as Record; } catch { return {}; } })() : {}; const mergedGitMemConfig = deepMergeGitMemConfig(existingGitMemConfig, buildGitMemConfig()); - writeFileSync(gitMemConfigPath, JSON.stringify(mergedGitMemConfig, null, 2) + '\n'); - console.log('✓ Created .git-mem.json'); + writeFileSync(configPath, stringifyYaml(mergedGitMemConfig)); + console.log('✓ Created .git-mem/.git-mem.yaml'); } // ── Git hooks (prepare-commit-msg, commit-msg, post-commit) ───── @@ -295,7 +301,7 @@ export async function initCommand(options: IInitCommandOptions, logger?: ILogger } // ── .gitignore ───────────────────────────────────────────────── - ensureGitignoreEntries(cwd, ['.env', '.git-mem.json']); + ensureGitignoreEntries(cwd, ['.env', '.git-mem/']); console.log('✓ Updated .gitignore'); // ── .env placeholder ────────────────────────────────────────── From 98164e3b733ff86dd0ed18271e940b0c2bec363a Mon Sep 17 00:00:00 2001 From: Tony Casey Date: Sat, 14 Feb 2026 20:33:11 +0000 Subject: [PATCH 2/2] fix: guard YAML parsing against null values parseYaml() returns null for empty files. Add type guard to coerce null/non-object results to empty object before passing to deepMergeGitMemConfig(). Addresses CodeRabbit review feedback. Co-Authored-By: Claude Opus 4.5 AI-Agent: Claude-Code/2.1.42 AI-Model: claude-opus-4-5-20251101 AI-Gotcha: guard YAML parsing against null values. parseYaml() returns null for empty files. Add type guard to coerce AI-Confidence: medium AI-Tags: commands, typescript AI-Lifecycle: project AI-Memory-Id: 3d999379 AI-Source: heuristic --- src/commands/init.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/commands/init.ts b/src/commands/init.ts index b0b8d12a..69f8d93d 100644 --- a/src/commands/init.ts +++ b/src/commands/init.ts @@ -253,9 +253,17 @@ export async function initCommand(options: IInitCommandOptions, logger?: ILogger if (!existsSync(configDir)) { mkdirSync(configDir, { recursive: true }); } - const existingGitMemConfig = existsSync(configPath) - ? (() => { try { return parseYaml(readFileSync(configPath, 'utf8')) as Record; } catch { return {}; } })() - : {}; + const existingGitMemConfig = (() => { + if (!existsSync(configPath)) return {}; + try { + const parsed = parseYaml(readFileSync(configPath, 'utf8')); + return parsed && typeof parsed === 'object' && !Array.isArray(parsed) + ? (parsed as Record) + : {}; + } catch { + return {}; + } + })(); const mergedGitMemConfig = deepMergeGitMemConfig(existingGitMemConfig, buildGitMemConfig()); writeFileSync(configPath, stringifyYaml(mergedGitMemConfig)); console.log('✓ Created .git-mem/.git-mem.yaml');