@riconext/hermes-repo 0.1.0 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/index.ts"],"sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { PACKAGE_NAME } from \"./index.js\";\n\nfunction readPkgVersion(): string {\n const root = join(dirname(fileURLToPath(import.meta.url)), \"..\", \"package.json\");\n const raw = readFileSync(root, \"utf8\");\n const pkg = JSON.parse(raw) as { version?: string };\n return typeof pkg.version === \"string\" ? pkg.version : \"0.0.0\";\n}\n\nconst version = readPkgVersion();\nconst argv = process.argv.slice(2);\nconst cmd = argv[0];\n\nif (cmd === \"-v\" || cmd === \"--version\") {\n process.stdout.write(`${version}\\n`);\n process.exit(0);\n}\n\nif (cmd === \"-h\" || cmd === \"--help\" || cmd === undefined) {\n process.stdout.write(`${PACKAGE_NAME} v${version}\n\n用法:\n hermes-repo 显示本帮助\n hermes-repo --version 显示版本\n\n后续将提供 init / validate / doctor 等子命令(见仓库 docs)。\n`);\n process.exit(cmd === undefined ? 0 : 0);\n}\n\nprocess.stderr.write(`未知命令: ${cmd}\\n请使用 hermes-repo --help\\n`);\nprocess.exit(1);\n","/**\n * @riconext/hermes-repo — 库入口(CLI 见 `hermes-repo` bin)。\n */\n\nexport const PACKAGE_NAME = \"@riconext/hermes-repo\" as const;\n"],"mappings":";;;AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS,YAAY;AAC9B,SAAS,qBAAqB;;;ACEvB,IAAM,eAAe;;;ADE5B,SAAS,iBAAyB;AAChC,QAAM,OAAO,KAAK,QAAQ,cAAc,YAAY,GAAG,CAAC,GAAG,MAAM,cAAc;AAC/E,QAAM,MAAM,aAAa,MAAM,MAAM;AACrC,QAAM,MAAM,KAAK,MAAM,GAAG;AAC1B,SAAO,OAAO,IAAI,YAAY,WAAW,IAAI,UAAU;AACzD;AAEA,IAAM,UAAU,eAAe;AAC/B,IAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AACjC,IAAM,MAAM,KAAK,CAAC;AAElB,IAAI,QAAQ,QAAQ,QAAQ,aAAa;AACvC,UAAQ,OAAO,MAAM,GAAG,OAAO;AAAA,CAAI;AACnC,UAAQ,KAAK,CAAC;AAChB;AAEA,IAAI,QAAQ,QAAQ,QAAQ,YAAY,QAAQ,QAAW;AACzD,UAAQ,OAAO,MAAM,GAAG,YAAY,KAAK,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAOjD;AACC,UAAQ,KAAK,QAAQ,SAAY,IAAI,CAAC;AACxC;AAEA,QAAQ,OAAO,MAAM,6BAAS,GAAG;AAAA;AAAA,CAA4B;AAC7D,QAAQ,KAAK,CAAC;","names":[]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/capture/claude-code/resolveSession.ts","../src/config/debugLog.ts","../src/init/paths.ts","../src/config/readConfig.ts","../src/config/findRepoRoot.ts","../src/capture/shouldCapture.ts","../src/capture/sessionsIndex.ts","../src/capture/writeCapture.ts","../src/capture/claude-code/parseJsonl.ts","../src/capture/claude-code/run.ts","../src/capture/router.ts","../src/capture/runCapture.ts","../src/hookExit.ts","../src/commands/capture.ts","../src/inject/runInject.ts","../src/inject/constants.ts","../src/commands/inject.ts","../src/init/runInit.ts","../src/init/assistants/claude-code.ts","../src/init/templateDir.ts","../src/index.ts","../src/init/scaffoldWrite.ts","../src/init/assistants/cursor.ts","../src/init/assistants/registry.ts","../src/init/ensureDirs.ts","../src/init/mergeAssistants.ts","../src/init/mergeGitignore.ts","../src/init/prompts.ts","../src/init/writeScaffoldFile.ts","../src/init/mergeConfig.ts","../src/commands/init.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { runCaptureCommand } from \"./commands/capture.js\";\nimport { runInjectCommand } from \"./commands/inject.js\";\nimport { runInitCommand } from \"./commands/init.js\";\nimport { readPkgVersion } from \"./index.js\";\n\nconst MIN_NODE_MAJOR = 20;\n\nfunction assertNodeVersion(): void {\n const major = Number.parseInt(process.versions.node.split(\".\")[0] ?? \"0\", 10);\n if (major < MIN_NODE_MAJOR) {\n console.error(\n `hermes-repo requires Node.js >= ${MIN_NODE_MAJOR}. Current: ${process.versions.node}`,\n );\n process.exit(1);\n }\n}\n\nfunction main(): void {\n assertNodeVersion();\n\n const program = new Command();\n\n program\n .name(\"hermes-repo\")\n .description(\n \"跨编程助手的项目级记忆系统:在 Git 仓库中沉淀约定、踩坑与可复用流程\",\n )\n .version(readPkgVersion(), \"-V, --version\", \"显示版本号\");\n\n program\n .command(\"init\")\n .description(\"在当前 Git 仓库初始化 .memory/ 记忆脚手架\")\n .option(\"-y, --yes\", \"非交互模式,使用默认选项\")\n .option(\"-f, --force\", \"覆盖已存在的脚手架文件(不删除 captures 等内容)\")\n .option(\"-C, --cwd <dir>\", \"目标目录,默认 process.cwd()\")\n .option(\n \"--tools <ids>\",\n \"逗号分隔的助手 id,如 claude-code(须与 -y 合用)\",\n )\n .action(\n (options: {\n yes?: boolean;\n force?: boolean;\n cwd?: string;\n tools?: string;\n }) => {\n void runInitCommand({\n yes: options.yes,\n force: options.force,\n cwd: options.cwd,\n tools: options.tools,\n });\n },\n );\n\n program\n .command(\"capture\")\n .description(\"Stop hook:捕获当前 Claude Code 会话到 .memory/captures/\")\n .option(\"-C, --cwd <dir>\", \"目标仓库根目录\")\n .option(\"--dry-run\", \"仅预览,不写入文件\")\n .option(\"--strict\", \"失败时 exit 1(hook 默认 exit 0)\")\n .action((options: { cwd?: string; dryRun?: boolean; strict?: boolean }) => {\n runCaptureCommand({\n cwd: options.cwd,\n dryRun: options.dryRun,\n strict: options.strict,\n });\n });\n\n program\n .command(\"inject\")\n .description(\"SessionStart hook:将 MEMORY.md 摘要输出到 stdout\")\n .option(\"-C, --cwd <dir>\", \"目标仓库根目录\")\n .option(\"--strict\", \"失败时 exit 1(hook 默认 exit 0)\")\n .action((options: { cwd?: string; strict?: boolean }) => {\n runInjectCommand({\n cwd: options.cwd,\n strict: options.strict,\n });\n });\n\n if (process.argv.length <= 2) {\n program.outputHelp();\n process.exit(0);\n }\n\n program.parse(process.argv);\n}\n\nmain();\n","import { existsSync, readdirSync, readFileSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { basename, join, resolve } from \"node:path\";\n\n/** Claude Code:项目目录名 = 绝对路径将 `/` 替换为 `-`(见官方 ~/.claude/projects/) */\nexport function encodeClaudeProjectDir(absPath: string): string {\n return resolve(absPath).replace(/\\//g, \"-\");\n}\n\nexport interface ResolveSessionOptions {\n /** Claude Stop hook stdin JSON 的 transcript_path(官方首选) */\n transcriptPath?: string;\n cwd?: string;\n}\n\n/**\n * 解析 Claude Code 会话 JSONL 路径。\n * 依据 https://code.claude.com/docs/en/claude-directory#application-data\n *\n * 优先级:\n * 1. HERMES_SESSION_JSONL(测试 / 手动覆盖)\n * 2. transcriptPath(hook stdin 的 transcript_path)\n * 3. ~/.claude/projects/<encoded-cwd>/*.jsonl(当前仓库)\n * 4. 全局 projects 下最新 .jsonl(含旧版 sessions 子目录回退)\n */\nexport function resolveSessionJsonlPath(\n repoRoot: string,\n options: ResolveSessionOptions = {},\n): string | null {\n const override = process.env.HERMES_SESSION_JSONL;\n if (override && existsSync(override)) {\n return resolve(override);\n }\n\n const fromHook = options.transcriptPath;\n if (fromHook && existsSync(fromHook)) {\n return resolve(fromHook);\n }\n\n const sessionId =\n process.env.CLAUDE_SESSION_ID ??\n process.env.CLAUDE_CODE_SESSION_ID ??\n process.env.SESSION_ID;\n\n const claudeHome = process.env.CLAUDE_CONFIG_DIR\n ? resolve(process.env.CLAUDE_CONFIG_DIR)\n : join(homedir(), \".claude\");\n const projectsRoot = join(claudeHome, \"projects\");\n if (!existsSync(projectsRoot)) {\n return null;\n }\n\n const cwd = resolve(options.cwd ?? repoRoot);\n const preferredProjectDir = encodeClaudeProjectDir(cwd);\n const preferredPath = join(projectsRoot, preferredProjectDir);\n if (existsSync(preferredPath)) {\n const hit = pickNewestJsonl(preferredPath, sessionId);\n if (hit) {\n return hit;\n }\n const legacySessions = join(preferredPath, \"sessions\");\n if (existsSync(legacySessions)) {\n const legacyHit = pickNewestJsonl(legacySessions, sessionId);\n if (legacyHit) {\n return legacyHit;\n }\n }\n }\n\n const candidates: Array<{ path: string; mtime: number }> = [];\n\n for (const projectDir of readdirSync(projectsRoot, { withFileTypes: true })) {\n if (!projectDir.isDirectory()) continue;\n const projectPath = join(projectsRoot, projectDir.name);\n collectJsonlCandidates(projectPath, sessionId, candidates);\n const legacySessions = join(projectPath, \"sessions\");\n if (existsSync(legacySessions)) {\n collectJsonlCandidates(legacySessions, sessionId, candidates);\n }\n }\n\n if (candidates.length === 0) {\n return null;\n }\n\n candidates.sort((a, b) => b.mtime - a.mtime);\n return candidates[0]?.path ?? null;\n}\n\n/** 从 hook stdin 读取 Claude Code 传入的 transcript_path(非 TTY 时) */\nexport function readHookTranscriptPathSync(): string | null {\n if (process.stdin.isTTY) {\n return null;\n }\n try {\n const raw = readFileSync(0, \"utf8\").trim();\n if (!raw) {\n return null;\n }\n const parsed = JSON.parse(raw) as { transcript_path?: unknown };\n const p = parsed.transcript_path;\n if (typeof p === \"string\" && existsSync(p)) {\n return resolve(p);\n }\n } catch {\n return null;\n }\n return null;\n}\n\nfunction pickNewestJsonl(\n dir: string,\n sessionId: string | undefined,\n): string | null {\n const candidates: Array<{ path: string; mtime: number }> = [];\n collectJsonlCandidates(dir, sessionId, candidates);\n if (candidates.length === 0) {\n return null;\n }\n candidates.sort((a, b) => b.mtime - a.mtime);\n return candidates[0]?.path ?? null;\n}\n\nfunction collectJsonlCandidates(\n dir: string,\n sessionId: string | undefined,\n out: Array<{ path: string; mtime: number }>,\n): void {\n if (!existsSync(dir)) {\n return;\n }\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n if (!entry.isFile() || !entry.name.endsWith(\".jsonl\")) {\n continue;\n }\n const fullPath = join(dir, entry.name);\n if (\n sessionId &&\n !entry.name.includes(sessionId) &&\n basename(entry.name, \".jsonl\") !== sessionId\n ) {\n continue;\n }\n try {\n const st = statSync(fullPath);\n out.push({ path: fullPath, mtime: st.mtimeMs });\n } catch {\n // skip\n }\n }\n}\n","import { appendFileSync, mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport type { RepoContext } from \"./types.js\";\nimport { memoryPath } from \"../init/paths.js\";\n\nexport const DEBUG_LOG_FILE = \"hermes-debug.log\";\n\nlet logFilePath: string | null = null;\n\nexport function configureDebugLogging(\n repoRoot: string | null,\n enabled: boolean,\n): void {\n if (!enabled || !repoRoot) {\n logFilePath = null;\n return;\n }\n logFilePath = memoryPath(repoRoot, DEBUG_LOG_FILE);\n}\n\nfunction formatLine(phase: string, message: string): string {\n return `${new Date().toISOString()} hermes-repo [${phase}] ${message}`;\n}\n\nfunction writeToLogFile(line: string): void {\n if (!logFilePath) {\n return;\n }\n mkdirSync(dirname(logFilePath), { recursive: true });\n appendFileSync(logFilePath, `${line}\\n`, \"utf8\");\n}\n\nexport function debugLog(\n enabled: boolean,\n phase: string,\n message: string,\n): void {\n if (!enabled) {\n return;\n }\n const line = formatLine(phase, message);\n console.error(line);\n writeToLogFile(line);\n}\n\nexport function debugFromContext(\n ctx: RepoContext | null | undefined,\n phase: string,\n message: string,\n): void {\n debugLog(ctx?.config.debug === true, phase, message);\n}\n","import { join } from \"node:path\";\n\nexport const MEMORY_DIR = \".memory\";\n\nexport const MEMORY_SUBDIRS = [\n \"captures/semantic\",\n \"captures/episodic\",\n \"captures/procedural\",\n \"personal\",\n \"sessions\",\n \"refs\",\n \"topics\",\n \"skills\",\n \"team/decisions\",\n \"team/conflict-resolutions\",\n \"templates\",\n \".archive\",\n] as const;\n\nexport const GITKEEP_DIRS = [\n \"topics\",\n \"skills\",\n \"team/decisions\",\n \"team/conflict-resolutions\",\n] as const;\n\nexport const EXAMPLE_TEMPLATE_FILES = [\n \"capture-semantic.example.md\",\n \"capture-episodic.example.md\",\n \"capture-procedural.example.md\",\n \"PROMOTE_PR.md\",\n] as const;\n\nexport const SCAFFOLD_RELATIVE_PATHS = [\n \".memory/config.json\",\n \".memory/MEMORY.md\",\n \".memory/sessions/index.json\",\n \".memory/team/steward-log.md\",\n \"AGENTS.md\",\n \".claude/hooks.json\",\n] as const;\n\nexport function memoryPath(root: string, ...segments: string[]): string {\n return join(root, MEMORY_DIR, ...segments);\n}\n","import { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { AssistantId } from \"../init/assistants/types.js\";\nimport { findRepoRoot } from \"./findRepoRoot.js\";\nimport type { HermesConfig, RepoContext } from \"./types.js\";\n\nfunction isAssistantId(value: unknown): value is AssistantId {\n return typeof value === \"string\";\n}\n\nexport function readConfigAtRepo(repoRoot: string): HermesConfig | null {\n const configPath = join(repoRoot, \".memory\", \"config.json\");\n try {\n const raw = JSON.parse(readFileSync(configPath, \"utf8\")) as {\n version?: number;\n storage?: { backend?: string };\n assistants?: unknown;\n debug?: unknown;\n };\n if (raw.version !== 1 || raw.storage?.backend !== \"file\") {\n return null;\n }\n const assistants = Array.isArray(raw.assistants)\n ? raw.assistants.filter(isAssistantId)\n : [];\n return {\n version: 1,\n storage: { backend: \"file\" },\n assistants,\n debug: raw.debug === true,\n };\n } catch {\n return null;\n }\n}\n\nexport function loadRepoContext(cwd?: string): RepoContext | null {\n const repoRoot = findRepoRoot(cwd);\n if (!repoRoot) {\n return null;\n }\n const config = readConfigAtRepo(repoRoot);\n if (!config) {\n return null;\n }\n return { repoRoot, config };\n}\n","import { existsSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\n\nconst CONFIG_REL = join(\".memory\", \"config.json\");\n\nexport function findRepoRoot(startDir?: string): string | null {\n let dir = resolve(startDir ?? process.cwd());\n\n while (true) {\n if (existsSync(join(dir, CONFIG_REL))) {\n return dir;\n }\n const parent = dirname(dir);\n if (parent === dir) {\n return null;\n }\n dir = parent;\n }\n}\n","import type { ParsedSession } from \"./types.js\";\n\nconst STRONG_SIGNALS = [\n \"修复\",\n \"因为\",\n \"改成\",\n \"注意\",\n \"约定\",\n \"不要\",\n \"必须\",\n \"最佳实践\",\n \"根因\",\n \"原因\",\n \"fix\",\n \"because\",\n \"change to\",\n \"note\",\n \"convention\",\n \"never\",\n \"always\",\n \"root cause\",\n \"pattern\",\n \"架构\",\n \"决策\",\n];\n\nconst CORRECTION_RE =\n /不对|错了|不是这样|不应该|别用|stop|wrong|incorrect|改成|修正/i;\n\nconst SEMANTIC_SIGNAL_RE =\n /约定|必须|架构|决策|规范|convention|pattern|always|never/i;\n\n/** v0.2:不因 fileChanges===0 单独否决(见 phase-2 已确认决策) */\nexport function shouldCapture(session: ParsedSession): boolean {\n if (session.messages.length < 3) {\n return false;\n }\n\n const hasStrongSignal = STRONG_SIGNALS.some((w) =>\n session.text.toLowerCase().includes(w.toLowerCase()),\n );\n const hasUserCorrection = session.messages.some(\n (m) => m.role === \"user\" && CORRECTION_RE.test(m.text),\n );\n const hasComplexTask = session.toolCalls > 5;\n\n return hasStrongSignal || hasUserCorrection || hasComplexTask;\n}\n\nexport function inferCaptureType(session: ParsedSession): \"semantic\" | \"episodic\" {\n if (SEMANTIC_SIGNAL_RE.test(session.text)) {\n return \"semantic\";\n }\n return \"episodic\";\n}\n","import { readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { memoryPath } from \"../init/paths.js\";\n\nexport interface SessionIndexEntry {\n id: string;\n capturedAt: string;\n captureFile: string;\n assistant: string;\n}\n\ninterface SessionsIndexFile {\n version: number;\n sessions: SessionIndexEntry[];\n}\n\nexport function readSessionsIndex(repoRoot: string): SessionsIndexFile {\n const indexPath = memoryPath(repoRoot, \"sessions\", \"index.json\");\n try {\n const data = JSON.parse(readFileSync(indexPath, \"utf8\")) as SessionsIndexFile;\n if (data.version === 1 && Array.isArray(data.sessions)) {\n return data;\n }\n } catch {\n // fall through\n }\n return { version: 1, sessions: [] };\n}\n\nexport function appendSessionIndex(\n repoRoot: string,\n entry: SessionIndexEntry,\n): void {\n const index = readSessionsIndex(repoRoot);\n index.sessions.push(entry);\n const indexPath = memoryPath(repoRoot, \"sessions\", \"index.json\");\n writeFileSync(indexPath, `${JSON.stringify(index, null, 2)}\\n`, \"utf8\");\n}\n\nexport function relativeCapturePath(\n type: string,\n filename: string,\n): string {\n return join(\".memory\", \"captures\", type, filename).replace(/\\\\/g, \"/\");\n}\n","import { existsSync, mkdirSync, readdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { memoryPath } from \"../init/paths.js\";\nimport type { CaptureMemoryType, ParsedSession } from \"./types.js\";\n\nfunction todayString(): string {\n return new Date().toISOString().slice(0, 10);\n}\n\nfunction nextCaptureFilename(repoRoot: string, type: CaptureMemoryType): string {\n const dir = memoryPath(repoRoot, \"captures\", type);\n mkdirSync(dir, { recursive: true });\n const date = todayString();\n const prefix = `capture-${date}-`;\n let max = 0;\n if (existsSync(dir)) {\n for (const name of readdirSync(dir)) {\n if (name.startsWith(prefix) && name.endsWith(\".md\")) {\n const num = Number.parseInt(name.slice(prefix.length, -3), 10);\n if (!Number.isNaN(num) && num > max) {\n max = num;\n }\n }\n }\n }\n const seq = String(max + 1).padStart(3, \"0\");\n return `capture-${date}-${seq}.md`;\n}\n\nfunction buildBody(session: ParsedSession): string {\n const recent = session.messages.slice(-6);\n const context = recent\n .map((m) => `**${m.role}**: ${m.text.slice(0, 500)}`)\n .join(\"\\n\\n\");\n\n return `## 上下文\n\n自动捕获自 Claude Code 会话 \\`${session.sessionId}\\`。\n\n## 发现\n\n${context || \"(无提取内容)\"}\n\n## 影响\n\n(待 consolidate 或人工补充)\n`;\n}\n\nexport function writeCaptureFile(\n repoRoot: string,\n session: ParsedSession,\n type: CaptureMemoryType,\n): { absolutePath: string; filename: string } {\n const filename = nextCaptureFilename(repoRoot, type);\n const absolutePath = memoryPath(repoRoot, \"captures\", type, filename);\n const date = todayString();\n\n const content = `---\ntype: ${type}\ndate: ${date}\nsession: ${session.sessionId}\ntags: [auto-capture, claude-code]\nscope: all\nconfidence: pending\n---\n\n${buildBody(session)}\n`;\n\n writeFileSync(absolutePath, content, \"utf8\");\n return { absolutePath, filename };\n}\n","import { readFileSync } from \"node:fs\";\nimport { basename } from \"node:path\";\nimport type { ParsedSession, SessionMessage } from \"../types.js\";\n\nconst FILE_CHANGE_TOOLS =\n /^(Write|Edit|MultiEdit|NotebookEdit|write|edit)$/i;\n\nfunction extractText(record: Record<string, unknown>): string {\n if (typeof record.content === \"string\") {\n return record.content;\n }\n const message = record.message;\n if (message && typeof message === \"object\") {\n const msg = message as Record<string, unknown>;\n if (typeof msg.content === \"string\") {\n return msg.content;\n }\n if (Array.isArray(msg.content)) {\n return msg.content\n .map((part) => {\n if (part && typeof part === \"object\" && \"text\" in part) {\n return String((part as { text: string }).text);\n }\n return \"\";\n })\n .join(\"\\n\");\n }\n }\n return \"\";\n}\n\nfunction inferRole(record: Record<string, unknown>): string {\n if (typeof record.role === \"string\") {\n return record.role;\n }\n if (typeof record.type === \"string\") {\n const t = record.type.toLowerCase();\n if (t === \"user\" || t === \"human\") return \"user\";\n if (t === \"assistant\") return \"assistant\";\n }\n return \"unknown\";\n}\n\nfunction isToolUse(record: Record<string, unknown>): boolean {\n const t = String(record.type ?? \"\").toLowerCase();\n return t === \"tool_use\" || t === \"tool\";\n}\n\nfunction toolName(record: Record<string, unknown>): string {\n if (typeof record.name === \"string\") return record.name;\n const tool = record.tool;\n if (tool && typeof tool === \"object\" && \"name\" in tool) {\n return String((tool as { name: string }).name);\n }\n return \"\";\n}\n\nexport function parseJsonlFile(jsonlPath: string): ParsedSession {\n const sessionId = basename(jsonlPath, \".jsonl\");\n const raw = readFileSync(jsonlPath, \"utf8\");\n const messages: SessionMessage[] = [];\n let fileChanges = 0;\n let toolCalls = 0;\n\n for (const line of raw.split(\"\\n\")) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n try {\n const record = JSON.parse(trimmed) as Record<string, unknown>;\n if (isToolUse(record)) {\n toolCalls += 1;\n const name = toolName(record);\n if (FILE_CHANGE_TOOLS.test(name)) {\n fileChanges += 1;\n }\n continue;\n }\n const role = inferRole(record);\n const text = extractText(record);\n if (text) {\n messages.push({ role, text });\n }\n } catch {\n // skip malformed lines\n }\n }\n\n const text = messages.map((m) => m.text).join(\"\\n\");\n\n return {\n sessionId,\n messages,\n text,\n fileChanges,\n toolCalls,\n };\n}\n","import { debugLog } from \"../../config/debugLog.js\";\nimport { inferCaptureType, shouldCapture } from \"../shouldCapture.js\";\nimport {\n appendSessionIndex,\n relativeCapturePath,\n} from \"../sessionsIndex.js\";\nimport type { CaptureResult } from \"../types.js\";\nimport { writeCaptureFile } from \"../writeCapture.js\";\nimport { parseJsonlFile } from \"./parseJsonl.js\";\nimport { resolveSessionJsonlPath } from \"./resolveSession.js\";\n\nexport function runClaudeCodeCapture(\n repoRoot: string,\n cwd?: string,\n dryRun?: boolean,\n options?: { transcriptPath?: string; debug?: boolean },\n): CaptureResult {\n const jsonlPath = resolveSessionJsonlPath(repoRoot, {\n cwd,\n transcriptPath: options?.transcriptPath,\n });\n if (!jsonlPath) {\n return { written: false, reason: \"no session jsonl found\" };\n }\n\n const session = parseJsonlFile(jsonlPath);\n if (!shouldCapture(session)) {\n return {\n written: false,\n reason: `heuristic rejected (messages=${session.messages.length}, toolCalls=${session.toolCalls})`,\n jsonlPath,\n };\n }\n\n const type = inferCaptureType(session);\n\n if (dryRun) {\n debugLog(\n options?.debug === true,\n \"capture\",\n `[dry-run] would capture ${type} session=${session.sessionId} from ${jsonlPath}`,\n );\n return { written: false, reason: \"dry-run\", jsonlPath };\n }\n\n const { filename } = writeCaptureFile(repoRoot, session, type);\n const captureFile = relativeCapturePath(type, filename);\n\n appendSessionIndex(repoRoot, {\n id: session.sessionId,\n capturedAt: new Date().toISOString(),\n captureFile,\n assistant: \"claude-code\",\n });\n\n return { written: true, capturePath: captureFile };\n}\n","import type { RepoContext } from \"../config/types.js\";\nimport { runClaudeCodeCapture } from \"./claude-code/run.js\";\nimport type { CaptureResult } from \"./types.js\";\n\nexport function routeCapture(\n ctx: RepoContext,\n options: {\n cwd?: string;\n dryRun?: boolean;\n transcriptPath?: string;\n },\n): CaptureResult {\n if (!ctx.config.assistants.includes(\"claude-code\")) {\n return { written: false, reason: \"claude-code not in assistants\" };\n }\n\n return runClaudeCodeCapture(ctx.repoRoot, options.cwd, options.dryRun, {\n transcriptPath: options.transcriptPath,\n debug: ctx.config.debug === true,\n });\n}\n","import { debugLog } from \"../config/debugLog.js\";\nimport { loadRepoContext } from \"../config/readConfig.js\";\nimport { routeCapture } from \"./router.js\";\nimport type { CaptureResult } from \"./types.js\";\n\nexport interface CaptureOptions {\n cwd?: string;\n dryRun?: boolean;\n strict?: boolean;\n /** Claude Stop hook stdin 中的 transcript_path */\n transcriptPath?: string;\n}\n\nfunction logCaptureResult(debug: boolean, result: CaptureResult): void {\n if (!debug) {\n return;\n }\n if (result.written && result.capturePath) {\n debugLog(true, \"capture\", `ok: ${result.capturePath}`);\n return;\n }\n const parts = [result.reason ?? \"unknown\"];\n if (result.jsonlPath) {\n parts.push(`jsonl=${result.jsonlPath}`);\n }\n debugLog(true, \"capture\", `skip: ${parts.join(\", \")}`);\n}\n\nexport function runCapture(options: CaptureOptions = {}): CaptureResult {\n const ctx = loadRepoContext(options.cwd);\n if (!ctx) {\n return { written: false, reason: \"not initialized\" };\n }\n\n const result = routeCapture(ctx, {\n cwd: options.cwd,\n dryRun: options.dryRun,\n transcriptPath: options.transcriptPath,\n });\n logCaptureResult(ctx.config.debug, result);\n return result;\n}\n","import { debugLog } from \"./config/debugLog.js\";\n\n/** Hook 路径下失败仍 exit 0,避免阻塞 Claude Code */\nexport function hookExit(code: number, strict?: boolean): never {\n process.exit(strict ? code : code === 0 ? 0 : 0);\n}\n\nexport function finalizeHookCommand(\n fn: () => void | Promise<void>,\n strict?: boolean,\n debug?: boolean,\n): void {\n void (async () => {\n try {\n await fn();\n process.exit(0);\n } catch (error) {\n debugLog(debug === true, \"hook\", error instanceof Error ? error.message : String(error));\n process.exit(strict ? 1 : 0);\n }\n })();\n}\n","import { readHookTranscriptPathSync } from \"../capture/claude-code/resolveSession.js\";\nimport { runCapture } from \"../capture/runCapture.js\";\nimport { configureDebugLogging } from \"../config/debugLog.js\";\nimport { loadRepoContext } from \"../config/readConfig.js\";\nimport { finalizeHookCommand } from \"../hookExit.js\";\n\nexport interface CaptureCommandOptions {\n cwd?: string;\n dryRun?: boolean;\n strict?: boolean;\n}\n\nexport function runCaptureCommand(opts: CaptureCommandOptions): void {\n const ctx = loadRepoContext(opts.cwd);\n const debug = ctx?.config.debug === true;\n configureDebugLogging(ctx?.repoRoot ?? null, debug);\n const transcriptPath = readHookTranscriptPathSync();\n\n finalizeHookCommand(() => {\n runCapture({\n cwd: opts.cwd,\n dryRun: opts.dryRun,\n strict: opts.strict,\n transcriptPath: transcriptPath ?? undefined,\n });\n }, opts.strict, debug);\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { debugFromContext } from \"../config/debugLog.js\";\nimport { loadRepoContext } from \"../config/readConfig.js\";\nimport { memoryPath } from \"../init/paths.js\";\nimport { INJECT_MAX_CHARS } from \"./constants.js\";\n\nexport function runInject(cwd?: string): { injected: boolean; chars: number } {\n const ctx = loadRepoContext(cwd);\n if (!ctx) {\n return { injected: false, chars: 0 };\n }\n\n const memoryFile = memoryPathOnDisk(ctx.repoRoot);\n if (!existsSync(memoryFile)) {\n debugFromContext(ctx, \"inject\", \"skip: MEMORY.md missing\");\n return { injected: false, chars: 0 };\n }\n\n const contentRaw = readFileSync(memoryFile, \"utf8\");\n if (!contentRaw.trim()) {\n debugFromContext(ctx, \"inject\", \"skip: MEMORY.md empty\");\n return { injected: false, chars: 0 };\n }\n\n let content = contentRaw;\n if (content.length > INJECT_MAX_CHARS) {\n content = `${content.slice(0, INJECT_MAX_CHARS)}\\n\\n...(truncated)`;\n }\n\n process.stdout.write(content);\n if (!content.endsWith(\"\\n\")) {\n process.stdout.write(\"\\n\");\n }\n\n debugFromContext(ctx, \"inject\", `ok: injected ${content.length} chars`);\n\n return { injected: true, chars: content.length };\n}\n\nfunction memoryPathOnDisk(repoRoot: string): string {\n return memoryPath(repoRoot, \"MEMORY.md\");\n}\n","/** Level 0 注入上限(参考设计文档 ~2.2K chars) */\nexport const INJECT_MAX_CHARS = 2200;\n","import { configureDebugLogging } from \"../config/debugLog.js\";\nimport { loadRepoContext } from \"../config/readConfig.js\";\nimport { finalizeHookCommand } from \"../hookExit.js\";\nimport { runInject } from \"../inject/runInject.js\";\n\nexport interface InjectCommandOptions {\n cwd?: string;\n strict?: boolean;\n}\n\nexport function runInjectCommand(opts: InjectCommandOptions): void {\n const ctx = loadRepoContext(opts.cwd);\n const debug = ctx?.config.debug === true;\n configureDebugLogging(ctx?.repoRoot ?? null, debug);\n\n finalizeHookCommand(() => {\n runInject(opts.cwd);\n }, opts.strict, debug);\n}\n","import { spawnSync } from \"node:child_process\";\nimport { resolve } from \"node:path\";\nimport {\n DEFAULT_ASSISTANT_IDS,\n parseToolsArg,\n validateAssistantSelection,\n} from \"./assistants/registry.js\";\nimport type { AssistantId } from \"./assistants/types.js\";\nimport { ensureMemoryTree } from \"./ensureDirs.js\";\nimport { mergeAssistants } from \"./mergeAssistants.js\";\nimport { mergeHermesGitignore } from \"./mergeGitignore.js\";\nimport { gatherInitOptions } from \"./prompts.js\";\nimport type { InitCliOptions, InitReport } from \"./types.js\";\nimport { writeScaffoldFiles } from \"./writeScaffoldFile.js\";\n\nexport function resolveTargetDir(cwd?: string): string {\n const targetDir = resolve(cwd ?? process.cwd());\n const gitCheck = spawnSync(\"git\", [\"rev-parse\", \"--is-inside-work-tree\"], {\n cwd: targetDir,\n encoding: \"utf8\",\n });\n if (gitCheck.status !== 0) {\n console.warn(\n \"warn: 当前目录可能不是 Git 仓库,init 仍会继续(建议在有 git 的项目根目录执行)\",\n );\n }\n return targetDir;\n}\n\nfunction resolveSelectedAssistants(opts: InitCliOptions): AssistantId[] {\n if (opts.assistants) {\n validateAssistantSelection(opts.assistants);\n return opts.assistants;\n }\n if (opts.tools) {\n if (!opts.yes) {\n console.error(\"init --tools requires -y in non-interactive mode\");\n process.exit(1);\n }\n return parseToolsArg(opts.tools);\n }\n if (opts.yes) {\n return [...DEFAULT_ASSISTANT_IDS];\n }\n return [];\n}\n\nexport function printInitReport(report: InitReport): void {\n const created = report.files.filter((f) => f.action === \"created\");\n const skipped = report.files.filter((f) => f.action === \"skipped\");\n const overwritten = report.files.filter((f) => f.action === \"overwritten\");\n\n console.log(`\\nhermes-repo init 完成 → ${report.targetDir}\\n`);\n console.log(`已启用助手: ${report.assistants.join(\", \")}\\n`);\n\n if (created.length > 0) {\n console.log(`已创建 (${created.length}):`);\n for (const f of created) {\n console.log(` + ${f.path}`);\n }\n }\n\n if (overwritten.length > 0) {\n console.log(`已覆盖 (${overwritten.length}):`);\n for (const f of overwritten) {\n console.log(` ~ ${f.path}`);\n }\n }\n\n if (skipped.length > 0) {\n console.log(`已跳过 (${skipped.length}):`);\n for (const f of skipped) {\n console.log(` - ${f.path}`);\n }\n }\n\n if (report.gitignoreAction) {\n console.log(`\\n.gitignore: ${report.gitignoreAction} hermes-repo 标记块`);\n }\n\n for (const warning of report.warnings) {\n console.warn(`warn: ${warning}`);\n }\n\n console.log(\"\");\n}\n\nexport async function runInit(opts: InitCliOptions): Promise<InitReport> {\n if (!process.stdin.isTTY && !opts.yes) {\n console.error(\"init requires -y in non-interactive environments\");\n process.exit(1);\n }\n\n if (opts.tools && !opts.yes) {\n console.error(\"init --tools requires -y\");\n process.exit(1);\n }\n\n let resolved: {\n targetDir: string;\n force: boolean;\n includeExampleTemplates: boolean;\n assistants: AssistantId[];\n cancelled: boolean;\n };\n\n if (opts.yes) {\n const targetDir = resolveTargetDir(opts.cwd);\n const selected = resolveSelectedAssistants(opts);\n resolved = {\n targetDir,\n force: Boolean(opts.force),\n includeExampleTemplates: opts.includeExampleTemplates ?? true,\n assistants: mergeAssistants(targetDir, selected),\n cancelled: false,\n };\n } else {\n const gathered = await gatherInitOptions(opts);\n if (gathered.cancelled) {\n console.log(\"init 已取消\");\n process.exit(0);\n }\n resolved = {\n ...gathered,\n assistants: mergeAssistants(gathered.targetDir, gathered.assistants),\n };\n }\n\n const report: InitReport = {\n targetDir: resolved.targetDir,\n assistants: resolved.assistants,\n files: [],\n warnings: [],\n };\n\n ensureMemoryTree(resolved.targetDir);\n writeScaffoldFiles(resolved.targetDir, resolved, report);\n\n const gitignore = mergeHermesGitignore(resolved.targetDir);\n report.gitignoreAction = gitignore.action;\n if (gitignore.warnBroadMemoryIgnore) {\n report.warnings.push(\n \".gitignore 中存在对整个 .memory/ 的忽略规则,可能与团队层放行冲突,请手动检查\",\n );\n }\n\n printInitReport(report);\n return report;\n}\n","import { mkdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { renderTemplate } from \"../templateDir.js\";\nimport { writeIfAllowed } from \"../scaffoldWrite.js\";\nimport type { AssistantAdapter, WriteContext } from \"./types.js\";\n\nexport const claudeCodeAdapter: AssistantAdapter = {\n id: \"claude-code\",\n label: \"Claude Code(Stop / SessionStart hooks)\",\n available: true,\n scaffoldPaths: [\".claude/hooks.json\"],\n write(ctx: WriteContext): void {\n const hooksDir = join(ctx.repoRoot, \".claude\");\n mkdirSync(hooksDir, { recursive: true });\n const hooksPath = join(hooksDir, \"hooks.json\");\n writeIfAllowed(\n ctx.report,\n hooksPath,\n \".claude/hooks.json\",\n renderTemplate(\"hooks.json.tpl\"),\n ctx.force,\n );\n },\n};\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { PACKAGE_NAME } from \"../index.js\";\n\nfunction resolveTemplateDir(): string {\n const here = dirname(fileURLToPath(import.meta.url));\n const candidates = [\n join(here, \"templates\"),\n join(here, \"..\", \"..\", \"templates\"),\n ];\n for (const dir of candidates) {\n if (existsSync(dir)) {\n return dir;\n }\n }\n return join(here, \"templates\");\n}\n\nconst templateDir = resolveTemplateDir();\n\nexport function resolveTemplatePath(name: string): string {\n return join(templateDir, name);\n}\n\nexport function readTemplate(name: string): string {\n return readFileSync(resolveTemplatePath(name), \"utf8\");\n}\n\nexport function renderTemplate(name: string): string {\n const raw = readTemplate(name);\n return raw.replaceAll(\"__PACKAGE_NAME__\", PACKAGE_NAME);\n}\n","import { readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nexport const PACKAGE_NAME = \"@riconext/hermes-repo\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nexport function readPkgVersion(): string {\n const pkgPath = join(__dirname, \"..\", \"package.json\");\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf8\")) as { version: string };\n return pkg.version;\n}\n","import { existsSync, writeFileSync } from \"node:fs\";\nimport type { InitFileAction, InitReport } from \"./types.js\";\n\nexport function shouldWriteFile(\n absolutePath: string,\n force: boolean,\n): { write: boolean; action: InitFileAction } {\n if (!existsSync(absolutePath)) {\n return { write: true, action: \"created\" };\n }\n if (force) {\n return { write: true, action: \"overwritten\" };\n }\n return { write: false, action: \"skipped\" };\n}\n\nexport function writeIfAllowed(\n report: InitReport,\n absolutePath: string,\n relativePath: string,\n content: string,\n force: boolean,\n): void {\n const { write, action } = shouldWriteFile(absolutePath, force);\n if (!write) {\n report.files.push({ path: relativePath, action });\n return;\n }\n writeFileSync(absolutePath, content, \"utf8\");\n report.files.push({ path: relativePath, action });\n}\n","import type { AssistantAdapter, WriteContext } from \"./types.js\";\n\n/** v0.9+:init 写入 .cursor/ hooks;当前仅占位 */\nexport const cursorAdapter: AssistantAdapter = {\n id: \"cursor\",\n label: \"Cursor\",\n available: false,\n scaffoldPaths: [],\n write(_ctx: WriteContext): void {\n // not available in v0.1.x\n },\n};\n","import type { AssistantAdapter, AssistantId } from \"./types.js\";\nimport { claudeCodeAdapter } from \"./claude-code.js\";\nimport { cursorAdapter } from \"./cursor.js\";\n\nexport const DEFAULT_ASSISTANT_IDS: AssistantId[] = [\"claude-code\"];\n\nconst ALL_ADAPTERS: AssistantAdapter[] = [claudeCodeAdapter, cursorAdapter];\n\nconst ADAPTER_BY_ID = new Map<AssistantId, AssistantAdapter>(\n ALL_ADAPTERS.map((a) => [a.id, a]),\n);\n\nexport function getAdapter(id: AssistantId): AssistantAdapter {\n const adapter = ADAPTER_BY_ID.get(id);\n if (!adapter) {\n throw new Error(`Unknown assistant id: ${id}`);\n }\n return adapter;\n}\n\nexport function listAvailable(): AssistantAdapter[] {\n return ALL_ADAPTERS.filter((a) => a.available);\n}\n\nexport function isKnownAssistantId(id: string): id is AssistantId {\n return ADAPTER_BY_ID.has(id as AssistantId);\n}\n\nexport function parseToolsArg(tools: string): AssistantId[] {\n const ids = tools\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean);\n\n if (ids.length === 0) {\n throw new Error(\"init --tools requires at least one assistant id\");\n }\n\n const result: AssistantId[] = [];\n for (const id of ids) {\n if (!isKnownAssistantId(id)) {\n throw new Error(`Unknown assistant id: ${id}`);\n }\n const adapter = getAdapter(id);\n if (!adapter.available) {\n throw new Error(`Assistant not available yet: ${id}`);\n }\n result.push(id);\n }\n return result;\n}\n\nexport function validateAssistantSelection(ids: AssistantId[]): void {\n if (ids.length === 0) {\n throw new Error(\"At least one assistant must be selected\");\n }\n for (const id of ids) {\n const adapter = getAdapter(id);\n if (!adapter.available) {\n throw new Error(`Assistant not available yet: ${id}`);\n }\n }\n}\n","import { mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { GITKEEP_DIRS, MEMORY_DIR, MEMORY_SUBDIRS } from \"./paths.js\";\n\nexport function ensureMemoryTree(repoRoot: string): void {\n const memoryRoot = join(repoRoot, MEMORY_DIR);\n mkdirSync(memoryRoot, { recursive: true });\n\n for (const sub of MEMORY_SUBDIRS) {\n mkdirSync(join(memoryRoot, sub), { recursive: true });\n }\n\n mkdirSync(join(repoRoot, \".claude\"), { recursive: true });\n\n for (const sub of GITKEEP_DIRS) {\n const keepPath = join(memoryRoot, sub, \".gitkeep\");\n writeFileSync(keepPath, \"\", { flag: \"a\" });\n }\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport type { AssistantId } from \"./assistants/types.js\";\nimport { memoryPath } from \"./paths.js\";\n\nfunction readExistingAssistants(repoRoot: string): AssistantId[] {\n const configPath = memoryPath(repoRoot, \"config.json\");\n if (!existsSync(configPath)) {\n return [];\n }\n try {\n const config = JSON.parse(readFileSync(configPath, \"utf8\")) as {\n assistants?: unknown;\n };\n if (!Array.isArray(config.assistants)) {\n return [];\n }\n return config.assistants.filter((id): id is AssistantId => typeof id === \"string\");\n } catch {\n return [];\n }\n}\n\n/** 与已有 config.assistants 做并集(保留已有 id + 追加本次选择) */\nexport function mergeAssistants(\n repoRoot: string,\n selected: AssistantId[],\n): AssistantId[] {\n const existing = readExistingAssistants(repoRoot);\n return [...new Set([...existing, ...selected])];\n}\n","import { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { readTemplate } from \"./templateDir.js\";\n\nconst START_MARKER = \"# >>> hermes-repo memory (do not edit this block manually)\";\nconst END_MARKER = \"# <<< hermes-repo memory\";\n\nexport type GitignoreMergeAction = \"created\" | \"updated\" | \"replaced\" | \"appended\";\n\nexport function mergeHermesGitignore(repoRoot: string): {\n action: GitignoreMergeAction;\n warnBroadMemoryIgnore: boolean;\n} {\n const block = readTemplate(\"gitignore-block.txt\").trimEnd() + \"\\n\";\n const gitignorePath = join(repoRoot, \".gitignore\");\n const contentBefore = existsSync(gitignorePath)\n ? readFileSync(gitignorePath, \"utf8\")\n : \"\";\n\n const warnBroadMemoryIgnore =\n contentBefore.length > 0 &&\n !contentBefore.includes(START_MARKER) &&\n /(^|\\n)\\.memory\\/\\s*$/m.test(contentBefore);\n\n if (!existsSync(gitignorePath)) {\n writeFileSync(gitignorePath, `${block}\\n`, \"utf8\");\n return { action: \"created\", warnBroadMemoryIgnore: false };\n }\n\n const startIdx = contentBefore.indexOf(START_MARKER);\n const endIdx = contentBefore.indexOf(END_MARKER);\n\n if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {\n const before = contentBefore.slice(0, startIdx);\n const after = contentBefore.slice(endIdx + END_MARKER.length);\n const next = `${before}${block}${after}`.replace(/\\n{3,}/g, \"\\n\\n\");\n writeFileSync(gitignorePath, next.endsWith(\"\\n\") ? next : `${next}\\n`, \"utf8\");\n return { action: \"replaced\", warnBroadMemoryIgnore };\n }\n\n if (startIdx !== -1) {\n const before = contentBefore.slice(0, startIdx);\n const next = `${before}${block}\\n`;\n writeFileSync(gitignorePath, next, \"utf8\");\n return { action: \"updated\", warnBroadMemoryIgnore };\n }\n\n const separator = contentBefore.endsWith(\"\\n\") || contentBefore.length === 0 ? \"\\n\" : \"\\n\\n\";\n writeFileSync(gitignorePath, `${contentBefore}${separator}${block}\\n`, \"utf8\");\n return { action: \"appended\", warnBroadMemoryIgnore };\n}\n","import { checkbox, confirm, input } from \"@inquirer/prompts\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { listAvailable } from \"./assistants/registry.js\";\nimport type { AssistantId } from \"./assistants/types.js\";\nimport type { InitCliOptions, InitResolvedOptions } from \"./types.js\";\nimport { memoryPath } from \"./paths.js\";\n\nfunction isInitialized(targetDir: string): boolean {\n const configPath = memoryPath(targetDir, \"config.json\");\n if (!existsSync(configPath)) {\n return false;\n }\n try {\n const config = JSON.parse(readFileSync(configPath, \"utf8\")) as {\n version?: number;\n };\n return config.version === 1;\n } catch {\n return false;\n }\n}\n\nexport async function gatherInitOptions(\n opts: InitCliOptions,\n): Promise<InitResolvedOptions> {\n const defaultDir = resolve(opts.cwd ?? process.cwd());\n\n const targetInput = await input({\n message: \"目标目录(Git 仓库根)\",\n default: defaultDir,\n });\n const targetDir = resolve(targetInput);\n\n const assistants = (await checkbox({\n message: \"选择要接入的编程助手(可多选)\",\n choices: listAvailable().map((a) => ({\n name: a.label,\n value: a.id,\n checked: a.id === \"claude-code\",\n })),\n validate: (value) => value.length > 0 || \"请至少选择一项\",\n })) as AssistantId[];\n\n const includeExampleTemplates = await confirm({\n message: \"是否写入 capture 示例模板到 .memory/templates/?\",\n default: true,\n });\n\n if (isInitialized(targetDir)) {\n const continueInit = await confirm({\n message: \"检测到已有 .memory/config.json,是否仅补全缺失项?\",\n default: true,\n });\n if (!continueInit) {\n return {\n targetDir,\n force: false,\n includeExampleTemplates,\n assistants,\n cancelled: true,\n };\n }\n }\n\n return {\n targetDir,\n force: Boolean(opts.force),\n includeExampleTemplates,\n assistants,\n cancelled: false,\n };\n}\n","import { copyFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { getAdapter } from \"./assistants/registry.js\";\nimport type { AssistantId } from \"./assistants/types.js\";\nimport type { InitReport, InitResolvedOptions } from \"./types.js\";\nimport { EXAMPLE_TEMPLATE_FILES, memoryPath } from \"./paths.js\";\nimport { renderTemplate, resolveTemplatePath } from \"./templateDir.js\";\nimport { mergeConfigForInit } from \"./mergeConfig.js\";\nimport { shouldWriteFile, writeIfAllowed } from \"./scaffoldWrite.js\";\n\nexport { shouldWriteFile } from \"./scaffoldWrite.js\";\n\nexport function buildConfigJson(assistants: AssistantId[]): string {\n return `${JSON.stringify(\n {\n version: 1,\n storage: { backend: \"file\" },\n assistants,\n debug: false,\n },\n null,\n 2,\n )}\\n`;\n}\n\nfunction writeConfigJson(\n report: InitReport,\n repoRoot: string,\n assistants: AssistantId[],\n): void {\n const { content, action } = mergeConfigForInit(repoRoot, assistants);\n const absolutePath = memoryPath(repoRoot, \"config.json\");\n writeFileSync(absolutePath, content, \"utf8\");\n report.files.push({ path: \".memory/config.json\", action });\n}\n\nfunction copyTemplateIfAllowed(\n report: InitReport,\n templateName: string,\n destAbsolute: string,\n relativePath: string,\n force: boolean,\n): void {\n const { write, action } = shouldWriteFile(destAbsolute, force);\n if (!write) {\n report.files.push({ path: relativePath, action });\n return;\n }\n copyFileSync(resolveTemplatePath(templateName), destAbsolute);\n report.files.push({ path: relativePath, action });\n}\n\nexport function writeScaffoldFiles(\n repoRoot: string,\n opts: InitResolvedOptions,\n report: InitReport,\n): void {\n const { force, includeExampleTemplates, assistants } = opts;\n\n writeConfigJson(report, repoRoot, assistants);\n\n writeIfAllowed(\n report,\n memoryPath(repoRoot, \"MEMORY.md\"),\n \".memory/MEMORY.md\",\n renderTemplate(\"MEMORY.md.tpl\"),\n force,\n );\n\n writeIfAllowed(\n report,\n memoryPath(repoRoot, \"sessions\", \"index.json\"),\n \".memory/sessions/index.json\",\n `${JSON.stringify({ version: 1, sessions: [] }, null, 2)}\\n`,\n force,\n );\n\n writeIfAllowed(\n report,\n memoryPath(repoRoot, \"team\", \"steward-log.md\"),\n \".memory/team/steward-log.md\",\n renderTemplate(\"steward-log.md.tpl\"),\n force,\n );\n\n writeIfAllowed(\n report,\n join(repoRoot, \"AGENTS.md\"),\n \"AGENTS.md\",\n renderTemplate(\"AGENTS.md.tpl\"),\n force,\n );\n\n for (const id of assistants) {\n getAdapter(id).write({ repoRoot, force, report });\n }\n\n if (includeExampleTemplates) {\n for (const name of EXAMPLE_TEMPLATE_FILES) {\n const dest = memoryPath(repoRoot, \"templates\", name);\n copyTemplateIfAllowed(\n report,\n name,\n dest,\n `.memory/templates/${name}`,\n force,\n );\n }\n }\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport type { AssistantId } from \"./assistants/types.js\";\nimport type { InitFileAction } from \"./types.js\";\nimport { memoryPath } from \"./paths.js\";\n\n/** init 每次都会写入的 config 字段(其余顶层 / storage 子字段保留) */\nexport function mergeConfigForInit(\n repoRoot: string,\n assistants: AssistantId[],\n): { content: string; action: InitFileAction } {\n const configPath = memoryPath(repoRoot, \"config.json\");\n const existed = existsSync(configPath);\n\n let existing: Record<string, unknown> = {};\n if (existed) {\n try {\n existing = JSON.parse(readFileSync(configPath, \"utf8\")) as Record<\n string,\n unknown\n >;\n } catch {\n existing = {};\n }\n }\n\n const prevStorage =\n existing.storage &&\n typeof existing.storage === \"object\" &&\n !Array.isArray(existing.storage)\n ? (existing.storage as Record<string, unknown>)\n : {};\n\n const merged: Record<string, unknown> = {\n ...existing,\n version: 1,\n storage: {\n ...prevStorage,\n backend: \"file\",\n },\n assistants,\n debug: existing.debug === true,\n };\n\n return {\n content: `${JSON.stringify(merged, null, 2)}\\n`,\n action: existed ? \"overwritten\" : \"created\",\n };\n}\n","import type { InitCliOptions } from \"../init/types.js\";\nimport { runInit } from \"../init/runInit.js\";\n\nexport async function runInitCommand(opts: InitCliOptions): Promise<void> {\n try {\n await runInit(opts);\n } catch (error) {\n console.error(error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n}\n"],"mappings":"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","names":["join","join","readFileSync","join","existsSync","dirname","join","resolve","join","readFileSync","readFileSync","join","readFileSync","join","existsSync","mkdirSync","readdirSync","writeFileSync","mkdirSync","existsSync","readdirSync","writeFileSync","readFileSync","basename","text","existsSync","readFileSync","existsSync","readFileSync","resolve","mkdirSync","join","existsSync","readFileSync","dirname","join","fileURLToPath","readFileSync","dirname","join","dirname","fileURLToPath","join","existsSync","readFileSync","existsSync","writeFileSync","join","mkdirSync","mkdirSync","writeFileSync","join","join","mkdirSync","writeFileSync","existsSync","readFileSync","existsSync","readFileSync","existsSync","readFileSync","writeFileSync","join","join","existsSync","readFileSync","writeFileSync","existsSync","readFileSync","resolve","existsSync","readFileSync","resolve","writeFileSync","join","existsSync","readFileSync","existsSync","readFileSync","writeFileSync","join","resolve"]}
@@ -0,0 +1,118 @@
1
+ # 项目指令
2
+
3
+ ## 记忆系统
4
+
5
+ 本项目使用 @riconext/hermes-repo 管理 AI 助手记忆。
6
+
7
+ 核心文件:
8
+
9
+ - `.memory/MEMORY.md` — 注入到每次会话的摘要
10
+ - `.memory/captures/` — 按类型(semantic / episodic / procedural)归档的原始捕获
11
+ - `.memory/topics/` — 整理后的主题记忆
12
+
13
+ ## 使用记忆
14
+
15
+ - 开始新任务前,先读取 `.memory/MEMORY.md`
16
+ - 如需查找历史经验: `npx @riconext/hermes-repo search <关键词>`
17
+ - 查看特定捕获: `cat .memory/captures/<type>/<文件名>.md`
18
+ - 查看主题: `cat .memory/topics/<主题>.md`
19
+ - 查看可用技能: `cat .memory/skills/*/SKILL.md`
20
+
21
+ ## 技能使用
22
+
23
+ 项目自动从重复的流程记忆中生成技能(SKILL.md),存在 `.memory/skills/`。
24
+
25
+ ### 何时加载技能
26
+
27
+ 当你需要执行以下操作时,先查看是否有对应的技能:
28
+
29
+ 1. 部署 / 发布 / 回滚
30
+ 2. 数据库迁移
31
+ 3. 新模块 / 新页面创建
32
+ 4. 重复性配置操作
33
+ 5. 调试已知类型的问题
34
+
35
+ ### 如何使用
36
+
37
+ 1. 查看技能目录: `ls .memory/skills/`
38
+ 2. 匹配到任务后: `cat .memory/skills/<name>/SKILL.md`
39
+ 3. 按步骤执行
40
+ 4. 执行结束后,在捕获中引用技能名(帮助 consolidate 追踪技能有效性)
41
+
42
+ ## 何时搜索过去经验
43
+
44
+ 当你遇到以下情况,应主动搜索 `.memory/` 中的历史记忆:
45
+
46
+ 1. 处理你之前解决过类似问题的模块
47
+ 2. 需要进行与上次类似的技术选型
48
+ 3. 用户说「之前不是这样」或「上次讨论过」
49
+ 4. 需要了解项目的历史架构决策
50
+
51
+ ## 记录新经验
52
+
53
+ 当你遇到以下情况,在 `.memory/captures/` 创建捕获文件:
54
+
55
+ 1. 你犯了错误并被用户纠正
56
+ 2. 你发现代码与已有约定不一致
57
+ 3. 你了解到项目特有的架构决策(包括被否决的方案)
58
+ 4. 你做出了非平凡的设计选择(包括为什么选 A 不选 B)
59
+ 5. 你重复遇到了类似问题(说明前一次的经验没有被记住)
60
+ 6. 你完成了复杂的多步操作流程
61
+
62
+ ### 分类参考
63
+
64
+ - **语义记忆**: 事实、约定、决策原则 → type: semantic
65
+ - **情景记忆**: 具体事件经过 → type: episodic
66
+ - **流程记忆**: 操作步骤 → type: procedural
67
+
68
+ ### scope 选择
69
+
70
+ - 这个经验适用于整个项目吗?→ scope: all
71
+ - 只适用于前端 / 后端 / 基础设施?→ 对应 scope
72
+
73
+ ## 团队协作(多人仓库)
74
+
75
+ 本项目由多人维护。记忆分两层:
76
+
77
+ ### 个人层(仅你自己可见,不提交 git)
78
+
79
+ - `.memory/captures/` — 你这次的 AI 捕获
80
+ - `.memory/refs/` — 你的引用记录
81
+ - 不需要审批,直接写入
82
+
83
+ ### 团队层(所有人可见,提交 git)
84
+
85
+ - `.memory/topics/` — 团队认同的约定
86
+ - `.memory/skills/` — 团队可复用的技能
87
+ - `.memory/MEMORY.md` — 团队记忆摘要
88
+
89
+ ### 晋升团队层
90
+
91
+ 当你觉得某条个人捕获对团队有价值:
92
+
93
+ 1. 标记晋升: `touch .memory/captures/<type>/xxx.promote`
94
+ 2. 使用 PR 模板 `.memory/templates/PROMOTE_PR.md` 创建晋升 PR
95
+ 3. 等团队 review 后合并;详情见 `npx @riconext/hermes-repo promote --pr`(v0.2+)
96
+
97
+ ### 冲突处理
98
+
99
+ 如果发现团队层记忆与你的经验矛盾:
100
+
101
+ 1. 在 `.memory/team/conflict-resolutions/` 创建冲突记录
102
+ 2. 不要直接修改团队层文件
103
+ 3. 在 PR 或周会上提出讨论
104
+
105
+ ## 引用记录
106
+
107
+ 当你读取某条捕获时,在 `.memory/refs/` 创建引用记录:
108
+
109
+ ```json
110
+ { "capture": "文件名", "reason": "为啥看这个", "date": "2026-05-20" }
111
+ ```
112
+
113
+ ## 禁止
114
+
115
+ - 不要写入代码的具体实现细节(代码本身是自文档的)
116
+ - 不要写入敏感信息(密钥、密码、个人数据)
117
+ - 不要重复写入已存在的内容(先搜索再写)
118
+ - 不要在没有用户交互的会话中创建捕获(纯自动化操作不产生经验)
@@ -0,0 +1,21 @@
1
+ # 项目记忆
2
+
3
+ 最后更新: — | 总计: 0 条捕获(0 语义 + 0 情景 + 0 流程)
4
+
5
+ ## 活跃主题
6
+
7
+ (consolidate 后自动填充)
8
+
9
+ ## 最近经验
10
+
11
+ (consolidate 后自动填充)
12
+
13
+ ## 项目约定
14
+
15
+ (consolidate 后自动填充)
16
+
17
+ ## 检索提示
18
+
19
+ - 全文检索: `npx @riconext/hermes-repo search <关键词>`
20
+ - 查看捕获: `ls .memory/captures/` 或 `cat .memory/captures/<type>/<文件>.md`
21
+ - 查看主题: `ls .memory/topics/`
@@ -0,0 +1,21 @@
1
+ ## 记忆晋升申请
2
+
3
+ ### 自动扫描结果
4
+
5
+ 本次检测到 {total_count} 条 promoted capture,建议晋升 {ai_approve_count} 条到团队层。
6
+
7
+ ---
8
+
9
+ <!-- 由 `npx @riconext/hermes-repo promote --pr` 自动填充每条捕获 -->
10
+
11
+ ### 操作说明
12
+
13
+ 1. 每一条勾选一个选项
14
+ 2. 如需说明,在对应项后附言
15
+ 3. 提交 review → 根据勾选结果执行 `promote --apply`
16
+
17
+ ### 本次晋升总览
18
+
19
+ | 序号 | 摘要 | AI 建议 | scope |
20
+ |------|------|---------|-------|
21
+ | — | — | — | — |
@@ -0,0 +1,20 @@
1
+ ---
2
+ type: episodic
3
+ date: 2026-05-20
4
+ session: example-session-id
5
+ tags: [debugging, incident]
6
+ scope: all
7
+ confidence: pending
8
+ ---
9
+
10
+ ## 上下文
11
+
12
+ (具体事件背景)
13
+
14
+ ## 经过
15
+
16
+ (发生了什么、采取了什么措施)
17
+
18
+ ## 结果
19
+
20
+ (最终结果与教训)
@@ -0,0 +1,27 @@
1
+ ---
2
+ type: procedural
3
+ date: 2026-05-20
4
+ session: example-session-id
5
+ tags: [deploy, workflow]
6
+ scope: all
7
+ step_count: 0
8
+ repeat_count: 1
9
+ confidence: pending
10
+ ---
11
+
12
+ ## 目标
13
+
14
+ (要完成什么)
15
+
16
+ ## 步骤
17
+
18
+ 1. (步骤一)
19
+ 2. (步骤二)
20
+
21
+ ## 注意
22
+
23
+ (易错点、前置条件)
24
+
25
+ ## 验证
26
+
27
+ (如何确认成功)
@@ -0,0 +1,20 @@
1
+ ---
2
+ type: semantic
3
+ date: 2026-05-20
4
+ session: example-session-id
5
+ tags: [auth, token, security]
6
+ scope: all
7
+ confidence: pending
8
+ ---
9
+
10
+ ## 上下文
11
+
12
+ (描述当时正在做什么)
13
+
14
+ ## 发现
15
+
16
+ (项目事实、约定或架构决策)
17
+
18
+ ## 影响
19
+
20
+ (对后续开发的影响,可选)
@@ -0,0 +1,8 @@
1
+ {
2
+ "version": 1,
3
+ "storage": {
4
+ "backend": "file"
5
+ },
6
+ "assistants": ["claude-code"],
7
+ "debug": false
8
+ }
@@ -0,0 +1,17 @@
1
+ # >>> hermes-repo memory (do not edit this block manually)
2
+ # 个人层 — 不提交
3
+ .memory/captures/
4
+ .memory/sessions/
5
+ .memory/refs/
6
+ .memory/personal/
7
+ .memory/hermes-debug.log
8
+
9
+ # 团队层 — 提交
10
+ !.memory/topics/
11
+ !.memory/skills/
12
+ !.memory/MEMORY.md
13
+ !.memory/MEMORY-*.md
14
+ !.memory/team/
15
+ !.memory/config.json
16
+ !.memory/templates/
17
+ # <<< hermes-repo memory
@@ -0,0 +1,24 @@
1
+ {
2
+ "hooks": {
3
+ "Stop": [
4
+ {
5
+ "hooks": [
6
+ {
7
+ "type": "command",
8
+ "command": "npx __PACKAGE_NAME__ capture"
9
+ }
10
+ ]
11
+ }
12
+ ],
13
+ "SessionStart": [
14
+ {
15
+ "hooks": [
16
+ {
17
+ "type": "command",
18
+ "command": "npx __PACKAGE_NAME__ inject"
19
+ }
20
+ ]
21
+ }
22
+ ]
23
+ }
24
+ }
@@ -0,0 +1,6 @@
1
+ # Memory Steward 日志
2
+
3
+ 记录团队记忆维护轮值与重要操作。
4
+
5
+ | 日期 | 负责人 | 操作 |
6
+ |------|--------|------|
package/package.json CHANGED
@@ -1,37 +1,27 @@
1
1
  {
2
2
  "name": "@riconext/hermes-repo",
3
- "version": "0.1.0",
4
- "description": "Hermes-repo 是面向任意 Git 仓库的命令行工具,将 Hermes 式「经验 → 技能 → 自改进」学习闭环映射到文档与团队约定的工具,适合希望统一「踩坑有记录、契约能升级、 规范能进化」的研发与平台团队。",
3
+ "version": "0.2.4",
4
+ "description": "跨编程助手的项目级记忆系统",
5
+ "type": "module",
5
6
  "license": "MIT",
6
- "author": {
7
- "name": "Rico",
8
- "url": "https://github.com/ricoNext"
9
- },
7
+ "author": "Rico",
10
8
  "repository": {
11
9
  "type": "git",
12
10
  "url": "git+https://github.com/ricoNext/hermes-repo.git"
13
11
  },
14
- "homepage": "https://github.com/ricoNext/hermes-repo#readme",
15
12
  "bugs": {
16
13
  "url": "https://github.com/ricoNext/hermes-repo/issues"
17
14
  },
18
- "type": "module",
19
- "main": "./dist/index.cjs",
20
- "module": "./dist/index.js",
21
- "types": "./dist/index.d.ts",
22
- "exports": {
23
- ".": {
24
- "import": {
25
- "types": "./dist/index.d.ts",
26
- "default": "./dist/index.js"
27
- },
28
- "require": {
29
- "types": "./dist/index.d.cts",
30
- "default": "./dist/index.cjs"
31
- }
32
- },
33
- "./package.json": "./package.json"
34
- },
15
+ "homepage": "https://github.com/ricoNext/hermes-repo#readme",
16
+ "keywords": [
17
+ "claude-code",
18
+ "hooks",
19
+ "memory",
20
+ "ai",
21
+ "cursor",
22
+ "agents",
23
+ "hermes"
24
+ ],
35
25
  "bin": {
36
26
  "hermes-repo": "./dist/cli.js"
37
27
  },
@@ -40,30 +30,28 @@
40
30
  "README.md",
41
31
  "LICENSE"
42
32
  ],
43
- "sideEffects": false,
44
33
  "engines": {
45
- "node": ">=18"
34
+ "node": ">=20"
46
35
  },
47
36
  "publishConfig": {
48
- "access": "public"
37
+ "access": "public",
38
+ "registry": "https://registry.npmjs.org/"
49
39
  },
50
40
  "scripts": {
51
41
  "build": "tsup",
52
- "prepublishOnly": "npm run build",
53
42
  "dev": "tsup --watch",
54
- "typecheck": "tsc --noEmit"
43
+ "test": "bun run build && vitest run",
44
+ "typecheck": "tsc --noEmit",
45
+ "prepublishOnly": "bun run build && chmod +x dist/cli.js"
46
+ },
47
+ "dependencies": {
48
+ "@inquirer/prompts": "^7.5.1",
49
+ "commander": "^13.1.0"
55
50
  },
56
- "keywords": [
57
- "hermes-repo",
58
- "evolve",
59
- "git",
60
- "cli",
61
- "documentation",
62
- "captures"
63
- ],
64
51
  "devDependencies": {
65
- "@types/node": "^22.10.0",
52
+ "@types/node": "^22.15.29",
66
53
  "tsup": "^8.5.0",
67
- "typescript": "^5.9.0"
54
+ "typescript": "^5.8.3",
55
+ "vitest": "^3.2.4"
68
56
  }
69
57
  }
package/dist/index.cjs DELETED
@@ -1,8 +0,0 @@
1
- 'use strict';
2
-
3
- // src/index.ts
4
- var PACKAGE_NAME = "@riconext/hermes-repo";
5
-
6
- exports.PACKAGE_NAME = PACKAGE_NAME;
7
- //# sourceMappingURL=index.cjs.map
8
- //# sourceMappingURL=index.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;AAIO,IAAM,YAAA,GAAe","file":"index.cjs","sourcesContent":["/**\n * @riconext/hermes-repo — 库入口(CLI 见 `hermes-repo` bin)。\n */\n\nexport const PACKAGE_NAME = \"@riconext/hermes-repo\" as const;\n"]}
package/dist/index.d.cts DELETED
@@ -1,6 +0,0 @@
1
- /**
2
- * @riconext/hermes-repo — 库入口(CLI 见 `hermes-repo` bin)。
3
- */
4
- declare const PACKAGE_NAME: "@riconext/hermes-repo";
5
-
6
- export { PACKAGE_NAME };
package/dist/index.d.ts DELETED
@@ -1,6 +0,0 @@
1
- /**
2
- * @riconext/hermes-repo — 库入口(CLI 见 `hermes-repo` bin)。
3
- */
4
- declare const PACKAGE_NAME: "@riconext/hermes-repo";
5
-
6
- export { PACKAGE_NAME };
package/dist/index.js DELETED
@@ -1,6 +0,0 @@
1
- // src/index.ts
2
- var PACKAGE_NAME = "@riconext/hermes-repo";
3
-
4
- export { PACKAGE_NAME };
5
- //# sourceMappingURL=index.js.map
6
- //# sourceMappingURL=index.js.map
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";AAIO,IAAM,YAAA,GAAe","file":"index.js","sourcesContent":["/**\n * @riconext/hermes-repo — 库入口(CLI 见 `hermes-repo` bin)。\n */\n\nexport const PACKAGE_NAME = \"@riconext/hermes-repo\" as const;\n"]}