recall-os 0.3.0 → 0.3.1

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/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli/main.ts","../src/commands/adr/accept.ts","../src/core/config/config-schema.ts","../src/core/filesystem/safe-path.ts","../src/core/config/load-config.ts","../src/core/filesystem/write-plan.ts","../src/core/filesystem/conflict-policy.ts","../src/core/filesystem/write-file-safe.ts","../src/core/naming/adr-number.ts","../src/core/naming/slugify.ts","../src/commands/write-summary.ts","../src/core/generator/generate-adr.ts","../src/core/generator/template-context.ts","../src/core/generator/render-template.ts","../src/commands/adr/create.ts","../src/commands/adr/supersede.ts","../src/core/generator/generate-feature.ts","../src/core/naming/feature-number.ts","../src/commands/feature/create.ts","../src/core/config/default-config.ts","../src/core/adopt/inspect-repo.ts","../src/core/adopt/generate-adoption.ts","../src/commands/adopt.ts","../src/core/doctor/checks/code-reference-check.ts","../src/core/doctor/checks/config-check.ts","../src/core/doctor/checks/content-check.ts","../src/core/doctor/checks/drift-check.ts","../src/core/doctor/checks/memory-integrity-check.ts","../src/core/adr/adr-sections.ts","../src/core/doctor/checks/required-files-check.ts","../src/core/doctor/checks/standards-check.ts","../src/core/doctor/checks/superseded-check.ts","../src/core/doctor/doctor-check.ts","../src/core/doctor/doctor-report.ts","../src/commands/doctor.ts","../src/commands/init.ts","../src/core/generator/generate-init.ts","../src/core/hooks/detect-gates.ts","../src/core/hooks/generate-hook.ts","../src/presets/flutter/preset.ts","../src/presets/generic/preset.ts","../src/presets/ios-swift/preset.ts","../src/presets/kotlin-android/preset.ts","../src/presets/laravel/shared.ts","../src/presets/laravel-api/preset.ts","../src/presets/laravel-react/preset.ts","../src/presets/laravel-vue/preset.ts","../src/presets/nextjs/preset.ts","../src/presets/python-fastapi/preset.ts","../src/core/presets/preset-schema.ts","../src/core/presets/validate-preset.ts","../src/core/presets/preset-registry.ts","../src/core/skills/render-skill.ts","../src/core/skills/skill-catalog.ts","../src/core/skills/generate-skill.ts","../src/core/mcp/known-servers.ts","../src/core/mcp/generate-mcp.ts","../src/commands/mcp/add.ts","../src/core/generator/generate-module.ts","../src/commands/module/create.ts","../src/commands/preset/list.ts","../src/commands/skill/create.ts","../src/commands/skill/list.ts"],"sourcesContent":["import { Command, CommanderError } from \"commander\";\n\nimport { acceptAdr, AdrAcceptError, formatAdrAcceptResult } from \"../commands/adr/accept.js\";\nimport { createAdr, AdrCreateError, formatAdrCreateResult } from \"../commands/adr/create.js\";\nimport {\n supersedeAdr,\n AdrSupersedeError,\n formatAdrSupersedeResult,\n} from \"../commands/adr/supersede.js\";\nimport {\n createFeature,\n FeatureCreateError,\n formatFeatureCreateResult,\n} from \"../commands/feature/create.js\";\nimport { adoptProject, AdoptError, formatAdoptResult } from \"../commands/adopt.js\";\nimport { doctorProject, formatDoctorResult } from \"../commands/doctor.js\";\nimport { formatInitResult, initProject, InitError } from \"../commands/init.js\";\nimport { mcpAdd, McpAddError, formatMcpAddResult } from \"../commands/mcp/add.js\";\nimport {\n createModule,\n formatModuleCreateResult,\n ModuleCreateError,\n} from \"../commands/module/create.js\";\nimport { formatPresetListResult, listPresetEntries } from \"../commands/preset/list.js\";\nimport {\n createSkill,\n formatSkillCreateResult,\n SkillCreateError,\n} from \"../commands/skill/create.js\";\nimport { formatSkillListResult } from \"../commands/skill/list.js\";\n\nexport type CliWritable = {\n write(message: string): void;\n};\n\nexport type CliIo = {\n cwd?: string;\n stdout?: CliWritable;\n stderr?: CliWritable;\n};\n\nexport function createCliProgram(\n io: CliIo = {},\n state: { exitCode: number } = { exitCode: 0 },\n): Command {\n const stdout = io.stdout ?? process.stdout;\n const stderr = io.stderr ?? process.stderr;\n const cwd = io.cwd ?? process.cwd();\n const program = new Command();\n\n program\n .name(\"recall\")\n .description(\"Initialize and maintain repository memory for AI-assisted software work.\")\n .exitOverride()\n .configureOutput({\n writeOut: (message) => stdout.write(message),\n writeErr: (message) => stderr.write(message),\n });\n\n program\n .command(\"init\")\n .description(\"Initialize Recall OS repository memory.\")\n .option(\"--preset <id>\", \"Apply optional preset guidance and proposed decisions.\")\n .option(\"--dry-run\", \"Show planned writes without writing files.\")\n .option(\"--force\", \"Overwrite existing files explicitly.\")\n .option(\"--reinit\", \"Allow --force to overwrite an existing Recall OS installation.\")\n .action(\n async (options: { preset?: string; dryRun?: boolean; force?: boolean; reinit?: boolean }) => {\n const result = await initProject({\n rootDir: cwd,\n preset: options.preset,\n dryRun: options.dryRun,\n force: options.force,\n reinit: options.reinit,\n });\n\n stdout.write(formatInitResult(result));\n },\n );\n\n program\n .command(\"adopt\")\n .description(\"Inspect an existing repository and propose reviewable memory.\")\n .option(\"--dry-run\", \"Show planned writes without writing files.\")\n .option(\"--force\", \"Overwrite existing files explicitly.\")\n .action(async (options: { dryRun?: boolean; force?: boolean }) => {\n const result = await adoptProject({\n rootDir: cwd,\n dryRun: options.dryRun,\n force: options.force,\n });\n\n stdout.write(formatAdoptResult(result));\n });\n\n const featureCommand = program.command(\"feature\").description(\"Manage Recall OS feature memory.\");\n\n featureCommand\n .command(\"create\")\n .description(\"Create feature memory docs.\")\n .argument(\"<name>\", \"Feature name.\")\n .option(\"--dry-run\", \"Show planned writes without writing files.\")\n .option(\"--force\", \"Overwrite existing files explicitly.\")\n .action(async (name: string, options: { dryRun?: boolean; force?: boolean }) => {\n const result = await createFeature({\n rootDir: cwd,\n name,\n dryRun: options.dryRun,\n force: options.force,\n });\n\n stdout.write(formatFeatureCreateResult(result));\n });\n\n const adrCommand = program.command(\"adr\").description(\"Manage Recall OS ADR memory.\");\n\n adrCommand\n .command(\"create\")\n .description(\"Create a proposed ADR.\")\n .argument(\"<title>\", \"ADR title.\")\n .option(\"--dry-run\", \"Show planned writes without writing files.\")\n .option(\"--force\", \"Overwrite existing files explicitly.\")\n .action(async (title: string, options: { dryRun?: boolean; force?: boolean }) => {\n const result = await createAdr({\n rootDir: cwd,\n title,\n dryRun: options.dryRun,\n force: options.force,\n });\n\n stdout.write(formatAdrCreateResult(result));\n });\n\n adrCommand\n .command(\"accept\")\n .description(\"Promote a proposed ADR to accepted repository memory.\")\n .argument(\"<name>\", \"Proposed ADR name or slug, e.g. mcp-figma.\")\n .option(\"--dry-run\", \"Show planned writes without writing files.\")\n .option(\"--force\", \"Overwrite existing files explicitly.\")\n .action(async (name: string, options: { dryRun?: boolean; force?: boolean }) => {\n const result = await acceptAdr({\n rootDir: cwd,\n name,\n dryRun: options.dryRun,\n force: options.force,\n });\n\n stdout.write(formatAdrAcceptResult(result));\n });\n\n adrCommand\n .command(\"supersede\")\n .description(\n \"Record a changed decision: mark an accepted ADR superseded by a new accepted ADR.\",\n )\n .argument(\"<old>\", \"Accepted ADR name or slug being superseded, e.g. database-postgres.\")\n .argument(\"<new-title>\", \"Title of the new decision that replaces it.\")\n .option(\"--dry-run\", \"Show planned writes without writing files.\")\n .option(\"--force\", \"Overwrite existing files explicitly.\")\n .action(\n async (oldName: string, newTitle: string, options: { dryRun?: boolean; force?: boolean }) => {\n const result = await supersedeAdr({\n rootDir: cwd,\n oldName,\n newTitle,\n dryRun: options.dryRun,\n force: options.force,\n });\n\n stdout.write(formatAdrSupersedeResult(result));\n },\n );\n\n const moduleCommand = program.command(\"module\").description(\"Manage Recall OS module memory.\");\n\n moduleCommand\n .command(\"create\")\n .description(\"Create module memory docs.\")\n .argument(\"<name>\", \"Module name.\")\n .option(\"--dry-run\", \"Show planned writes without writing files.\")\n .option(\"--force\", \"Overwrite existing files explicitly.\")\n .action(async (name: string, options: { dryRun?: boolean; force?: boolean }) => {\n const result = await createModule({\n rootDir: cwd,\n name,\n dryRun: options.dryRun,\n force: options.force,\n });\n\n stdout.write(formatModuleCreateResult(result));\n });\n\n program\n .command(\"doctor\")\n .description(\"Check whether Recall OS repository memory is healthy.\")\n .action(async () => {\n const result = await doctorProject({ rootDir: cwd });\n\n stdout.write(formatDoctorResult(result));\n state.exitCode = result.exitCode;\n });\n\n const mcpCommand = program.command(\"mcp\").description(\"Manage Recall OS MCP context memory.\");\n\n mcpCommand\n .command(\"add\")\n .description(\"Generate proposed, offline memory for an MCP server.\")\n .argument(\"<server>\", \"MCP server name, e.g. figma.\")\n .option(\"--dry-run\", \"Show planned writes without writing files.\")\n .option(\"--force\", \"Overwrite existing files explicitly.\")\n .action(async (server: string, options: { dryRun?: boolean; force?: boolean }) => {\n const result = await mcpAdd({\n rootDir: cwd,\n server,\n dryRun: options.dryRun,\n force: options.force,\n });\n\n stdout.write(formatMcpAddResult(result));\n });\n\n const skillCommand = program.command(\"skill\").description(\"Manage Recall OS agent skills.\");\n\n skillCommand\n .command(\"create\")\n .description(\"Generate an agent skill for Claude Code and the portable Agent Skills target.\")\n .argument(\"<name>\", \"Skill name.\")\n .option(\"--dry-run\", \"Show planned writes without writing files.\")\n .option(\"--force\", \"Overwrite existing files explicitly.\")\n .action(async (name: string, options: { dryRun?: boolean; force?: boolean }) => {\n const result = await createSkill({\n rootDir: cwd,\n name,\n dryRun: options.dryRun,\n force: options.force,\n });\n\n stdout.write(formatSkillCreateResult(result));\n });\n\n skillCommand\n .command(\"list\")\n .description(\"List built-in catalog skills.\")\n .action(() => {\n stdout.write(formatSkillListResult());\n });\n\n const presetCommand = program.command(\"preset\").description(\"Inspect Recall OS presets.\");\n\n presetCommand\n .command(\"list\")\n .description(\"List built-in presets.\")\n .action(() => {\n stdout.write(formatPresetListResult(listPresetEntries()));\n });\n\n return program;\n}\n\nexport async function main(\n argv: string[] = process.argv.slice(2),\n io: CliIo = {},\n): Promise<number> {\n const stderr = io.stderr ?? process.stderr;\n const state = { exitCode: 0 };\n const program = createCliProgram(io, state);\n\n try {\n await program.parseAsync(argv, { from: \"user\" });\n return state.exitCode;\n } catch (error) {\n if (error instanceof InitError) {\n stderr.write(`${error.message}\\n`);\n for (const detail of error.details) {\n stderr.write(`- ${detail}\\n`);\n }\n return 1;\n }\n\n if (error instanceof FeatureCreateError) {\n stderr.write(`${error.message}\\n`);\n for (const detail of error.details) {\n stderr.write(`- ${detail}\\n`);\n }\n return 1;\n }\n\n if (error instanceof AdoptError) {\n stderr.write(`${error.message}\\n`);\n for (const detail of error.details) {\n stderr.write(`- ${detail}\\n`);\n }\n return 1;\n }\n\n if (error instanceof AdrCreateError) {\n stderr.write(`${error.message}\\n`);\n for (const detail of error.details) {\n stderr.write(`- ${detail}\\n`);\n }\n return 1;\n }\n\n if (error instanceof AdrAcceptError) {\n stderr.write(`${error.message}\\n`);\n for (const detail of error.details) {\n stderr.write(`- ${detail}\\n`);\n }\n return 1;\n }\n\n if (error instanceof AdrSupersedeError) {\n stderr.write(`${error.message}\\n`);\n for (const detail of error.details) {\n stderr.write(`- ${detail}\\n`);\n }\n return 1;\n }\n\n if (error instanceof ModuleCreateError) {\n stderr.write(`${error.message}\\n`);\n for (const detail of error.details) {\n stderr.write(`- ${detail}\\n`);\n }\n return 1;\n }\n\n if (error instanceof SkillCreateError) {\n stderr.write(`${error.message}\\n`);\n for (const detail of error.details) {\n stderr.write(`- ${detail}\\n`);\n }\n return 1;\n }\n\n if (error instanceof McpAddError) {\n stderr.write(`${error.message}\\n`);\n for (const detail of error.details) {\n stderr.write(`- ${detail}\\n`);\n }\n return 1;\n }\n\n if (error instanceof CommanderError) {\n return error.exitCode;\n }\n\n stderr.write(error instanceof Error ? `${error.message}\\n` : \"Unknown error.\\n\");\n return 1;\n }\n}\n","import { existsSync } from \"node:fs\";\nimport { readFile, readdir, rm } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { ConfigValidationError } from \"../../core/config/config-schema.js\";\nimport { loadConfig, ConfigLoadError } from \"../../core/config/load-config.js\";\nimport { resolveSafePath } from \"../../core/filesystem/safe-path.js\";\nimport { createWritePlan, type WritePlan } from \"../../core/filesystem/write-plan.js\";\nimport { executeWritePlan, type WriteResult } from \"../../core/filesystem/write-file-safe.js\";\nimport { getNextAdrNumber } from \"../../core/naming/adr-number.js\";\nimport { SlugifyError, slugify } from \"../../core/naming/slugify.js\";\nimport { appendNextSteps, appendWriteSummary } from \"../write-summary.js\";\n\nexport type AdrAcceptOptions = {\n rootDir: string;\n name: string;\n dryRun?: boolean;\n force?: boolean;\n};\n\nexport type AdrAcceptResult = {\n slug: string;\n acceptedPath: string;\n source: \"proposed\" | \"in-place\";\n proposedRemoved: string | null;\n dryRun: boolean;\n writeResult: WriteResult;\n};\n\nexport type AdrAcceptErrorCode =\n | \"CONFIG_REQUIRED\"\n | \"INVALID_ADR_NAME\"\n | \"NOT_FOUND\"\n | \"WRITE_PLAN_ERROR\";\n\nexport class AdrAcceptError extends Error {\n readonly code: AdrAcceptErrorCode;\n readonly details: string[];\n\n constructor(code: AdrAcceptErrorCode, message: string, details: string[] = []) {\n super(message);\n this.name = \"AdrAcceptError\";\n this.code = code;\n this.details = details;\n }\n}\n\nexport async function acceptAdr(options: AdrAcceptOptions): Promise<AdrAcceptResult> {\n const slug = createSlug(options.name);\n const config = await loadRequiredConfig(options.rootDir);\n const adrDirAbsolute = resolveSafePath(options.rootDir, config.adrDir).absolutePath;\n\n const proposedRelative = `${config.adrDir}/proposed/ADR-PROPOSED-${slug}.md`;\n const proposedAbsolute = resolveSafePath(options.rootDir, proposedRelative).absolutePath;\n\n if (existsSync(proposedAbsolute)) {\n return promoteProposed(\n options,\n config.adrDir,\n adrDirAbsolute,\n proposedRelative,\n proposedAbsolute,\n slug,\n );\n }\n\n const numbered = await findNumberedAdr(adrDirAbsolute, slug);\n if (numbered !== null) {\n return acceptInPlace(options, config.adrDir, numbered);\n }\n\n throw new AdrAcceptError(\"NOT_FOUND\", `No proposed ADR found for \"${slug}\".`, [\n `Looked for ${proposedRelative} and a Proposed ADR matching the slug in ${config.adrDir}.`,\n ]);\n}\n\nasync function promoteProposed(\n options: AdrAcceptOptions,\n adrDir: string,\n adrDirAbsolute: string,\n proposedRelative: string,\n proposedAbsolute: string,\n slug: string,\n): Promise<AdrAcceptResult> {\n const content = await readFile(proposedAbsolute, \"utf8\");\n const next = await getNextAdrNumber(adrDirAbsolute);\n const acceptedRelative = `${adrDir}/${next.id}-${slug}.md`;\n const accepted = renderAccepted(content, next.id);\n\n const writeResult = await write(options, acceptedRelative, accepted);\n\n let proposedRemoved: string | null = null;\n if (!options.dryRun) {\n await rm(proposedAbsolute);\n proposedRemoved = proposedRelative;\n }\n\n return {\n slug,\n acceptedPath: acceptedRelative,\n source: \"proposed\",\n proposedRemoved,\n dryRun: options.dryRun ?? false,\n writeResult,\n };\n}\n\nasync function acceptInPlace(\n options: AdrAcceptOptions,\n adrDir: string,\n numbered: { fileName: string; content: string },\n): Promise<AdrAcceptResult> {\n const relativePath = `${adrDir}/${numbered.fileName}`;\n const accepted = renderAccepted(numbered.content, null);\n\n // The file already exists; promotion is an explicit accept, so overwrite it in place.\n const writeResult = await write({ ...options, force: true }, relativePath, accepted);\n\n return {\n slug: numbered.fileName,\n acceptedPath: relativePath,\n source: \"in-place\",\n proposedRemoved: null,\n dryRun: options.dryRun ?? false,\n writeResult,\n };\n}\n\nasync function write(\n options: AdrAcceptOptions,\n relativePath: string,\n content: string,\n): Promise<WriteResult> {\n const plan = createWritePlan({\n rootDir: options.rootDir,\n files: [{ path: relativePath, content }],\n force: options.force,\n });\n\n if (plan.hasErrors) {\n throw new AdrAcceptError(\n \"WRITE_PLAN_ERROR\",\n \"ADR accept write plan contains errors.\",\n plan.entries\n .filter(\n (entry): entry is Extract<WritePlan[\"entries\"][number], { action: \"error\" }> =>\n entry.action === \"error\",\n )\n .map((entry) => `${entry.path}: ${entry.reason}`),\n );\n }\n\n return executeWritePlan(plan, { dryRun: options.dryRun });\n}\n\nfunction renderAccepted(content: string, id: string | null): string {\n let out = content.replace(/(##\\s+Status\\r?\\n\\r?\\n)Proposed\\b/u, \"$1Accepted\");\n\n if (id !== null) {\n out = out.replace(/^# Proposed ADR: (.+)$/mu, `# ${id}: $1`);\n }\n\n return out;\n}\n\nasync function findNumberedAdr(\n adrDirAbsolute: string,\n slug: string,\n): Promise<{ fileName: string; content: string } | null> {\n const pattern = new RegExp(`^ADR-\\\\d{4,}-${escapeRegExp(slug)}\\\\.md$`, \"u\");\n\n let entries;\n try {\n entries = await readdir(adrDirAbsolute, { withFileTypes: true });\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return null;\n }\n throw error;\n }\n\n const match = entries.find((entry) => entry.isFile() && pattern.test(entry.name));\n if (match === undefined) {\n return null;\n }\n\n const content = await readFile(path.join(adrDirAbsolute, match.name), \"utf8\");\n if (!/(##\\s+Status\\r?\\n\\r?\\n)Proposed\\b/u.test(content)) {\n throw new AdrAcceptError(\"NOT_FOUND\", `ADR ${match.name} is not Proposed.`);\n }\n\n return { fileName: match.name, content };\n}\n\nexport function formatAdrAcceptResult(result: AdrAcceptResult): string {\n const lines = [\n result.dryRun ? \"Recall OS ADR accept dry run complete.\" : \"Recall OS ADR accept complete.\",\n `Accepted: ${result.acceptedPath}`,\n ];\n\n appendWriteSummary(lines, { dryRun: result.dryRun, writeResult: result.writeResult });\n\n if (result.proposedRemoved !== null) {\n lines.push(`Removed proposal: ${result.proposedRemoved}`);\n }\n\n if (!result.dryRun) {\n appendNextSteps(lines, [\n `${result.acceptedPath} is now Accepted and is repository source of truth.`,\n \"Drift checks now treat references to it as resolved.\",\n ]);\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction createSlug(name: string): string {\n const withoutPrefix = name.replace(/^ADR-PROPOSED-/iu, \"\");\n try {\n return slugify(withoutPrefix);\n } catch (error) {\n if (error instanceof SlugifyError) {\n throw new AdrAcceptError(\"INVALID_ADR_NAME\", error.message);\n }\n throw error;\n }\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/gu, \"\\\\$&\");\n}\n\nasync function loadRequiredConfig(rootDir: string) {\n try {\n return await loadConfig(rootDir);\n } catch (error) {\n if (error instanceof ConfigLoadError || error instanceof ConfigValidationError) {\n throw new AdrAcceptError(\n \"CONFIG_REQUIRED\",\n \"Recall OS config not found or invalid. Run `recall init` first.\",\n [error.message],\n );\n }\n throw error;\n }\n}\n","import { z } from \"zod\";\n\nimport type { ConflictPolicy } from \"../filesystem/conflict-policy.js\";\nimport { normalizeOutputPath } from \"../filesystem/safe-path.js\";\n\nconst PRESET_ID_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/u;\nconst VERSION_PATTERN = /^\\d+\\.\\d+\\.\\d+$/u;\n// Reject empty strings and any ASCII control characters (including newlines and tabs).\nconst PRE_COMMIT_GATE_PATTERN = /^[^\\u0000-\\u001f\\u007f]+$/u;\n\nexport const memoryProfileSchema = z.enum([\"lite\", \"standard\", \"strict\"]);\nexport const aiToolTargetSchema = z.enum([\"claude\", \"codex\", \"cursor\", \"generic\"]);\nexport const configWritePolicySchema = z.enum([\"skip-existing\", \"overwrite\"]);\n\nexport type MemoryProfile = z.infer<typeof memoryProfileSchema>;\nexport type AiToolTarget = z.infer<typeof aiToolTargetSchema>;\nexport type ConfigWritePolicy = Extract<ConflictPolicy, \"skip-existing\" | \"overwrite\">;\n\nexport class ConfigValidationError extends Error {\n readonly issues: string[];\n\n constructor(issues: string[]) {\n super(`Invalid Recall OS config: ${issues.join(\"; \")}`);\n this.name = \"ConfigValidationError\";\n this.issues = issues;\n }\n}\n\nconst versionSchema = z\n .string()\n .regex(VERSION_PATTERN, \"Version must use MAJOR.MINOR.PATCH format.\");\n\nconst presetSchema = z.union([\n z.null(),\n z\n .string()\n .min(1, \"Preset cannot be empty.\")\n .max(80, \"Preset cannot exceed 80 characters.\")\n .regex(PRESET_ID_PATTERN, \"Preset must use lowercase letters, numbers, and single hyphens.\"),\n]);\n\nconst preCommitGateSchema = z\n .string()\n .min(1, \"Pre-commit gate cannot be empty.\")\n .max(200, \"Pre-commit gate cannot exceed 200 characters.\")\n .regex(\n PRE_COMMIT_GATE_PATTERN,\n \"Pre-commit gate must be a single line without control characters.\",\n );\n\nconst safeRelativePathSchema = z.string().transform((value, context) => {\n try {\n return normalizeOutputPath(value);\n } catch (error) {\n context.addIssue({\n code: \"custom\",\n message: error instanceof Error ? error.message : \"Path is invalid.\",\n });\n return z.NEVER;\n }\n});\n\nexport const recallConfigSchema = z\n .object({\n version: versionSchema,\n templateVersion: versionSchema,\n preset: presetSchema,\n memoryProfile: memoryProfileSchema,\n mode: memoryProfileSchema,\n aiTools: z.array(aiToolTargetSchema).min(1, \"At least one AI tool is required.\"),\n docsDir: safeRelativePathSchema,\n featuresDir: safeRelativePathSchema,\n modulesDir: safeRelativePathSchema,\n adrDir: safeRelativePathSchema,\n writePolicy: configWritePolicySchema,\n preCommitGates: z.array(preCommitGateSchema).max(50, \"Too many pre-commit gates.\").default([]),\n })\n .strict()\n .superRefine((config, context) => {\n if (config.memoryProfile !== config.mode) {\n context.addIssue({\n code: \"custom\",\n path: [\"mode\"],\n message: \"Mode must match memoryProfile.\",\n });\n }\n\n const seenAiTools = new Set<AiToolTarget>();\n for (const aiTool of config.aiTools) {\n if (seenAiTools.has(aiTool)) {\n context.addIssue({\n code: \"custom\",\n path: [\"aiTools\"],\n message: `Duplicate AI tool \"${aiTool}\".`,\n });\n }\n seenAiTools.add(aiTool);\n }\n });\n\nexport type RecallConfig = z.infer<typeof recallConfigSchema>;\n\nexport function parseConfig(value: unknown): RecallConfig {\n const result = recallConfigSchema.safeParse(value);\n\n if (!result.success) {\n throw new ConfigValidationError(\n result.error.issues.map((issue) => {\n const path = issue.path.length > 0 ? `${issue.path.join(\".\")}: ` : \"\";\n return `${path}${issue.message}`;\n }),\n );\n }\n\n return result.data;\n}\n","import path from \"node:path\";\nimport { realpathSync } from \"node:fs\";\n\nconst CONTROL_CHARS = /[\\u0000-\\u001f\\u007f]/u;\n\nexport class SafePathError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"SafePathError\";\n }\n}\n\nexport type SafePath = {\n path: string;\n absolutePath: string;\n};\n\nexport function normalizeOutputPath(relativePath: string): string {\n if (relativePath.length === 0) {\n throw new SafePathError(\"Path cannot be empty.\");\n }\n\n if (CONTROL_CHARS.test(relativePath)) {\n throw new SafePathError(\"Path cannot contain null bytes or control characters.\");\n }\n\n if (relativePath.includes(\"\\\\\")) {\n throw new SafePathError(\"Path must use forward slashes.\");\n }\n\n if (path.posix.isAbsolute(relativePath) || path.win32.isAbsolute(relativePath)) {\n throw new SafePathError(\"Path must be relative.\");\n }\n\n const segments = relativePath.split(\"/\");\n\n if (segments.some((segment) => segment.length === 0)) {\n throw new SafePathError(\"Path cannot contain empty segments.\");\n }\n\n if (segments.some((segment) => segment === \"..\")) {\n throw new SafePathError(\"Path cannot contain path traversal.\");\n }\n\n const normalized = path.posix.normalize(relativePath);\n\n if (normalized === \".\" || normalized.startsWith(\"../\") || normalized === \"..\") {\n throw new SafePathError(\"Path cannot escape the project root.\");\n }\n\n return normalized;\n}\n\nexport function resolveSafePath(rootDir: string, relativePath: string): SafePath {\n const normalizedPath = normalizeOutputPath(relativePath);\n const absoluteRoot = realpathSync.native(rootDir);\n const absolutePath = path.resolve(absoluteRoot, normalizedPath);\n const relativeToRoot = path.relative(absoluteRoot, absolutePath);\n\n if (relativeToRoot === \"\" || relativeToRoot.startsWith(\"..\") || path.isAbsolute(relativeToRoot)) {\n throw new SafePathError(\"Resolved path must stay inside the project root.\");\n }\n\n return {\n path: normalizedPath,\n absolutePath,\n };\n}\n","import { readFile } from \"node:fs/promises\";\nimport { resolveSafePath } from \"../filesystem/safe-path.js\";\nimport { parseConfig, type RecallConfig } from \"./config-schema.js\";\n\nexport const CONFIG_PATH = \".recall/config.json\";\n\nexport class ConfigLoadError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ConfigLoadError\";\n }\n}\n\nexport async function loadConfig(rootDir: string): Promise<RecallConfig> {\n const configPath = resolveSafePath(rootDir, CONFIG_PATH);\n\n let rawConfig: string;\n try {\n rawConfig = await readFile(configPath.absolutePath, \"utf8\");\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n throw new ConfigLoadError(`Recall OS config not found at ${CONFIG_PATH}.`);\n }\n throw error;\n }\n\n let parsedJson: unknown;\n try {\n parsedJson = JSON.parse(rawConfig);\n } catch {\n throw new ConfigLoadError(`Recall OS config at ${CONFIG_PATH} is not valid JSON.`);\n }\n\n return parseConfig(parsedJson);\n}\n","import { existsSync } from \"node:fs\";\n\nimport type { ConflictPolicy } from \"./conflict-policy.js\";\nimport { shouldOverwriteExisting } from \"./conflict-policy.js\";\nimport { resolveSafePath } from \"./safe-path.js\";\n\nexport type WriteFileInput = {\n path: string;\n content: string;\n executable?: boolean;\n};\n\nexport type WritePlanCreateEntry = {\n action: \"create\";\n path: string;\n absolutePath: string;\n content: string;\n executable?: boolean;\n};\n\nexport type WritePlanSkipEntry = {\n action: \"skip\";\n path: string;\n absolutePath: string;\n reason: string;\n};\n\nexport type WritePlanOverwriteEntry = {\n action: \"overwrite\";\n path: string;\n absolutePath: string;\n content: string;\n executable?: boolean;\n};\n\nexport type WritePlanErrorEntry = {\n action: \"error\";\n path: string;\n reason: string;\n};\n\nexport type WritePlanEntry =\n | WritePlanCreateEntry\n | WritePlanSkipEntry\n | WritePlanOverwriteEntry\n | WritePlanErrorEntry;\n\nexport type WritePlan = {\n entries: WritePlanEntry[];\n hasErrors: boolean;\n};\n\nexport type CreateWritePlanOptions = {\n rootDir: string;\n files: WriteFileInput[];\n policy?: ConflictPolicy;\n force?: boolean;\n};\n\nexport function createWritePlan(options: CreateWritePlanOptions): WritePlan {\n const policy = options.policy ?? (options.force ? \"overwrite\" : \"skip-existing\");\n const seen = new Map<string, string>();\n const entries: WritePlanEntry[] = [];\n\n for (const file of options.files) {\n try {\n const safePath = resolveSafePath(options.rootDir, file.path);\n const existingPath = seen.get(safePath.path);\n\n if (existingPath !== undefined) {\n entries.push({\n action: \"error\",\n path: file.path,\n reason: `Duplicate output path \"${safePath.path}\" also used by \"${existingPath}\".`,\n });\n continue;\n }\n\n seen.set(safePath.path, file.path);\n\n if (existsSync(safePath.absolutePath)) {\n if (shouldOverwriteExisting(policy)) {\n entries.push({\n action: \"overwrite\",\n path: safePath.path,\n absolutePath: safePath.absolutePath,\n content: file.content,\n executable: file.executable,\n });\n } else {\n entries.push({\n action: \"skip\",\n path: safePath.path,\n absolutePath: safePath.absolutePath,\n reason: \"File already exists.\",\n });\n }\n continue;\n }\n\n entries.push({\n action: \"create\",\n path: safePath.path,\n absolutePath: safePath.absolutePath,\n content: file.content,\n executable: file.executable,\n });\n } catch (error) {\n entries.push({\n action: \"error\",\n path: file.path,\n reason: error instanceof Error ? error.message : \"Invalid output path.\",\n });\n }\n }\n\n return {\n entries,\n hasErrors: entries.some((entry) => entry.action === \"error\"),\n };\n}\n","export type ConflictPolicy = \"skip-existing\" | \"overwrite\";\n\nexport function shouldOverwriteExisting(policy: ConflictPolicy): boolean {\n return policy === \"overwrite\";\n}\n\nexport function resolveConflictPolicy(force = false): ConflictPolicy {\n return force ? \"overwrite\" : \"skip-existing\";\n}\n","import { chmod, mkdir, writeFile, lstat } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport type {\n WritePlan,\n WritePlanCreateEntry,\n WritePlanEntry,\n WritePlanOverwriteEntry,\n} from \"./write-plan.js\";\n\nexport type WriteResult = {\n created: string[];\n overwritten: string[];\n skipped: string[];\n dryRun: boolean;\n};\n\nexport class WriteSafetyError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"WriteSafetyError\";\n }\n}\n\nexport type ExecuteWritePlanOptions = {\n dryRun?: boolean;\n};\n\nexport async function executeWritePlan(\n plan: WritePlan,\n options: ExecuteWritePlanOptions = {},\n): Promise<WriteResult> {\n if (plan.hasErrors) {\n throw new WriteSafetyError(\"Refusing to execute a write plan with errors.\");\n }\n\n const result: WriteResult = {\n created: [],\n overwritten: [],\n skipped: [],\n dryRun: options.dryRun ?? false,\n };\n\n for (const entry of plan.entries) {\n if (entry.action === \"skip\") {\n result.skipped.push(entry.path);\n continue;\n }\n\n if (entry.action !== \"create\" && entry.action !== \"overwrite\") {\n continue;\n }\n\n if (result.dryRun) {\n if (entry.action === \"create\") {\n result.created.push(entry.path);\n } else {\n result.overwritten.push(entry.path);\n }\n continue;\n }\n\n await writeFileSafe(entry);\n\n if (entry.action === \"create\") {\n result.created.push(entry.path);\n } else {\n result.overwritten.push(entry.path);\n }\n }\n\n return result;\n}\n\nexport async function writeFileSafe(\n entry: WritePlanCreateEntry | WritePlanOverwriteEntry,\n): Promise<void> {\n await assertNoSymlinkInExistingPath(entry.absolutePath);\n await mkdir(path.dirname(entry.absolutePath), { recursive: true });\n await writeFile(entry.absolutePath, entry.content, {\n encoding: \"utf8\",\n flag: entry.action === \"create\" ? \"wx\" : \"w\",\n });\n\n if (entry.executable === true) {\n await chmod(entry.absolutePath, 0o755);\n }\n}\n\nasync function assertNoSymlinkInExistingPath(absolutePath: string): Promise<void> {\n const segments = path.resolve(absolutePath).split(path.sep);\n let current = segments[0] === \"\" ? path.sep : segments[0];\n const startIndex = segments[0] === \"\" ? 1 : 1;\n\n for (let index = startIndex; index < segments.length; index += 1) {\n current =\n current === path.sep\n ? path.join(current, segments[index] ?? \"\")\n : path.join(current, segments[index] ?? \"\");\n\n try {\n const stats = await lstat(current);\n if (stats.isSymbolicLink()) {\n throw new WriteSafetyError(`Refusing to write through symlink: ${current}`);\n }\n } catch (error) {\n if (error instanceof WriteSafetyError) {\n throw error;\n }\n\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return;\n }\n\n throw error;\n }\n }\n}\n\nexport function assertExecutableEntry(\n entry: WritePlanEntry,\n): asserts entry is WritePlanCreateEntry | WritePlanOverwriteEntry {\n if (entry.action !== \"create\" && entry.action !== \"overwrite\") {\n throw new WriteSafetyError(`Entry action \"${entry.action}\" is not executable.`);\n }\n}\n","import { readdir } from \"node:fs/promises\";\n\nconst ADR_FILE_PATTERN = /^ADR-(\\d{4,})-([a-z0-9]+(?:-[a-z0-9]+)*)\\.md$/u;\n\nexport type AdrNumber = {\n number: number;\n id: string;\n};\n\nexport type AdrFile = AdrNumber & {\n slug: string;\n fileName: string;\n};\n\nexport async function getNextAdrNumber(adrDirAbsolutePath: string): Promise<AdrNumber> {\n const existingFiles = await readExistingAdrFiles(adrDirAbsolutePath);\n return getNextAdrNumberFromFiles(existingFiles);\n}\n\nexport async function getAdrFileForSlug(\n adrDirAbsolutePath: string,\n slug: string,\n): Promise<AdrFile> {\n const existingFiles = await readExistingAdrFiles(adrDirAbsolutePath);\n const existingFile = existingFiles\n .filter((file) => file.slug === slug)\n .sort((left, right) => left.number - right.number)[0];\n\n if (existingFile !== undefined) {\n return existingFile;\n }\n\n const nextAdrNumber = getNextAdrNumberFromFiles(existingFiles);\n\n return {\n ...nextAdrNumber,\n slug,\n fileName: `${nextAdrNumber.id}-${slug}.md`,\n };\n}\n\nfunction getNextAdrNumberFromFiles(existingFiles: AdrFile[]): AdrNumber {\n const existingNumbers = existingFiles.map((file) => file.number);\n const highestNumber = existingNumbers.length === 0 ? 0 : Math.max(...existingNumbers);\n const nextNumber = highestNumber + 1;\n\n return {\n number: nextNumber,\n id: formatAdrNumber(nextNumber),\n };\n}\n\nexport function formatAdrNumber(adrNumber: number): string {\n if (!Number.isInteger(adrNumber) || adrNumber < 1) {\n throw new Error(\"ADR number must be a positive integer.\");\n }\n\n return `ADR-${String(adrNumber).padStart(4, \"0\")}`;\n}\n\nexport function parseAdrNumber(fileName: string): number | null {\n const match = ADR_FILE_PATTERN.exec(fileName);\n\n if (match === null) {\n return null;\n }\n\n return Number.parseInt(match[1] ?? \"\", 10);\n}\n\nasync function readExistingAdrFiles(adrDirAbsolutePath: string): Promise<AdrFile[]> {\n let entries;\n\n try {\n entries = await readdir(adrDirAbsolutePath, { withFileTypes: true });\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return [];\n }\n\n throw error;\n }\n\n return entries\n .filter((entry) => entry.isFile())\n .map((entry) => parseAdrFile(entry.name))\n .filter((adrFile): adrFile is AdrFile => adrFile !== null);\n}\n\nfunction parseAdrFile(fileName: string): AdrFile | null {\n const match = ADR_FILE_PATTERN.exec(fileName);\n\n if (match === null) {\n return null;\n }\n\n const number = Number.parseInt(match[1] ?? \"\", 10);\n const id = formatAdrNumber(number);\n const slug = match[2] ?? \"\";\n\n return {\n number,\n id,\n slug,\n fileName,\n };\n}\n","const MAX_SLUG_LENGTH = 80;\nconst CONTROL_CHARS = /[\\u0000-\\u001f\\u007f]/u;\nconst WINDOWS_RESERVED_NAMES = new Set([\n \"con\",\n \"prn\",\n \"aux\",\n \"nul\",\n \"com1\",\n \"com2\",\n \"com3\",\n \"com4\",\n \"com5\",\n \"com6\",\n \"com7\",\n \"com8\",\n \"com9\",\n \"lpt1\",\n \"lpt2\",\n \"lpt3\",\n \"lpt4\",\n \"lpt5\",\n \"lpt6\",\n \"lpt7\",\n \"lpt8\",\n \"lpt9\",\n]);\n\nexport class SlugifyError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"SlugifyError\";\n }\n}\n\nexport type SlugifyOptions = {\n maxLength?: number;\n};\n\nexport function slugify(input: string, options: SlugifyOptions = {}): string {\n const maxLength = options.maxLength ?? MAX_SLUG_LENGTH;\n\n if (!Number.isInteger(maxLength) || maxLength < 1) {\n throw new SlugifyError(\"Slug max length must be a positive integer.\");\n }\n\n const original = input;\n const trimmed = original.trim();\n\n if (trimmed.length === 0) {\n throw new SlugifyError(\"Name cannot be empty.\");\n }\n\n if (original.endsWith(\".\") || original.endsWith(\" \")) {\n throw new SlugifyError(\"Name cannot end with a dot or space.\");\n }\n\n if (CONTROL_CHARS.test(original)) {\n throw new SlugifyError(\"Name cannot contain null bytes or control characters.\");\n }\n\n if (/[\\\\/]/u.test(original)) {\n throw new SlugifyError(\"Name cannot contain path separators.\");\n }\n\n if (trimmed === \".\" || trimmed === \"..\" || trimmed.includes(\"..\")) {\n throw new SlugifyError(\"Name cannot contain path traversal.\");\n }\n\n const withoutDiacritics = trimmed.normalize(\"NFKD\").replace(/[\\u0300-\\u036f]/gu, \"\");\n const slug = withoutDiacritics\n .toLowerCase()\n .replace(/[^a-z0-9]+/gu, \"-\")\n .replace(/-+/gu, \"-\")\n .replace(/^-|-$/gu, \"\")\n .slice(0, maxLength)\n .replace(/-$/u, \"\");\n\n if (slug.length === 0) {\n throw new SlugifyError(\"Name must include at least one letter or number.\");\n }\n\n if (WINDOWS_RESERVED_NAMES.has(slug)) {\n throw new SlugifyError(`Name \"${slug}\" is reserved on Windows.`);\n }\n\n return slug;\n}\n","import type { WriteResult } from \"../core/filesystem/write-file-safe.js\";\n\nexport type WriteSummaryOptions = {\n dryRun: boolean;\n writeResult: WriteResult;\n};\n\nexport function appendWriteSummary(lines: string[], options: WriteSummaryOptions): void {\n appendFileList(\n lines,\n options.dryRun ? \"Planned creates\" : \"Created\",\n options.writeResult.created,\n );\n appendFileList(\n lines,\n options.dryRun ? \"Planned overwrites\" : \"Overwritten\",\n options.writeResult.overwritten,\n );\n appendFileList(lines, \"Skipped\", options.writeResult.skipped);\n}\n\n/**\n * Append a \"Next steps\" guidance block so the CLI tells the user what each artifact is for and what\n * to do next, instead of only listing created paths.\n */\nexport function appendNextSteps(lines: string[], steps: string[]): void {\n if (steps.length === 0) {\n return;\n }\n\n lines.push(\"\");\n lines.push(\"Next steps:\");\n for (const step of steps) {\n lines.push(`- ${step}`);\n }\n}\n\nfunction appendFileList(lines: string[], label: string, paths: string[]): void {\n if (paths.length === 0) {\n return;\n }\n\n lines.push(`${label}:`);\n for (const filePath of paths) {\n lines.push(`- ${filePath}`);\n }\n}\n","import path from \"node:path\";\n\nimport type { WriteFileInput } from \"../filesystem/write-plan.js\";\nimport { slugify } from \"../naming/slugify.js\";\nimport { createTemplateContext } from \"./template-context.js\";\nimport { renderTemplate } from \"./render-template.js\";\n\nexport type GenerateAdrFileOptions = {\n adrDir: string;\n adrId: string;\n title: string;\n};\n\nconst adrTemplate = `# {{adrId}}: {{title}}\n\n## Status\n\nProposed\n\n## Context\n\nWhat decision needs to be made, and why now?\n\n## Decision\n\nWhat option is proposed?\n\n## Alternatives Considered\n\nWhat other options were considered?\n\n## Consequences\n\nWhat improves, what worsens, and what risks remain?\n\n## Related Documents\n\n- PRD:\n- Architecture:\n- Security:\n- Feature:\n`;\n\nexport function generateAdrFile(options: GenerateAdrFileOptions): WriteFileInput[] {\n const slug = slugify(options.title);\n const title = titleizeAdrTitle(options.title);\n const context = createTemplateContext({\n adrId: options.adrId,\n slug,\n title,\n });\n\n return [\n {\n path: path.posix.join(options.adrDir, `${options.adrId}-${slug}.md`),\n content: renderTemplate(adrTemplate, context),\n },\n ];\n}\n\nexport type GenerateSupersedingAdrOptions = {\n adrDir: string;\n adrId: string;\n title: string;\n supersedesRef: string;\n};\n\nconst supersedingAdrTemplate = `# {{adrId}}: {{title}}\n\n## Status\n\nAccepted\n\n## Supersedes\n\n- {{supersedesRef}}\n\n## Context\n\nWhat changed, and why the previous decision no longer holds?\n\n## Decision\n\nWhat is the new decision?\n\n## Alternatives Considered\n\nWhat other options were considered?\n\n## Consequences\n\nWhat improves, what worsens, and what risks remain?\n\n## Related Documents\n\n- PRD:\n- Architecture:\n- Security:\n- Feature:\n`;\n\n/**\n * Render a new, accepted ADR that supersedes an existing one. Used by `recall adr supersede`: a human\n * recording a changed decision, so the new ADR is Accepted and carries a `## Supersedes` link back to\n * the decision it replaces.\n */\nexport function generateSupersedingAdr(options: GenerateSupersedingAdrOptions): {\n path: string;\n content: string;\n slug: string;\n} {\n const slug = slugify(options.title);\n const title = titleizeAdrTitle(options.title);\n const context = createTemplateContext({\n adrId: options.adrId,\n slug,\n title,\n supersedesRef: options.supersedesRef,\n });\n\n return {\n path: path.posix.join(options.adrDir, `${options.adrId}-${slug}.md`),\n content: renderTemplate(supersedingAdrTemplate, context),\n slug,\n };\n}\n\nfunction titleizeAdrTitle(title: string): string {\n return title\n .trim()\n .replace(/[-_]+/gu, \" \")\n .replace(/\\s+/gu, \" \")\n .replace(/\\b\\w/gu, (character) => character.toUpperCase());\n}\n","const TEMPLATE_KEY_PATTERN = /^[A-Za-z][A-Za-z0-9_]*$/u;\nconst RESERVED_TEMPLATE_KEYS = new Set([\"constructor\", \"__proto__\", \"prototype\"]);\n\nexport type TemplateValue = string | number | boolean;\nexport type TemplateContext = Readonly<Record<string, TemplateValue>>;\n\nexport class TemplateRenderError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"TemplateRenderError\";\n }\n}\n\nfunction isTemplateValue(value: unknown): value is TemplateValue {\n return typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\";\n}\n\nfunction validateTemplateKey(key: string): void {\n if (!TEMPLATE_KEY_PATTERN.test(key)) {\n throw new TemplateRenderError(\n `Invalid template key \"${key}\". Keys must match [A-Za-z][A-Za-z0-9_]*.`,\n );\n }\n\n if (RESERVED_TEMPLATE_KEYS.has(key)) {\n throw new TemplateRenderError(`Invalid template key \"${key}\". Key is reserved.`);\n }\n}\n\nexport function createTemplateContext(values: Readonly<Record<string, unknown>>): TemplateContext {\n if (values === null || typeof values !== \"object\" || Array.isArray(values)) {\n throw new TemplateRenderError(\"Template context must be an object.\");\n }\n\n const context = Object.create(null) as Record<string, TemplateValue>;\n\n for (const [key, value] of Object.entries(values)) {\n validateTemplateKey(key);\n\n if (!isTemplateValue(value)) {\n throw new TemplateRenderError(\n `Invalid value for template key \"${key}\". Values must be strings, numbers, or booleans.`,\n );\n }\n\n context[key] = value;\n }\n\n return Object.freeze(context);\n}\n","import {\n createTemplateContext,\n TemplateRenderError,\n type TemplateContext,\n type TemplateValue,\n} from \"./template-context.js\";\n\nconst TEMPLATE_KEY_PATTERN = /^[A-Za-z][A-Za-z0-9_]*$/u;\nconst RESERVED_TEMPLATE_KEYS = new Set([\"constructor\", \"__proto__\", \"prototype\"]);\nconst EXECUTION_MARKERS = [\"<%\", \"%>\"];\nconst LOGIC_MARKERS = [\"{{#\", \"{{/\", \"{{^\", \"{{>\"];\n\nfunction validatePlaceholderKey(key: string): void {\n if (!TEMPLATE_KEY_PATTERN.test(key)) {\n throw new TemplateRenderError(\n `Invalid placeholder \"${key}\". Placeholders must match [A-Za-z][A-Za-z0-9_]*.`,\n );\n }\n\n if (RESERVED_TEMPLATE_KEYS.has(key)) {\n throw new TemplateRenderError(`Invalid placeholder \"${key}\". Placeholder is reserved.`);\n }\n}\n\nfunction stringifyTemplateValue(value: TemplateValue): string {\n return String(value);\n}\n\nfunction rejectUnsupportedSyntax(template: string): void {\n for (const marker of EXECUTION_MARKERS) {\n if (template.includes(marker)) {\n throw new TemplateRenderError(\n `Unsupported template syntax \"${marker}\". Template execution is not supported.`,\n );\n }\n }\n\n for (const marker of LOGIC_MARKERS) {\n if (template.includes(marker)) {\n throw new TemplateRenderError(\n `Unsupported template syntax \"${marker}\". Template logic is not supported.`,\n );\n }\n }\n}\n\nexport function renderTemplate(template: string, context: TemplateContext): string {\n if (typeof template !== \"string\") {\n throw new TemplateRenderError(\"Template must be a string.\");\n }\n\n const safeContext = createTemplateContext(context);\n rejectUnsupportedSyntax(template);\n\n let output = \"\";\n let cursor = 0;\n\n while (cursor < template.length) {\n const openingIndex = template.indexOf(\"{{\", cursor);\n const closingIndex = template.indexOf(\"}}\", cursor);\n\n if (closingIndex !== -1 && (openingIndex === -1 || closingIndex < openingIndex)) {\n throw new TemplateRenderError(\"Invalid template syntax: unmatched closing braces.\");\n }\n\n if (openingIndex === -1) {\n output += template.slice(cursor);\n break;\n }\n\n output += template.slice(cursor, openingIndex);\n\n const placeholderEnd = template.indexOf(\"}}\", openingIndex + 2);\n\n if (placeholderEnd === -1) {\n throw new TemplateRenderError(\"Invalid template syntax: unmatched opening braces.\");\n }\n\n const placeholder = template.slice(openingIndex + 2, placeholderEnd).trim();\n\n if (placeholder.length === 0) {\n throw new TemplateRenderError(\"Invalid template syntax: placeholder cannot be empty.\");\n }\n\n validatePlaceholderKey(placeholder);\n\n if (!Object.prototype.hasOwnProperty.call(safeContext, placeholder)) {\n throw new TemplateRenderError(`Missing template value for \"${placeholder}\".`);\n }\n\n output += stringifyTemplateValue(safeContext[placeholder]);\n cursor = placeholderEnd + 2;\n }\n\n return output;\n}\n","import { ConfigValidationError } from \"../../core/config/config-schema.js\";\nimport { loadConfig, ConfigLoadError } from \"../../core/config/load-config.js\";\nimport { resolveSafePath } from \"../../core/filesystem/safe-path.js\";\nimport { createWritePlan, type WritePlan } from \"../../core/filesystem/write-plan.js\";\nimport { executeWritePlan, type WriteResult } from \"../../core/filesystem/write-file-safe.js\";\nimport { generateAdrFile } from \"../../core/generator/generate-adr.js\";\nimport { getAdrFileForSlug } from \"../../core/naming/adr-number.js\";\nimport { SlugifyError, slugify } from \"../../core/naming/slugify.js\";\nimport { appendNextSteps, appendWriteSummary } from \"../write-summary.js\";\n\nexport type AdrCreateOptions = {\n rootDir: string;\n title: string;\n dryRun?: boolean;\n force?: boolean;\n};\n\nexport type AdrCreateResult = {\n adrId: string;\n slug: string;\n adrPath: string;\n dryRun: boolean;\n plan: WritePlan;\n writeResult: WriteResult;\n};\n\nexport type AdrCreateErrorCode = \"CONFIG_REQUIRED\" | \"INVALID_ADR_TITLE\" | \"WRITE_PLAN_ERROR\";\n\nexport class AdrCreateError extends Error {\n readonly code: AdrCreateErrorCode;\n readonly details: string[];\n\n constructor(code: AdrCreateErrorCode, message: string, details: string[] = []) {\n super(message);\n this.name = \"AdrCreateError\";\n this.code = code;\n this.details = details;\n }\n}\n\nexport async function createAdr(options: AdrCreateOptions): Promise<AdrCreateResult> {\n const slug = createAdrSlug(options.title);\n const config = await loadRequiredConfig(options.rootDir);\n const adrDirPath = resolveSafePath(options.rootDir, config.adrDir);\n const adrFile = await getAdrFileForSlug(adrDirPath.absolutePath, slug);\n const files = generateAdrFile({\n adrDir: config.adrDir,\n adrId: adrFile.id,\n title: options.title,\n });\n const plan = createWritePlan({\n rootDir: options.rootDir,\n files,\n force: options.force,\n });\n\n if (plan.hasErrors) {\n throw new AdrCreateError(\n \"WRITE_PLAN_ERROR\",\n \"ADR create write plan contains errors.\",\n plan.entries\n .filter((entry) => entry.action === \"error\")\n .map((entry) => `${entry.path}: ${entry.reason}`),\n );\n }\n\n const writeResult = await executeWritePlan(plan, { dryRun: options.dryRun });\n\n return {\n adrId: adrFile.id,\n slug,\n adrPath: `${config.adrDir}/${adrFile.fileName}`,\n dryRun: options.dryRun ?? false,\n plan,\n writeResult,\n };\n}\n\nexport function formatAdrCreateResult(result: AdrCreateResult): string {\n const lines = [\n result.dryRun ? \"Recall OS ADR create dry run complete.\" : \"Recall OS ADR create complete.\",\n `ADR: ${result.adrPath}`,\n ];\n\n appendWriteSummary(lines, {\n dryRun: result.dryRun,\n writeResult: result.writeResult,\n });\n\n if (!result.dryRun) {\n appendNextSteps(lines, [\n `Open ${result.adrPath} and fill: Context, Decision, Alternatives, Consequences.`,\n \"It is Proposed — set Status to Accepted once the team agrees.\",\n ]);\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction createAdrSlug(title: string): string {\n try {\n return slugify(title);\n } catch (error) {\n if (error instanceof SlugifyError) {\n throw new AdrCreateError(\"INVALID_ADR_TITLE\", error.message);\n }\n\n throw error;\n }\n}\n\nasync function loadRequiredConfig(rootDir: string) {\n try {\n return await loadConfig(rootDir);\n } catch (error) {\n if (error instanceof ConfigLoadError || error instanceof ConfigValidationError) {\n throw new AdrCreateError(\n \"CONFIG_REQUIRED\",\n \"Recall OS config not found or invalid. Run `recall init` first.\",\n [error.message],\n );\n }\n\n throw error;\n }\n}\n","import { readFile, readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { ConfigValidationError } from \"../../core/config/config-schema.js\";\nimport { loadConfig, ConfigLoadError } from \"../../core/config/load-config.js\";\nimport { resolveSafePath } from \"../../core/filesystem/safe-path.js\";\nimport { createWritePlan, type WritePlan } from \"../../core/filesystem/write-plan.js\";\nimport { executeWritePlan, type WriteResult } from \"../../core/filesystem/write-file-safe.js\";\nimport { generateSupersedingAdr } from \"../../core/generator/generate-adr.js\";\nimport { getNextAdrNumber } from \"../../core/naming/adr-number.js\";\nimport { SlugifyError, slugify } from \"../../core/naming/slugify.js\";\nimport { appendNextSteps, appendWriteSummary } from \"../write-summary.js\";\n\nexport type AdrSupersedeOptions = {\n rootDir: string;\n oldName: string;\n newTitle: string;\n dryRun?: boolean;\n force?: boolean;\n};\n\nexport type AdrSupersedeResult = {\n oldRef: string;\n oldPath: string;\n newRef: string;\n newPath: string;\n dryRun: boolean;\n writeResult: WriteResult;\n};\n\nexport type AdrSupersedeErrorCode =\n | \"CONFIG_REQUIRED\"\n | \"INVALID_ADR_NAME\"\n | \"NOT_FOUND\"\n | \"NOT_ACCEPTED\"\n | \"WRITE_PLAN_ERROR\";\n\nexport class AdrSupersedeError extends Error {\n readonly code: AdrSupersedeErrorCode;\n readonly details: string[];\n\n constructor(code: AdrSupersedeErrorCode, message: string, details: string[] = []) {\n super(message);\n this.name = \"AdrSupersedeError\";\n this.code = code;\n this.details = details;\n }\n}\n\nexport async function supersedeAdr(options: AdrSupersedeOptions): Promise<AdrSupersedeResult> {\n const oldSlug = createSlug(options.oldName, \"oldName\");\n // Validate the new title is sluggable, with a clean error before any file work.\n createSlug(options.newTitle, \"newTitle\");\n const config = await loadRequiredConfig(options.rootDir);\n const adrDirAbsolute = resolveSafePath(options.rootDir, config.adrDir).absolutePath;\n\n const old = await findAcceptedAdr(adrDirAbsolute, oldSlug);\n const next = await getNextAdrNumber(adrDirAbsolute);\n const oldRef = old.fileName.replace(/\\.md$/u, \"\");\n\n // The new, accepted decision that records why the old one changed.\n const superseding = generateSupersedingAdr({\n adrDir: config.adrDir,\n adrId: next.id,\n title: options.newTitle,\n supersedesRef: oldRef,\n });\n const newRef = `${next.id}-${superseding.slug}`;\n\n // Mark the old ADR superseded, but keep \"Accepted\" in the status so existing drift checks still\n // treat references to it as a real, once-accepted decision — the new superseded-reference check is\n // what flags those references for review.\n const markedOld = old.content.replace(\n /(##\\s+Status\\r?\\n\\r?\\n)Accepted[^\\n]*/u,\n `$1Accepted — superseded by ${newRef}`,\n );\n\n const writeNew = await write(options, superseding.path, superseding.content, options.force);\n const oldRelative = `${config.adrDir}/${old.fileName}`;\n const writeOld = await write(options, oldRelative, markedOld, true);\n\n return {\n oldRef,\n oldPath: oldRelative,\n newRef,\n newPath: superseding.path,\n dryRun: options.dryRun ?? false,\n writeResult: {\n created: [...writeNew.created, ...writeOld.created],\n overwritten: [...writeNew.overwritten, ...writeOld.overwritten],\n skipped: [...writeNew.skipped, ...writeOld.skipped],\n dryRun: options.dryRun ?? false,\n },\n };\n}\n\nasync function findAcceptedAdr(\n adrDirAbsolute: string,\n slug: string,\n): Promise<{ fileName: string; content: string }> {\n const pattern = new RegExp(`^ADR-\\\\d{4,}-${escapeRegExp(slug)}\\\\.md$`, \"u\");\n\n let entries;\n try {\n entries = await readdir(adrDirAbsolute, { withFileTypes: true });\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n throw new AdrSupersedeError(\"NOT_FOUND\", `No accepted ADR found for \"${slug}\".`);\n }\n throw error;\n }\n\n const match = entries.find((entry) => entry.isFile() && pattern.test(entry.name));\n if (match === undefined) {\n throw new AdrSupersedeError(\"NOT_FOUND\", `No accepted ADR found for \"${slug}\".`, [\n `Looked for an ADR-####-${slug}.md in the ADR directory.`,\n ]);\n }\n\n const content = await readFile(path.join(adrDirAbsolute, match.name), \"utf8\");\n if (!/(##\\s+Status\\r?\\n\\r?\\n)Accepted\\b/u.test(content)) {\n throw new AdrSupersedeError(\n \"NOT_ACCEPTED\",\n `ADR ${match.name} is not Accepted, so there is nothing to supersede.`,\n [\"Only an accepted decision can be superseded. Accept it first with `recall adr accept`.\"],\n );\n }\n\n return { fileName: match.name, content };\n}\n\nasync function write(\n options: AdrSupersedeOptions,\n relativePath: string,\n content: string,\n force: boolean | undefined,\n): Promise<WriteResult> {\n const plan = createWritePlan({\n rootDir: options.rootDir,\n files: [{ path: relativePath, content }],\n force,\n });\n\n if (plan.hasErrors) {\n throw new AdrSupersedeError(\n \"WRITE_PLAN_ERROR\",\n \"ADR supersede write plan contains errors.\",\n plan.entries\n .filter(\n (entry): entry is Extract<WritePlan[\"entries\"][number], { action: \"error\" }> =>\n entry.action === \"error\",\n )\n .map((entry) => `${entry.path}: ${entry.reason}`),\n );\n }\n\n return executeWritePlan(plan, { dryRun: options.dryRun });\n}\n\nexport function formatAdrSupersedeResult(result: AdrSupersedeResult): string {\n const lines = [\n result.dryRun\n ? \"Recall OS ADR supersede dry run complete.\"\n : \"Recall OS ADR supersede complete.\",\n `Superseded: ${result.oldPath} (now marked superseded by ${result.newRef})`,\n `New decision: ${result.newPath}`,\n ];\n\n appendWriteSummary(lines, { dryRun: result.dryRun, writeResult: result.writeResult });\n\n if (!result.dryRun) {\n appendNextSteps(lines, [\n `Fill ${result.newPath}: Context (what changed), Decision, Alternatives, Consequences.`,\n `${result.oldRef} stays in history as superseded; update any memory that still relies on it.`,\n \"Run `recall doctor` — it flags memory that still references the superseded decision.\",\n ]);\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction createSlug(name: string, field: \"oldName\" | \"newTitle\"): string {\n const withoutPrefix = name.replace(/^ADR-(?:PROPOSED-|\\d{4,}-)/iu, \"\");\n try {\n return slugify(withoutPrefix);\n } catch (error) {\n if (error instanceof SlugifyError) {\n throw new AdrSupersedeError(\"INVALID_ADR_NAME\", `Invalid ${field}: ${error.message}`);\n }\n throw error;\n }\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/gu, \"\\\\$&\");\n}\n\nasync function loadRequiredConfig(rootDir: string) {\n try {\n return await loadConfig(rootDir);\n } catch (error) {\n if (error instanceof ConfigLoadError || error instanceof ConfigValidationError) {\n throw new AdrSupersedeError(\n \"CONFIG_REQUIRED\",\n \"Recall OS config not found or invalid. Run `recall init` first.\",\n [error.message],\n );\n }\n throw error;\n }\n}\n","import path from \"node:path\";\n\nimport type { WriteFileInput } from \"../filesystem/write-plan.js\";\nimport { slugify } from \"../naming/slugify.js\";\nimport { createTemplateContext } from \"./template-context.js\";\nimport { renderTemplate } from \"./render-template.js\";\n\nexport type GenerateFeatureFilesOptions = {\n featuresDir: string;\n featureId: string;\n featureName: string;\n};\n\ntype FeatureTemplate = {\n fileName: string;\n content: string;\n};\n\nconst featureTemplates: FeatureTemplate[] = [\n {\n fileName: \"PRD.md\",\n content: `# PRD: {{title}}\n\n## Purpose\n\nDescribe why this feature exists and what user or business problem it solves.\n\n## In Scope\n\n- TBD\n\n## Non-Goals\n\n- TBD\n`,\n },\n {\n fileName: \"ACCEPTANCE.md\",\n content: `# Acceptance Criteria: {{title}}\n\n## Criteria\n\n- TBD\n\n## Out Of Scope\n\n- TBD\n`,\n },\n {\n fileName: \"ARCHITECTURE_IMPACT.md\",\n content: `# Architecture Impact: {{title}}\n\n## Affected Modules\n\n- TBD\n\n## ADR Impact\n\nState whether this feature needs a new or updated ADR.\n\n## Security Impact\n\nState whether auth, secrets, storage, networking, telemetry, file writes, or dependencies change.\n`,\n },\n {\n fileName: \"CHANGE_REQUESTS.md\",\n content: `# Change Requests: {{title}}\n\nRecord accepted changes to the feature requirements here.\n`,\n },\n {\n fileName: \"PLAN.md\",\n content: `# Plan: {{title}}\n\n## Approach\n\nTBD\n\n## Boundaries\n\nTBD\n`,\n },\n {\n fileName: \"TASKS.md\",\n content: `# Tasks: {{title}}\n\n## T1: Define Scope\n\nStatus: Todo\n\nScope:\n\n- TBD\n\nAcceptance:\n\n- TBD\n\nTests:\n\n- TBD\n\nDo Not:\n\n- Start implementation before PRD, acceptance, architecture impact, and test plan are clear.\n`,\n },\n {\n fileName: \"TEST_PLAN.md\",\n content: `# Test Plan: {{title}}\n\n## Unit Tests\n\n- TBD\n\n## Integration Tests\n\n- TBD\n\n## Security Tests\n\n- TBD\n`,\n },\n {\n fileName: \"REVIEW.md\",\n content: `# Review: {{title}}\n\n## Status\n\nPending review.\n\n## Findings\n\n- TBD\n`,\n },\n {\n fileName: \"COMPLETION_REPORT.md\",\n content: `# Completion Report: {{title}}\n\n## Status\n\nPending.\n\n## Files Changed\n\n- TBD\n\n## Tests Run\n\n- TBD\n\n## Results\n\n- TBD\n\n## Remaining Risks\n\n- TBD\n`,\n },\n];\n\nexport function generateFeatureFiles(options: GenerateFeatureFilesOptions): WriteFileInput[] {\n const slug = slugify(options.featureName);\n const featureDir = path.posix.join(options.featuresDir, `${options.featureId}-${slug}`);\n const title = titleizeFeatureName(options.featureName);\n const context = createTemplateContext({\n featureId: options.featureId,\n slug,\n title,\n });\n\n return featureTemplates.map((template) => ({\n path: path.posix.join(featureDir, template.fileName),\n content: renderTemplate(template.content, context),\n }));\n}\n\nfunction titleizeFeatureName(featureName: string): string {\n return featureName\n .trim()\n .replace(/[-_]+/gu, \" \")\n .replace(/\\s+/gu, \" \")\n .replace(/\\b\\w/gu, (character) => character.toUpperCase());\n}\n","import { readdir } from \"node:fs/promises\";\n\nconst FEATURE_FOLDER_PATTERN = /^F-(\\d{3,})-([a-z0-9]+(?:-[a-z0-9]+)*)$/u;\n\nexport type FeatureNumber = {\n number: number;\n id: string;\n};\n\nexport type FeatureFolder = FeatureNumber & {\n slug: string;\n folderName: string;\n};\n\nexport async function getNextFeatureNumber(\n featuresDirAbsolutePath: string,\n): Promise<FeatureNumber> {\n const existingFolders = await readExistingFeatureFolders(featuresDirAbsolutePath);\n return getNextFeatureNumberFromFolders(existingFolders);\n}\n\nexport async function getFeatureFolderForSlug(\n featuresDirAbsolutePath: string,\n slug: string,\n): Promise<FeatureFolder> {\n const existingFolders = await readExistingFeatureFolders(featuresDirAbsolutePath);\n const existingFolder = existingFolders\n .filter((folder) => folder.slug === slug)\n .sort((left, right) => left.number - right.number)[0];\n\n if (existingFolder !== undefined) {\n return existingFolder;\n }\n\n const nextFeatureNumber = getNextFeatureNumberFromFolders(existingFolders);\n\n return {\n ...nextFeatureNumber,\n slug,\n folderName: `${nextFeatureNumber.id}-${slug}`,\n };\n}\n\nfunction getNextFeatureNumberFromFolders(existingFolders: FeatureFolder[]): FeatureNumber {\n const existingNumbers = existingFolders.map((folder) => folder.number);\n const highestNumber = existingNumbers.length === 0 ? 0 : Math.max(...existingNumbers);\n const nextNumber = highestNumber + 1;\n\n return {\n number: nextNumber,\n id: formatFeatureNumber(nextNumber),\n };\n}\n\nexport function formatFeatureNumber(featureNumber: number): string {\n if (!Number.isInteger(featureNumber) || featureNumber < 1) {\n throw new Error(\"Feature number must be a positive integer.\");\n }\n\n return `F-${String(featureNumber).padStart(3, \"0\")}`;\n}\n\nexport function parseFeatureNumber(folderName: string): number | null {\n const match = FEATURE_FOLDER_PATTERN.exec(folderName);\n\n if (match === null) {\n return null;\n }\n\n return Number.parseInt(match[1] ?? \"\", 10);\n}\n\nasync function readExistingFeatureFolders(\n featuresDirAbsolutePath: string,\n): Promise<FeatureFolder[]> {\n let entries;\n\n try {\n entries = await readdir(featuresDirAbsolutePath, { withFileTypes: true });\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return [];\n }\n\n throw error;\n }\n\n return entries\n .filter((entry) => entry.isDirectory())\n .map((entry) => parseFeatureFolder(entry.name))\n .filter((featureFolder): featureFolder is FeatureFolder => featureFolder !== null);\n}\n\nfunction parseFeatureFolder(folderName: string): FeatureFolder | null {\n const match = FEATURE_FOLDER_PATTERN.exec(folderName);\n\n if (match === null) {\n return null;\n }\n\n const number = Number.parseInt(match[1] ?? \"\", 10);\n const id = formatFeatureNumber(number);\n const slug = match[2] ?? \"\";\n\n return {\n number,\n id,\n slug,\n folderName,\n };\n}\n","import { ConfigValidationError } from \"../../core/config/config-schema.js\";\nimport { loadConfig, ConfigLoadError } from \"../../core/config/load-config.js\";\nimport { resolveSafePath } from \"../../core/filesystem/safe-path.js\";\nimport { createWritePlan, type WritePlan } from \"../../core/filesystem/write-plan.js\";\nimport { executeWritePlan, type WriteResult } from \"../../core/filesystem/write-file-safe.js\";\nimport { generateFeatureFiles } from \"../../core/generator/generate-feature.js\";\nimport { getFeatureFolderForSlug } from \"../../core/naming/feature-number.js\";\nimport { SlugifyError, slugify } from \"../../core/naming/slugify.js\";\nimport { appendNextSteps, appendWriteSummary } from \"../write-summary.js\";\n\nexport type FeatureCreateOptions = {\n rootDir: string;\n name: string;\n dryRun?: boolean;\n force?: boolean;\n};\n\nexport type FeatureCreateResult = {\n featureId: string;\n slug: string;\n featurePath: string;\n dryRun: boolean;\n plan: WritePlan;\n writeResult: WriteResult;\n};\n\nexport type FeatureCreateErrorCode =\n | \"CONFIG_REQUIRED\"\n | \"INVALID_FEATURE_NAME\"\n | \"WRITE_PLAN_ERROR\";\n\nexport class FeatureCreateError extends Error {\n readonly code: FeatureCreateErrorCode;\n readonly details: string[];\n\n constructor(code: FeatureCreateErrorCode, message: string, details: string[] = []) {\n super(message);\n this.name = \"FeatureCreateError\";\n this.code = code;\n this.details = details;\n }\n}\n\nexport async function createFeature(options: FeatureCreateOptions): Promise<FeatureCreateResult> {\n const slug = createFeatureSlug(options.name);\n const config = await loadRequiredConfig(options.rootDir);\n const featuresDirPath = resolveSafePath(options.rootDir, config.featuresDir);\n const featureFolder = await getFeatureFolderForSlug(featuresDirPath.absolutePath, slug);\n const files = generateFeatureFiles({\n featuresDir: config.featuresDir,\n featureId: featureFolder.id,\n featureName: options.name,\n });\n const plan = createWritePlan({\n rootDir: options.rootDir,\n files,\n force: options.force,\n });\n\n if (plan.hasErrors) {\n throw new FeatureCreateError(\n \"WRITE_PLAN_ERROR\",\n \"Feature create write plan contains errors.\",\n plan.entries\n .filter((entry) => entry.action === \"error\")\n .map((entry) => `${entry.path}: ${entry.reason}`),\n );\n }\n\n const writeResult = await executeWritePlan(plan, { dryRun: options.dryRun });\n\n return {\n featureId: featureFolder.id,\n slug,\n featurePath: `${config.featuresDir}/${featureFolder.folderName}`,\n dryRun: options.dryRun ?? false,\n plan,\n writeResult,\n };\n}\n\nexport function formatFeatureCreateResult(result: FeatureCreateResult): string {\n const lines = [\n result.dryRun\n ? \"Recall OS feature create dry run complete.\"\n : \"Recall OS feature create complete.\",\n `Feature: ${result.featurePath}`,\n ];\n\n appendWriteSummary(lines, {\n dryRun: result.dryRun,\n writeResult: result.writeResult,\n });\n\n if (!result.dryRun) {\n appendNextSteps(lines, [\n `Start in ${result.featurePath}: write PRD.md (why) and ACCEPTANCE.md (how you will know it works).`,\n \"Then PLAN.md, TASKS.md, and TEST_PLAN.md before you implement.\",\n \"Run `recall doctor` to check the memory is complete.\",\n ]);\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction createFeatureSlug(name: string): string {\n try {\n return slugify(name);\n } catch (error) {\n if (error instanceof SlugifyError) {\n throw new FeatureCreateError(\"INVALID_FEATURE_NAME\", error.message);\n }\n\n throw error;\n }\n}\n\nasync function loadRequiredConfig(rootDir: string) {\n try {\n return await loadConfig(rootDir);\n } catch (error) {\n if (error instanceof ConfigLoadError || error instanceof ConfigValidationError) {\n throw new FeatureCreateError(\n \"CONFIG_REQUIRED\",\n \"Recall OS config not found or invalid. Run `recall init` first.\",\n [error.message],\n );\n }\n\n throw error;\n }\n}\n","import { parseConfig, type RecallConfig } from \"./config-schema.js\";\n\nconst DEFAULT_CONFIG = {\n version: \"0.1.0\",\n templateVersion: \"0.1.0\",\n preset: null,\n memoryProfile: \"standard\",\n mode: \"standard\",\n aiTools: [\"claude\", \"codex\"],\n docsDir: \"docs\",\n featuresDir: \"docs/40-features\",\n modulesDir: \"docs/30-modules\",\n adrDir: \"docs/adrs\",\n writePolicy: \"skip-existing\",\n preCommitGates: [],\n} satisfies RecallConfig;\n\nexport function createDefaultConfig(overrides: Partial<RecallConfig> = {}): RecallConfig {\n return parseConfig({\n ...DEFAULT_CONFIG,\n aiTools: [...DEFAULT_CONFIG.aiTools],\n preCommitGates: [...DEFAULT_CONFIG.preCommitGates],\n ...overrides,\n });\n}\n","import { existsSync } from \"node:fs\";\nimport { readFile, readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\n\n/**\n * Read-only signals inferred from a repository's manifest and marker files.\n *\n * Inspection never executes repository code, makes network calls, or installs anything. Every signal\n * here is a candidate the user reviews; nothing is accepted by adoption.\n */\nexport type RepoSignals = {\n languages: string[];\n packageManager: string | null;\n /** The manifest file the package manager was inferred from (e.g. `go.mod`). */\n packageManagerSource: string | null;\n frameworks: string[];\n hasTests: boolean;\n /** Where tests were detected (e.g. a matched `*_test.go` path), so a reviewer can correct it. */\n testsEvidence: string | null;\n hasReadme: boolean;\n hasDocs: boolean;\n};\n\n/** Maps a detected framework to the manifest it was inferred from, for reviewable provenance. */\nconst FRAMEWORK_SOURCES: Record<string, string> = {\n \"Next.js\": \"package.json\",\n React: \"package.json\",\n NestJS: \"package.json\",\n Express: \"package.json\",\n FastAPI: \"pyproject.toml / requirements.txt\",\n Flask: \"pyproject.toml / requirements.txt\",\n Django: \"pyproject.toml / requirements.txt\",\n Gin: \"go.mod\",\n Echo: \"go.mod\",\n Fiber: \"go.mod\",\n Chi: \"go.mod\",\n \"Spring Boot\": \"pom.xml / build.gradle\",\n \"Actix Web\": \"Cargo.toml\",\n Axum: \"Cargo.toml\",\n Rocket: \"Cargo.toml\",\n Laravel: \"composer.json\",\n Symfony: \"composer.json\",\n \"Ruby on Rails\": \"Gemfile\",\n Flutter: \"pubspec.yaml\",\n};\n\nexport async function inspectRepo(rootDir: string): Promise<RepoSignals> {\n const has = (relativePath: string): boolean => existsSync(path.join(rootDir, relativePath));\n\n const languages = new Set<string>();\n const frameworks = new Set<string>();\n\n const pkg = has(\"package.json\") ? await readJson(rootDir, \"package.json\") : null;\n if (pkg !== null) {\n languages.add(has(\"tsconfig.json\") ? \"TypeScript\" : \"JavaScript\");\n }\n\n let pythonText = \"\";\n if (has(\"pyproject.toml\")) {\n languages.add(\"Python\");\n pythonText += await readText(rootDir, \"pyproject.toml\");\n }\n if (has(\"requirements.txt\")) {\n languages.add(\"Python\");\n pythonText += await readText(rootDir, \"requirements.txt\");\n }\n\n if (has(\"go.mod\")) {\n languages.add(\"Go\");\n }\n if (has(\"Cargo.toml\")) {\n languages.add(\"Rust\");\n }\n if (has(\"pom.xml\") || has(\"build.gradle\") || has(\"build.gradle.kts\")) {\n languages.add(\"JVM\");\n }\n if (has(\"Package.swift\")) {\n languages.add(\"Swift\");\n }\n if (has(\"pubspec.yaml\")) {\n languages.add(\"Dart\");\n frameworks.add(\"Flutter\");\n }\n\n if (has(\"composer.json\")) {\n languages.add(\"PHP\");\n const composer = (await readText(rootDir, \"composer.json\")).toLowerCase();\n if (composer.includes(\"laravel/framework\")) {\n frameworks.add(\"Laravel\");\n } else if (composer.includes(\"symfony/\")) {\n frameworks.add(\"Symfony\");\n }\n }\n\n if (has(\"Gemfile\")) {\n languages.add(\"Ruby\");\n const gemfile = (await readText(rootDir, \"Gemfile\")).toLowerCase();\n if (gemfile.includes(\"rails\")) {\n frameworks.add(\"Ruby on Rails\");\n }\n }\n\n const deps = collectDependencies(pkg);\n if (\"next\" in deps) {\n frameworks.add(\"Next.js\");\n } else if (\"react\" in deps) {\n frameworks.add(\"React\");\n }\n if (\"@nestjs/core\" in deps) {\n frameworks.add(\"NestJS\");\n } else if (\"express\" in deps) {\n frameworks.add(\"Express\");\n }\n\n const python = pythonText.toLowerCase();\n if (python.includes(\"fastapi\")) {\n frameworks.add(\"FastAPI\");\n } else if (python.includes(\"flask\")) {\n frameworks.add(\"Flask\");\n } else if (python.includes(\"django\")) {\n frameworks.add(\"Django\");\n }\n\n if (has(\"go.mod\")) {\n const goModules = `${await readText(rootDir, \"go.mod\")}${await readText(rootDir, \"go.sum\")}`;\n if (goModules.includes(\"gin-gonic/gin\")) {\n frameworks.add(\"Gin\");\n } else if (goModules.includes(\"labstack/echo\")) {\n frameworks.add(\"Echo\");\n } else if (goModules.includes(\"gofiber/fiber\")) {\n frameworks.add(\"Fiber\");\n } else if (goModules.includes(\"go-chi/chi\")) {\n frameworks.add(\"Chi\");\n }\n }\n\n const jvmManifest =\n `${await readText(rootDir, \"pom.xml\")}${await readText(rootDir, \"build.gradle\")}${await readText(rootDir, \"build.gradle.kts\")}`.toLowerCase();\n if (jvmManifest.includes(\"spring-boot\") || jvmManifest.includes(\"springframework\")) {\n frameworks.add(\"Spring Boot\");\n }\n\n if (has(\"Cargo.toml\")) {\n const cargo = (await readText(rootDir, \"Cargo.toml\")).toLowerCase();\n if (cargo.includes(\"actix-web\")) {\n frameworks.add(\"Actix Web\");\n } else if (cargo.includes(\"axum\")) {\n frameworks.add(\"Axum\");\n } else if (cargo.includes(\"rocket\")) {\n frameworks.add(\"Rocket\");\n }\n }\n\n const [packageManager, packageManagerSource] = detectPackageManager(has);\n\n const scripts = pkg !== null && isRecord(pkg.scripts) ? pkg.scripts : {};\n const testsEvidence = await detectTestsEvidence(rootDir, has, \"test\" in scripts, python);\n\n return {\n languages: [...languages],\n packageManager,\n packageManagerSource,\n frameworks: [...frameworks],\n hasTests: testsEvidence !== null,\n testsEvidence,\n hasReadme: has(\"README.md\") || has(\"README\"),\n hasDocs: has(\"docs\"),\n };\n}\n\n/**\n * Human-readable summary of the inferred signals, with the source each was read from so a reviewer\n * can confirm or correct it. Shared by `recall adopt` (which persists it) and `recall init` (which\n * surfaces it). Every line is proposed, never accepted.\n */\nexport function summarizeSignals(signals: RepoSignals): string[] {\n const lines: string[] = [];\n\n lines.push(`- Languages: ${formatList(signals.languages)}`);\n\n lines.push(\n signals.packageManager === null\n ? \"- Package manager: none detected\"\n : `- Package manager: ${signals.packageManager}${\n signals.packageManagerSource === null ? \"\" : ` (from \\`${signals.packageManagerSource}\\`)`\n }`,\n );\n\n if (signals.frameworks.length === 0) {\n lines.push(\"- Frameworks: none detected\");\n } else {\n const withSource = signals.frameworks.map((framework) => {\n const source = FRAMEWORK_SOURCES[framework];\n return source === undefined ? framework : `${framework} (from \\`${source}\\`)`;\n });\n lines.push(`- Frameworks: ${withSource.join(\", \")}`);\n }\n\n lines.push(\n signals.testsEvidence === null\n ? \"- Tests: none detected — if tests exist, point Recall at them by correcting this report\"\n : `- Tests: detected via ${signals.testsEvidence}`,\n );\n\n lines.push(`- README present: ${signals.hasReadme ? \"yes\" : \"no\"}`);\n lines.push(`- Docs folder present: ${signals.hasDocs ? \"yes\" : \"no\"}`);\n\n return lines;\n}\n\nfunction formatList(values: string[]): string {\n return values.length === 0 ? \"none detected\" : values.join(\", \");\n}\n\n/**\n * Choose the repository's primary package manager. A backend manifest (Go, Rust, JVM, PHP, Ruby,\n * Python, Swift, Dart) wins over a JavaScript one, because a lone `package.json` in such a repo is\n * usually tooling (linters, git hooks) rather than the project's real package manager.\n */\nfunction detectPackageManager(\n has: (relativePath: string) => boolean,\n): [string | null, string | null] {\n const candidates: Array<[boolean, string, string]> = [\n [has(\"go.mod\"), \"Go modules\", \"go.mod\"],\n [has(\"Cargo.toml\"), \"Cargo\", \"Cargo.toml\"],\n [has(\"pom.xml\"), \"Maven\", \"pom.xml\"],\n [has(\"build.gradle\"), \"Gradle\", \"build.gradle\"],\n [has(\"build.gradle.kts\"), \"Gradle\", \"build.gradle.kts\"],\n [has(\"composer.json\"), \"Composer\", \"composer.json\"],\n [has(\"Gemfile\"), \"Bundler\", \"Gemfile\"],\n [has(\"Package.swift\"), \"Swift Package Manager\", \"Package.swift\"],\n [has(\"pubspec.yaml\"), \"pub\", \"pubspec.yaml\"],\n [has(\"uv.lock\"), \"uv\", \"uv.lock\"],\n [has(\"poetry.lock\"), \"Poetry\", \"poetry.lock\"],\n [has(\"requirements.txt\"), \"pip\", \"requirements.txt\"],\n [has(\"pyproject.toml\"), \"pip\", \"pyproject.toml\"],\n [has(\"pnpm-lock.yaml\"), \"pnpm\", \"pnpm-lock.yaml\"],\n [has(\"yarn.lock\"), \"yarn\", \"yarn.lock\"],\n [has(\"package-lock.json\"), \"npm\", \"package-lock.json\"],\n [has(\"package.json\"), \"npm\", \"package.json\"],\n ];\n\n for (const [present, name, source] of candidates) {\n if (present) {\n return [name, source];\n }\n }\n\n return [null, null];\n}\n\nasync function detectTestsEvidence(\n rootDir: string,\n has: (relativePath: string) => boolean,\n hasTestScript: boolean,\n pythonText: string,\n): Promise<string | null> {\n if (has(\"tests\")) {\n return \"`tests/` directory\";\n }\n if (has(\"test\")) {\n return \"`test/` directory\";\n }\n if (has(\"__tests__\")) {\n return \"`__tests__/` directory\";\n }\n if (has(\"pytest.ini\") || pythonText.includes(\"pytest\")) {\n return \"pytest configuration\";\n }\n if (has(\"phpunit.xml\") || has(\"phpunit.xml.dist\")) {\n return \"PHPUnit configuration\";\n }\n if (hasTestScript) {\n return '`\"test\"` script in package.json';\n }\n\n const testFile = await findTestFile(rootDir);\n if (testFile !== null) {\n return `\\`${testFile}\\``;\n }\n\n return null;\n}\n\nconst TEST_FILE_PATTERNS = [\n /_test\\.go$/u,\n /\\.(test|spec)\\.[cm]?[jt]sx?$/u,\n /^test_.+\\.py$/u,\n /_test\\.py$/u,\n /.+Tests?\\.(java|kt)$/u,\n /.+Test\\.php$/u,\n /_spec\\.rb$/u,\n /_test\\.rb$/u,\n];\n\nconst TEST_WALK_SKIP_DIRS = new Set([\n \"node_modules\",\n \"vendor\",\n \"dist\",\n \"build\",\n \"target\",\n \"coverage\",\n \"Pods\",\n \"__pycache__\",\n]);\n\n/**\n * Bounded, read-only walk that detects test files across ecosystems (Go `*_test.go`, JS/TS\n * `*.test.*`/`*.spec.*`, Python `test_*.py`, JVM `*Test.(java|kt)`, PHP `*Test.php`, Ruby `*_spec.rb`).\n * Capped at a fixed entry budget and skips heavy/vendored directories so it stays fast on large repos.\n */\nasync function findTestFile(rootDir: string): Promise<string | null> {\n let budget = 4000;\n const stack = [rootDir];\n\n while (stack.length > 0 && budget > 0) {\n const dir = stack.pop();\n if (dir === undefined) {\n break;\n }\n\n let entries;\n try {\n entries = await readdir(dir, { withFileTypes: true });\n } catch {\n continue;\n }\n\n for (const entry of entries) {\n budget -= 1;\n if (budget <= 0) {\n break;\n }\n\n if (entry.isDirectory()) {\n if (!TEST_WALK_SKIP_DIRS.has(entry.name) && !entry.name.startsWith(\".\")) {\n stack.push(path.join(dir, entry.name));\n }\n } else if (TEST_FILE_PATTERNS.some((pattern) => pattern.test(entry.name))) {\n return path.relative(rootDir, path.join(dir, entry.name));\n }\n }\n }\n\n return null;\n}\n\nfunction collectDependencies(pkg: Record<string, unknown> | null): Record<string, unknown> {\n if (pkg === null) {\n return {};\n }\n\n const dependencies = isRecord(pkg.dependencies) ? pkg.dependencies : {};\n const devDependencies = isRecord(pkg.devDependencies) ? pkg.devDependencies : {};\n\n return { ...dependencies, ...devDependencies };\n}\n\nasync function readJson(\n rootDir: string,\n relativePath: string,\n): Promise<Record<string, unknown> | null> {\n try {\n const parsed = JSON.parse(await readText(rootDir, relativePath)) as unknown;\n return isRecord(parsed) ? parsed : null;\n } catch {\n return null;\n }\n}\n\nasync function readText(rootDir: string, relativePath: string): Promise<string> {\n try {\n return await readFile(path.join(rootDir, relativePath), \"utf8\");\n } catch {\n return \"\";\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import type { WriteFileInput } from \"../filesystem/write-plan.js\";\nimport { summarizeSignals, type RepoSignals } from \"./inspect-repo.js\";\n\nexport const ADOPTION_REPORT_PATH = \"docs/adopt/ADOPTION_REPORT.md\";\n\nexport type GenerateAdoptionOptions = {\n adrDir: string;\n signals: RepoSignals;\n};\n\nexport function generateAdoptionFiles(options: GenerateAdoptionOptions): WriteFileInput[] {\n const files: WriteFileInput[] = [\n {\n path: ADOPTION_REPORT_PATH,\n content: renderReport(options.adrDir, options.signals),\n },\n ];\n\n for (const framework of options.signals.frameworks) {\n files.push({\n path: `${options.adrDir}/proposed/ADR-PROPOSED-adopt-${frameworkSlug(framework)}.md`,\n content: renderProposedAdr(framework),\n });\n }\n\n return files;\n}\n\nfunction renderReport(adrDir: string, signals: RepoSignals): string {\n return `# Adoption Report\n\n## Status\n\nProposed. Everything below is inferred from this repository and requires human review. Nothing here\nis accepted repository memory until you accept it.\n\n## Detected Signals\n\nEach signal notes the file it was inferred from. If one is wrong, correct the source or edit this\nreport — nothing here is accepted.\n\n${summarizeSignals(signals).join(\"\\n\")}\n\n## Proposed Decisions\n\n${renderProposedDecisions(adrDir, signals)}\n\n## Review Checklist\n\n- [ ] Confirm the detected languages and package manager (and the source each was read from).\n- [ ] Confirm where tests were detected, or point Recall at the right location if it is wrong.\n- [ ] Accept or reject each proposed framework ADR under \\`${adrDir}/proposed/\\`.\n- [ ] Run \\`recall init\\` to establish neutral repository memory if it does not exist yet.\n- [ ] Record any decision you accept with \\`recall adr create\\` or by accepting the proposed ADR.\n\n## Notes\n\nThis report was produced by \\`recall adopt\\` through read-only inspection of manifest and marker\nfiles. No repository code was executed and no decision was accepted automatically.\n`;\n}\n\nfunction renderProposedDecisions(adrDir: string, signals: RepoSignals): string {\n if (signals.frameworks.length === 0) {\n return \"- No framework decisions were inferred. Add decisions with `recall adr create` as needed.\";\n }\n\n return signals.frameworks\n .map(\n (framework) =>\n `- Proposed: record **${framework}** as an architecture decision (see ` +\n `\\`${adrDir}/proposed/ADR-PROPOSED-adopt-${frameworkSlug(framework)}.md\\`). Requires review.`,\n )\n .join(\"\\n\");\n}\n\nfunction renderProposedAdr(framework: string): string {\n return `# Proposed ADR: Use ${framework}\n\n## Status\n\nProposed\n\n## Context\n\n\\`recall adopt\\` detected ${framework} in this repository through read-only inspection.\n\n## Decision\n\nConsider recording ${framework} as an accepted architecture decision. This is proposed by adoption\nand is not accepted until a human reviews and accepts it.\n\n## Alternatives Considered\n\n- Record a different framework.\n- Leave the decision unrecorded for now.\n\n## Consequences\n\n- Captures a framework already in use as reviewable repository memory.\n- Requires explicit human acceptance before it becomes repository truth.\n\n## Related Documents\n\n- \\`docs/10-architecture/ARCHITECTURE.md\\` — record the accepted architecture here once promoted.\n- The adoption report generated alongside this proposal.\n`;\n}\n\nfunction frameworkSlug(framework: string): string {\n return framework\n .toLowerCase()\n .replace(/\\./gu, \"\")\n .replace(/[^a-z0-9]+/gu, \"-\")\n .replace(/^-+|-+$/gu, \"\");\n}\n","import { createDefaultConfig } from \"../core/config/default-config.js\";\nimport { ConfigValidationError } from \"../core/config/config-schema.js\";\nimport { loadConfig, ConfigLoadError } from \"../core/config/load-config.js\";\nimport { generateAdoptionFiles } from \"../core/adopt/generate-adoption.js\";\nimport { inspectRepo, type RepoSignals } from \"../core/adopt/inspect-repo.js\";\nimport { createWritePlan, type WritePlan } from \"../core/filesystem/write-plan.js\";\nimport { executeWritePlan, type WriteResult } from \"../core/filesystem/write-file-safe.js\";\nimport { appendNextSteps, appendWriteSummary } from \"./write-summary.js\";\n\nexport type AdoptOptions = {\n rootDir: string;\n dryRun?: boolean;\n force?: boolean;\n};\n\nexport type AdoptResult = {\n signals: RepoSignals;\n dryRun: boolean;\n plan: WritePlan;\n writeResult: WriteResult;\n};\n\nexport type AdoptErrorCode = \"WRITE_PLAN_ERROR\";\n\nexport class AdoptError extends Error {\n readonly code: AdoptErrorCode;\n readonly details: string[];\n\n constructor(code: AdoptErrorCode, message: string, details: string[] = []) {\n super(message);\n this.name = \"AdoptError\";\n this.code = code;\n this.details = details;\n }\n}\n\nexport async function adoptProject(options: AdoptOptions): Promise<AdoptResult> {\n const config = await loadConfigOrDefault(options.rootDir);\n const signals = await inspectRepo(options.rootDir);\n const files = generateAdoptionFiles({ adrDir: config.adrDir, signals });\n const plan = createWritePlan({\n rootDir: options.rootDir,\n files,\n force: options.force,\n });\n\n if (plan.hasErrors) {\n throw new AdoptError(\n \"WRITE_PLAN_ERROR\",\n \"Recall OS adopt write plan contains errors.\",\n plan.entries\n .filter((entry) => entry.action === \"error\")\n .map((entry) => `${entry.path}: ${entry.reason}`),\n );\n }\n\n const writeResult = await executeWritePlan(plan, { dryRun: options.dryRun });\n\n return {\n signals,\n dryRun: options.dryRun ?? false,\n plan,\n writeResult,\n };\n}\n\nexport function formatAdoptResult(result: AdoptResult): string {\n const lines = [\n result.dryRun ? \"Recall OS adopt dry run complete.\" : \"Recall OS adopt complete.\",\n \"Inferred signals are proposed and require human review.\",\n `Languages: ${formatList(result.signals.languages)}`,\n `Package manager: ${result.signals.packageManager ?? \"none detected\"}`,\n `Frameworks: ${formatList(result.signals.frameworks)}`,\n ];\n\n appendWriteSummary(lines, {\n dryRun: result.dryRun,\n writeResult: result.writeResult,\n });\n\n if (!result.dryRun) {\n appendNextSteps(lines, [\n \"Review docs/adopt/ADOPTION_REPORT.md — everything in it is proposed.\",\n \"Run `recall init` to establish neutral repository memory if it does not exist yet.\",\n \"Accept or reject each proposed ADR under docs/adrs/proposed/.\",\n ]);\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nasync function loadConfigOrDefault(rootDir: string) {\n try {\n return await loadConfig(rootDir);\n } catch (error) {\n if (error instanceof ConfigLoadError || error instanceof ConfigValidationError) {\n return createDefaultConfig();\n }\n\n throw error;\n }\n}\n\nfunction formatList(values: string[]): string {\n return values.length > 0 ? values.join(\", \") : \"none detected\";\n}\n","import { existsSync } from \"node:fs\";\nimport { readFile, readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport type { DoctorCheckContext, DoctorFinding } from \"../doctor-check.js\";\n\nconst featureFolderPattern = /^F-\\d{3,}-[a-z0-9]+(?:-[a-z0-9]+)*$/u;\n\n// Only the current-state docs are checked. Historical docs (completion reports, reviews) legitimately\n// reference paths as they were at the time and must not be flagged when code is later refactored.\nconst FEATURE_DOCS = [\"PRD.md\", \"ARCHITECTURE_IMPACT.md\"];\nconst MODULE_DOCS = [\"MODULE.md\", \"DECISIONS.md\"];\n\n// An inline-code token that looks like a concrete source path: under src/ or tests/, with a file\n// extension. Placeholder-bearing paths (`<id>`, globs, `...`) are skipped so illustrative paths do\n// not false-positive.\nconst codePathPattern = /`((?:src|tests)\\/[A-Za-z0-9._/-]+\\.[A-Za-z0-9]+)`/gu;\nconst placeholderMarkers = /[<>*]|\\.\\.\\./u;\n\n/**\n * Deterministic memory-to-code drift check.\n *\n * Flags current-state memory that cites a `src/` or `tests/` path which no longer exists, so stale\n * documentation that references renamed or deleted code is surfaced rather than silently trusted.\n */\nexport async function checkCodeReferences(context: DoctorCheckContext): Promise<DoctorFinding[]> {\n if (context.config === undefined) {\n return [];\n }\n\n const findings: DoctorFinding[] = [];\n\n const featureEntries = await readDirIfExists(context.rootDir, context.config.featuresDir);\n for (const folder of featureEntries) {\n if (!folder.isDirectory() || !featureFolderPattern.test(folder.name)) {\n continue;\n }\n for (const doc of FEATURE_DOCS) {\n const relativePath = path.posix.join(context.config.featuresDir, folder.name, doc);\n findings.push(...(await checkDoc(context.rootDir, relativePath)));\n }\n }\n\n const moduleEntries = await readDirIfExists(context.rootDir, context.config.modulesDir);\n for (const folder of moduleEntries) {\n if (!folder.isDirectory()) {\n continue;\n }\n for (const doc of MODULE_DOCS) {\n const relativePath = path.posix.join(context.config.modulesDir, folder.name, doc);\n findings.push(...(await checkDoc(context.rootDir, relativePath)));\n }\n }\n\n return findings;\n}\n\nasync function checkDoc(rootDir: string, relativePath: string): Promise<DoctorFinding[]> {\n const content = await readFileIfExists(rootDir, relativePath);\n if (content === undefined) {\n return [];\n }\n\n const findings: DoctorFinding[] = [];\n const seen = new Set<string>();\n\n for (const match of content.matchAll(codePathPattern)) {\n const reference = match[1];\n if (placeholderMarkers.test(reference) || seen.has(reference)) {\n continue;\n }\n seen.add(reference);\n\n if (!existsSync(path.join(rootDir, reference))) {\n findings.push({\n severity: \"warning\",\n check: \"drift-code-reference\",\n message: `Repository memory references ${reference}, which does not exist.`,\n path: relativePath,\n });\n }\n }\n\n return findings;\n}\n\nasync function readDirIfExists(rootDir: string, relativePath: string) {\n try {\n return await readdir(path.join(rootDir, relativePath), { withFileTypes: true });\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return [];\n }\n throw error;\n }\n}\n\nasync function readFileIfExists(\n rootDir: string,\n relativePath: string,\n): Promise<string | undefined> {\n try {\n return await readFile(path.join(rootDir, relativePath), \"utf8\");\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return undefined;\n }\n throw error;\n }\n}\n","import { readFile } from \"node:fs/promises\";\n\nimport {\n ConfigValidationError,\n parseConfig,\n type RecallConfig,\n} from \"../../config/config-schema.js\";\nimport { CONFIG_PATH } from \"../../config/load-config.js\";\nimport { resolveSafePath } from \"../../filesystem/safe-path.js\";\nimport type { DoctorFinding } from \"../doctor-check.js\";\n\nexport type ConfigCheckResult = {\n config?: RecallConfig;\n findings: DoctorFinding[];\n};\n\nexport async function checkConfig(rootDir: string): Promise<ConfigCheckResult> {\n const configPath = resolveSafePath(rootDir, CONFIG_PATH);\n\n let rawConfig: string;\n try {\n rawConfig = await readFile(configPath.absolutePath, \"utf8\");\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return {\n findings: [\n {\n severity: \"error\",\n check: \"config\",\n message: \"Missing .recall/config.json.\",\n path: CONFIG_PATH,\n },\n ],\n };\n }\n throw error;\n }\n\n let parsedJson: unknown;\n try {\n parsedJson = JSON.parse(rawConfig);\n } catch {\n return {\n findings: [\n {\n severity: \"error\",\n check: \"config\",\n message: \"Config file is not valid JSON.\",\n path: CONFIG_PATH,\n },\n ],\n };\n }\n\n try {\n const config = parseConfig(parsedJson);\n\n return {\n config,\n findings: [\n {\n severity: \"info\",\n check: \"config\",\n message: \"Recall OS config validates.\",\n path: CONFIG_PATH,\n },\n ],\n };\n } catch (error) {\n if (error instanceof ConfigValidationError) {\n return {\n findings: [\n {\n severity: \"error\",\n check: \"config\",\n message: error.message,\n path: CONFIG_PATH,\n },\n ],\n };\n }\n\n throw error;\n }\n}\n","import { readFile, readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport type { DoctorCheckContext, DoctorFinding } from \"../doctor-check.js\";\n\nconst featureFolderPattern = /^F-\\d{3,}-[a-z0-9]+(?:-[a-z0-9]+)*$/u;\nconst acceptedAdrPattern = /^ADR-\\d{4,}-[a-z0-9]+(?:-[a-z0-9]+)*\\.md$/u;\n\nconst SECURITY_MODEL_PATH = \"docs/20-security/SECURITY_MODEL.md\";\nconst THREAT_MODEL_PATH = \"docs/20-security/THREAT_MODEL.md\";\n\n/**\n * Content-completeness check.\n *\n * Flags feature PRDs and module memory whose required sections are still unedited template stubs, so\n * generated scaffolds become an enforced workflow rather than silent empty docs. Findings are\n * warnings: they surface gaps without hard-failing structurally healthy repositories.\n */\nexport async function checkContent(context: DoctorCheckContext): Promise<DoctorFinding[]> {\n if (context.config === undefined) {\n return [];\n }\n\n const findings: DoctorFinding[] = [];\n const entries = await readDirIfExists(context.rootDir, context.config.featuresDir);\n const featureFolders = entries.filter(\n (entry) => entry.isDirectory() && featureFolderPattern.test(entry.name),\n );\n\n for (const folder of featureFolders) {\n const prdPath = path.posix.join(context.config.featuresDir, folder.name, \"PRD.md\");\n const prd = await readFileIfExists(context.rootDir, prdPath);\n\n if (prd === undefined) {\n continue;\n }\n\n if (sectionIsUnfilled(prd, \"Purpose\")) {\n findings.push({\n severity: \"warning\",\n check: \"content-feature-prd\",\n message: \"Feature PRD purpose is still an unfilled template.\",\n path: prdPath,\n });\n }\n\n if (sectionIsUnfilled(prd, \"In Scope\")) {\n findings.push({\n severity: \"warning\",\n check: \"content-feature-prd\",\n message: \"Feature PRD in-scope section is still an unfilled template.\",\n path: prdPath,\n });\n }\n }\n\n const moduleEntries = await readDirIfExists(context.rootDir, context.config.modulesDir);\n const moduleFolders = moduleEntries.filter((entry) => entry.isDirectory());\n\n const adrEntries = await readDirIfExists(context.rootDir, context.config.adrDir);\n const acceptedAdrs = adrEntries.filter(\n (entry) => entry.isFile() && acceptedAdrPattern.test(entry.name),\n );\n\n // Force the foundational security docs to be filled, but only once the repository has real work.\n // A bare `recall init` stays green; a project with a feature, module, or accepted decision must\n // not leave its threat model and security model as untouched stubs.\n const hasWork = featureFolders.length > 0 || moduleFolders.length > 0 || acceptedAdrs.length > 0;\n\n if (hasWork) {\n findings.push(...(await checkSecurityDoc(context.rootDir)));\n }\n\n for (const folder of moduleFolders) {\n const modulePath = path.posix.join(context.config.modulesDir, folder.name, \"MODULE.md\");\n const moduleDoc = await readFileIfExists(context.rootDir, modulePath);\n\n if (moduleDoc === undefined) {\n continue;\n }\n\n if (sectionIsUnfilled(moduleDoc, \"Purpose\")) {\n findings.push({\n severity: \"warning\",\n check: \"content-module\",\n message: \"Module memory purpose is still an unfilled template.\",\n path: modulePath,\n });\n }\n\n if (sectionIsUnfilled(moduleDoc, \"Owns\")) {\n findings.push({\n severity: \"warning\",\n check: \"content-module\",\n message: \"Module memory owns section is still an unfilled template.\",\n path: modulePath,\n });\n }\n }\n\n return findings;\n}\n\nasync function checkSecurityDoc(rootDir: string): Promise<DoctorFinding[]> {\n const findings: DoctorFinding[] = [];\n\n const security = await readFileIfExists(rootDir, SECURITY_MODEL_PATH);\n if (security !== undefined && sectionIsUnfilled(security, \"Authentication And Authorization\")) {\n findings.push({\n severity: \"warning\",\n check: \"content-security\",\n message:\n \"Security model authentication and authorization section is still an unfilled template.\",\n path: SECURITY_MODEL_PATH,\n });\n }\n\n const threat = await readFileIfExists(rootDir, THREAT_MODEL_PATH);\n if (threat !== undefined && sectionIsUnfilled(threat, \"Assets\")) {\n findings.push({\n severity: \"warning\",\n check: \"content-threat-model\",\n message: \"Threat model assets section is still an unfilled template.\",\n path: THREAT_MODEL_PATH,\n });\n }\n\n return findings;\n}\n\nfunction sectionIsUnfilled(content: string, heading: string): boolean {\n const section = getSection(content, heading);\n return section !== undefined && isUnfilled(section);\n}\n\nfunction isUnfilled(value: string): boolean {\n const normalized = value\n .replace(/[`*_>#-]/gu, \" \")\n .replace(/\\s+/gu, \" \")\n .trim()\n .toLowerCase()\n .replace(/\\.$/u, \"\");\n\n if (normalized.length === 0) {\n return true;\n }\n\n if (\n normalized === \"tbd\" ||\n normalized === \"todo\" ||\n normalized === \"pending\" ||\n normalized === \"none\" ||\n normalized === \"n/a\"\n ) {\n return true;\n }\n\n return (\n normalized.includes(\"describe why this feature exists\") ||\n normalized.includes(\"describe what this module owns\") ||\n normalized.includes(\"describe how this repository authenticates\") ||\n normalized.includes(\"describe what this repository must protect\")\n );\n}\n\nfunction getSection(content: string, heading: string): string | undefined {\n const lines = content.split(/\\r?\\n/u);\n const normalizedHeading = `## ${heading.toLowerCase()}`;\n const startIndex = lines.findIndex((line) => line.trim().toLowerCase() === normalizedHeading);\n\n if (startIndex === -1) {\n return undefined;\n }\n\n const body: string[] = [];\n\n for (let index = startIndex + 1; index < lines.length; index += 1) {\n if (/^##\\s+/u.test(lines[index])) {\n break;\n }\n\n body.push(lines[index]);\n }\n\n return body.join(\"\\n\").trim();\n}\n\nasync function readDirIfExists(rootDir: string, relativePath: string) {\n try {\n return await readdir(path.join(rootDir, relativePath), { withFileTypes: true });\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return [];\n }\n throw error;\n }\n}\n\nasync function readFileIfExists(\n rootDir: string,\n relativePath: string,\n): Promise<string | undefined> {\n try {\n return await readFile(path.join(rootDir, relativePath), \"utf8\");\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return undefined;\n }\n throw error;\n }\n}\n","import { readFile, readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport type { DoctorCheckContext, DoctorFinding } from \"../doctor-check.js\";\n\nconst adrFilePattern = /^ADR-(\\d{4,})-[a-z0-9]+(?:-[a-z0-9]+)*\\.md$/iu;\nconst adrReferencePattern = /ADR-\\d{4,}/giu;\n\ntype KnownAdr = {\n id: string;\n accepted: boolean;\n};\n\n/**\n * Deterministic, local, read-only drift check.\n *\n * Detects repository memory that references ADR identifiers which either do not exist\n * (dangling decision references) or are not yet accepted (reliance on a proposed decision).\n */\nexport async function checkDrift(context: DoctorCheckContext): Promise<DoctorFinding[]> {\n if (context.config === undefined) {\n return [];\n }\n\n const knownAdrs = await loadKnownAdrs(context.rootDir, context.config.adrDir);\n\n const findings: DoctorFinding[] = [];\n findings.push(...(await checkReferences(context.rootDir, context.config.featuresDir, knownAdrs)));\n findings.push(...(await checkReferences(context.rootDir, context.config.modulesDir, knownAdrs)));\n\n return findings;\n}\n\nasync function loadKnownAdrs(rootDir: string, adrDir: string): Promise<Map<string, KnownAdr>> {\n const known = new Map<string, KnownAdr>();\n const files = await readMarkdownFiles(rootDir, adrDir);\n\n for (const file of files) {\n const match = adrFilePattern.exec(path.basename(file));\n if (match === null) {\n continue;\n }\n\n const id = `ADR-${match[1]}`;\n const content = await readFile(path.join(rootDir, file), \"utf8\");\n const accepted = sectionContains(content, \"Status\", /\\baccepted\\b/iu);\n\n // First accepted declaration wins; otherwise keep the existing record.\n const existing = known.get(id);\n if (existing === undefined || (!existing.accepted && accepted)) {\n known.set(id, { id, accepted });\n }\n }\n\n return known;\n}\n\nasync function checkReferences(\n rootDir: string,\n referenceDir: string,\n knownAdrs: Map<string, KnownAdr>,\n): Promise<DoctorFinding[]> {\n const findings: DoctorFinding[] = [];\n const files = await readMarkdownFiles(rootDir, referenceDir);\n\n for (const file of files) {\n const content = await readFile(path.join(rootDir, file), \"utf8\");\n const referenced = new Set<string>();\n\n // Ignore ADR identifiers inside fenced code blocks and inline code so illustrative\n // examples are not treated as real references.\n for (const match of stripCode(content).matchAll(adrReferencePattern)) {\n referenced.add(match[0].toUpperCase());\n }\n\n for (const id of referenced) {\n const known = knownAdrs.get(id);\n\n if (known === undefined) {\n findings.push({\n severity: \"error\",\n check: \"drift-adr-reference\",\n message: `Repository memory references ${id} but no matching ADR exists.`,\n path: file,\n });\n continue;\n }\n\n if (!known.accepted) {\n findings.push({\n severity: \"warning\",\n check: \"drift-proposed-reference\",\n message: `Repository memory references ${id} which is not accepted.`,\n path: file,\n });\n }\n }\n }\n\n return findings;\n}\n\nfunction stripCode(content: string): string {\n return content\n .replace(/```[\\s\\S]*?```/gu, \" \")\n .replace(/~~~[\\s\\S]*?~~~/gu, \" \")\n .replace(/`[^`]*`/gu, \" \");\n}\n\nasync function readMarkdownFiles(rootDir: string, relativeDir: string): Promise<string[]> {\n const entries = await readDirIfExists(rootDir, relativeDir);\n const files: string[] = [];\n\n for (const entry of entries) {\n const childRelative = path.posix.join(relativeDir, entry.name);\n\n if (entry.isDirectory()) {\n files.push(...(await readMarkdownFiles(rootDir, childRelative)));\n continue;\n }\n\n if (entry.isFile() && entry.name.toLowerCase().endsWith(\".md\")) {\n files.push(childRelative);\n }\n }\n\n return files;\n}\n\nfunction sectionContains(content: string, heading: string, pattern: RegExp): boolean {\n const section = getSection(content, heading);\n return section !== undefined && pattern.test(section);\n}\n\nfunction getSection(content: string, heading: string): string | undefined {\n const lines = content.split(/\\r?\\n/u);\n const normalizedHeading = `## ${heading.toLowerCase()}`;\n const startIndex = lines.findIndex((line) => line.trim().toLowerCase() === normalizedHeading);\n\n if (startIndex === -1) {\n return undefined;\n }\n\n const body: string[] = [];\n\n for (let index = startIndex + 1; index < lines.length; index += 1) {\n if (/^##\\s+/u.test(lines[index])) {\n break;\n }\n\n body.push(lines[index]);\n }\n\n return body.join(\"\\n\").trim();\n}\n\nasync function readDirIfExists(rootDir: string, relativePath: string) {\n try {\n return await readdir(path.join(rootDir, relativePath), { withFileTypes: true });\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return [];\n }\n throw error;\n }\n}\n","import { lstat, readFile, readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { REQUIRED_ADR_SECTIONS } from \"../../adr/adr-sections.js\";\nimport type { DoctorCheckContext, DoctorFinding } from \"../doctor-check.js\";\n\nconst featureFolderPattern = /^F-\\d{3,}-[a-z0-9]+(?:-[a-z0-9]+)*$/u;\nconst adrFilePattern = /^ADR-\\d{4,}-[a-z0-9]+(?:-[a-z0-9]+)*\\.md$/u;\n\nconst requiredFeatureDocs = [\n \"PRD.md\",\n \"ACCEPTANCE.md\",\n \"ARCHITECTURE_IMPACT.md\",\n \"CHANGE_REQUESTS.md\",\n \"PLAN.md\",\n \"TASKS.md\",\n \"TEST_PLAN.md\",\n \"REVIEW.md\",\n \"COMPLETION_REPORT.md\",\n];\n\nconst requiredModuleDocs = [\"MODULE.md\", \"TASKS.md\", \"TEST_PLAN.md\", \"DECISIONS.md\"];\n\nconst requiredAdrSections = REQUIRED_ADR_SECTIONS;\n\nexport async function checkMemoryIntegrity(context: DoctorCheckContext): Promise<DoctorFinding[]> {\n if (context.config === undefined) {\n return [];\n }\n\n const findings: DoctorFinding[] = [];\n\n findings.push(...(await checkFeatureFolders(context.rootDir, context.config.featuresDir)));\n findings.push(...(await checkModuleFolders(context.rootDir, context.config.modulesDir)));\n findings.push(...(await checkAdrFiles(context.rootDir, context.config.adrDir)));\n\n return findings;\n}\n\nasync function checkFeatureFolders(rootDir: string, featuresDir: string): Promise<DoctorFinding[]> {\n const findings: DoctorFinding[] = [];\n const entries = await readDirIfExists(rootDir, featuresDir);\n const featureFolders = entries.filter(\n (entry) => entry.isDirectory() && featureFolderPattern.test(entry.name),\n );\n\n for (const featureFolder of featureFolders) {\n for (const requiredDoc of requiredFeatureDocs) {\n const filePath = path.posix.join(featuresDir, featureFolder.name, requiredDoc);\n if (!(await isFile(rootDir, filePath))) {\n findings.push({\n severity: \"error\",\n check: \"feature-memory\",\n message: \"Feature folder is missing a required doc.\",\n path: filePath,\n });\n }\n }\n }\n\n findings.push({\n severity: \"info\",\n check: \"feature-memory\",\n message: `${featureFolders.length} feature folders detected.`,\n });\n\n return findings;\n}\n\nasync function checkModuleFolders(rootDir: string, modulesDir: string): Promise<DoctorFinding[]> {\n const findings: DoctorFinding[] = [];\n const entries = await readDirIfExists(rootDir, modulesDir);\n const moduleFolders = entries.filter((entry) => entry.isDirectory());\n\n for (const moduleFolder of moduleFolders) {\n for (const requiredDoc of requiredModuleDocs) {\n const filePath = path.posix.join(modulesDir, moduleFolder.name, requiredDoc);\n if (!(await isFile(rootDir, filePath))) {\n findings.push({\n severity: \"error\",\n check: \"module-memory\",\n message: \"Module folder is missing a required doc.\",\n path: filePath,\n });\n }\n }\n }\n\n findings.push({\n severity: \"info\",\n check: \"module-memory\",\n message: `${moduleFolders.length} module folders detected.`,\n });\n\n return findings;\n}\n\nasync function checkAdrFiles(rootDir: string, adrDir: string): Promise<DoctorFinding[]> {\n const findings: DoctorFinding[] = [];\n const entries = await readDirIfExists(rootDir, adrDir);\n const adrFiles = entries.filter((entry) => entry.isFile() && adrFilePattern.test(entry.name));\n\n for (const adrFile of adrFiles) {\n const filePath = path.posix.join(adrDir, adrFile.name);\n const content = await readFile(path.join(rootDir, filePath), \"utf8\");\n\n for (const requiredSection of requiredAdrSections) {\n if (!content.includes(requiredSection)) {\n findings.push({\n severity: \"error\",\n check: \"adr-memory\",\n message: `ADR file is missing required section ${requiredSection}.`,\n path: filePath,\n });\n }\n }\n }\n\n findings.push({\n severity: \"info\",\n check: \"adr-memory\",\n message: `${adrFiles.length} ADRs detected.`,\n });\n\n return findings;\n}\n\nasync function readDirIfExists(rootDir: string, relativePath: string) {\n try {\n return await readdir(path.join(rootDir, relativePath), { withFileTypes: true });\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return [];\n }\n throw error;\n }\n}\n\nasync function isFile(rootDir: string, relativePath: string): Promise<boolean> {\n try {\n return (await lstat(path.join(rootDir, relativePath))).isFile();\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return false;\n }\n throw error;\n }\n}\n","/**\n * The section headings every accepted ADR must contain. This is the single source of truth:\n * `recall doctor` validates against it, and every generator that emits a proposed ADR\n * (presets, `recall mcp add`, `recall adopt`) normalizes its body to include all of them — so a\n * proposed ADR stays healthy once a human promotes it with `recall adr accept`.\n */\nexport const REQUIRED_ADR_SECTIONS = [\n \"## Status\",\n \"## Context\",\n \"## Decision\",\n \"## Alternatives Considered\",\n \"## Consequences\",\n \"## Related Documents\",\n] as const;\n\nconst SECTION_PLACEHOLDERS: Record<string, string> = {\n \"## Related Documents\":\n \"- None yet. Link related ADRs, features, or modules as they are accepted.\",\n};\n\n/**\n * Append any required ADR section missing from `body`, using a neutral proposed-stage placeholder.\n * Idempotent: a body that already contains every required section is returned unchanged (aside from\n * a single trailing newline). Generated proposed ADRs historically stopped at `## Consequences`,\n * which made them fail Doctor's `## Related Documents` check the moment they were accepted.\n */\nexport function ensureRequiredAdrSections(body: string): string {\n let result = body.replace(/\\s+$/u, \"\");\n\n for (const section of REQUIRED_ADR_SECTIONS) {\n if (!result.includes(section)) {\n const placeholder = SECTION_PLACEHOLDERS[section] ?? \"To be documented.\";\n result += `\\n\\n${section}\\n\\n${placeholder}`;\n }\n }\n\n return `${result}\\n`;\n}\n","import { lstat } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport type { DoctorCheckContext, DoctorFinding } from \"../doctor-check.js\";\n\nconst rootFiles = [\"AGENTS.md\", \"CLAUDE.md\"];\n\nconst requiredDocs = [\n \"00-product/PRD.md\",\n \"00-product/BRD.md\",\n \"10-architecture/ARCHITECTURE.md\",\n \"10-architecture/MEMORY_ENGINE.md\",\n \"10-architecture/FILE_WRITE_POLICY.md\",\n \"20-security/SECURITY_MODEL.md\",\n \"20-security/THREAT_MODEL.md\",\n \"50-quality/TESTING_STRATEGY.md\",\n \"50-quality/QUALITY_GATES.md\",\n \"60-engineering/ENGINEERING_STANDARDS.md\",\n \"60-engineering/AI_AGENT_RULES.md\",\n \"ai/AI_AGENTS_SKILLS_MCP_STRATEGY.md\",\n \"ai/MCP_STRATEGY.md\",\n \"ai/RECALL_COMMANDS.md\",\n];\n\nexport async function checkRequiredFiles(context: DoctorCheckContext): Promise<DoctorFinding[]> {\n const findings: DoctorFinding[] = [];\n const docsDir = context.config?.docsDir ?? \"docs\";\n\n for (const filePath of rootFiles) {\n if (!(await isFile(context.rootDir, filePath))) {\n findings.push(missingFile(filePath, \"required-files\"));\n }\n }\n\n for (const relativeDocPath of requiredDocs) {\n const filePath = path.posix.join(docsDir, relativeDocPath);\n if (!(await isFile(context.rootDir, filePath))) {\n findings.push(missingFile(filePath, \"required-docs\"));\n }\n }\n\n const adrIndexPath = path.posix.join(context.config?.adrDir ?? \"docs/adrs\", \"README.md\");\n if (!(await isFile(context.rootDir, adrIndexPath))) {\n findings.push(missingFile(adrIndexPath, \"required-docs\"));\n }\n\n if (context.config !== undefined) {\n const requiredDirectories = [\n context.config.docsDir,\n context.config.featuresDir,\n context.config.modulesDir,\n context.config.adrDir,\n ];\n\n for (const directoryPath of requiredDirectories) {\n if (!(await isDirectory(context.rootDir, directoryPath))) {\n findings.push({\n severity: \"error\",\n check: \"configured-directories\",\n message: \"Configured directory is missing.\",\n path: directoryPath,\n });\n }\n }\n }\n\n return findings;\n}\n\nasync function isFile(rootDir: string, relativePath: string): Promise<boolean> {\n try {\n return (await lstat(path.join(rootDir, relativePath))).isFile();\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return false;\n }\n throw error;\n }\n}\n\nasync function isDirectory(rootDir: string, relativePath: string): Promise<boolean> {\n try {\n return (await lstat(path.join(rootDir, relativePath))).isDirectory();\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return false;\n }\n throw error;\n }\n}\n\nfunction missingFile(pathValue: string, check: string): DoctorFinding {\n return {\n severity: \"error\",\n check,\n message: \"Required file is missing.\",\n path: pathValue,\n };\n}\n","import { lstat, readFile, readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport type { DoctorCheckContext, DoctorFinding } from \"../doctor-check.js\";\n\nconst featureFolderPattern = /^F-\\d{3,}-[a-z0-9]+(?:-[a-z0-9]+)*$/u;\nconst adrFilePattern = /^ADR-\\d{4,}-[a-z0-9]+(?:-[a-z0-9]+)*\\.md$/u;\n\nconst securitySensitivePattern =\n /\\b(auth|authentication|authorization|secrets?|storage|networking?|telemetry|file writes?|write policy|dependencies?|mcp|ai api|cloud|runtime)\\b/iu;\n\nexport async function checkStandards(context: DoctorCheckContext): Promise<DoctorFinding[]> {\n if (context.config === undefined) {\n return [];\n }\n\n const findings: DoctorFinding[] = [];\n\n findings.push(...(await checkFeatureStandards(context.rootDir, context.config.featuresDir)));\n findings.push(...(await checkAdrStandards(context.rootDir, context.config.adrDir)));\n\n return findings;\n}\n\nasync function checkFeatureStandards(\n rootDir: string,\n featuresDir: string,\n): Promise<DoctorFinding[]> {\n const findings: DoctorFinding[] = [];\n const entries = await readDirIfExists(rootDir, featuresDir);\n const featureFolders = entries.filter(\n (entry) => entry.isDirectory() && featureFolderPattern.test(entry.name),\n );\n\n for (const featureFolder of featureFolders) {\n const featureDir = path.posix.join(featuresDir, featureFolder.name);\n const completionReportPath = path.posix.join(featureDir, \"COMPLETION_REPORT.md\");\n const reviewPath = path.posix.join(featureDir, \"REVIEW.md\");\n const architectureImpactPath = path.posix.join(featureDir, \"ARCHITECTURE_IMPACT.md\");\n\n const completionReport = await readFileIfExists(rootDir, completionReportPath);\n const review = await readFileIfExists(rootDir, reviewPath);\n const architectureImpact = await readFileIfExists(rootDir, architectureImpactPath);\n\n if (completionReport !== undefined) {\n const featureIsComplete = sectionContains(completionReport, \"Status\", /\\bcomplete\\b/iu);\n\n if (featureIsComplete) {\n if (review !== undefined && sectionContains(review, \"Status\", /\\bpending\\b/iu)) {\n findings.push({\n severity: \"error\",\n check: \"standards-feature-completion\",\n message: \"Feature is marked complete but review is still pending.\",\n path: reviewPath,\n });\n }\n\n if (!hasMeaningfulSection(completionReport, \"Tests Run\")) {\n findings.push({\n severity: \"error\",\n check: \"standards-feature-completion\",\n message: \"Feature is marked complete but completion report is missing test evidence.\",\n path: completionReportPath,\n });\n }\n\n if (!hasMeaningfulSection(completionReport, \"Results\")) {\n findings.push({\n severity: \"error\",\n check: \"standards-feature-completion\",\n message: \"Feature is marked complete but completion report is missing result evidence.\",\n path: completionReportPath,\n });\n }\n }\n\n if (architectureImpact !== undefined) {\n findings.push(\n ...checkSecurityImpactEvidence(\n architectureImpact,\n architectureImpactPath,\n featureIsComplete,\n ),\n );\n }\n }\n }\n\n return findings;\n}\n\nasync function checkAdrStandards(rootDir: string, adrDir: string): Promise<DoctorFinding[]> {\n const findings: DoctorFinding[] = [];\n const entries = await readDirIfExists(rootDir, adrDir);\n const adrFiles = entries.filter((entry) => entry.isFile() && adrFilePattern.test(entry.name));\n\n for (const adrFile of adrFiles) {\n const adrPath = path.posix.join(adrDir, adrFile.name);\n const content = await readFile(path.join(rootDir, adrPath), \"utf8\");\n const isAccepted = sectionContains(content, \"Status\", /\\baccepted\\b/iu);\n\n if (!hasMeaningfulSection(content, \"Consequences\")) {\n findings.push({\n severity: isAccepted ? \"error\" : \"warning\",\n check: \"standards-adr-consequences\",\n message: \"ADR consequence evidence is incomplete.\",\n path: adrPath,\n });\n }\n }\n\n return findings;\n}\n\nfunction checkSecurityImpactEvidence(\n architectureImpact: string,\n architectureImpactPath: string,\n featureIsComplete: boolean,\n): DoctorFinding[] {\n const contentWithoutSecuritySection = removeSection(architectureImpact, \"Security Impact\");\n\n if (!securitySensitivePattern.test(contentWithoutSecuritySection)) {\n return [];\n }\n\n if (hasMeaningfulSection(architectureImpact, \"Security Impact\")) {\n return [];\n }\n\n return [\n {\n severity: featureIsComplete ? \"error\" : \"warning\",\n check: \"standards-security-impact\",\n message: \"Security-sensitive feature planning is missing security impact evidence.\",\n path: architectureImpactPath,\n },\n ];\n}\n\nfunction sectionContains(content: string, heading: string, pattern: RegExp): boolean {\n const section = getSection(content, heading);\n return section !== undefined && pattern.test(section);\n}\n\nfunction hasMeaningfulSection(content: string, heading: string): boolean {\n const section = getSection(content, heading);\n return section !== undefined && !isPlaceholder(section);\n}\n\nfunction getSection(content: string, heading: string): string | undefined {\n const lines = content.split(/\\r?\\n/u);\n const startIndex = findSectionStart(lines, heading);\n\n if (startIndex === -1) {\n return undefined;\n }\n\n const body: string[] = [];\n\n for (let index = startIndex + 1; index < lines.length; index += 1) {\n if (/^##\\s+/u.test(lines[index])) {\n break;\n }\n\n body.push(lines[index]);\n }\n\n return body.join(\"\\n\").trim();\n}\n\nfunction removeSection(content: string, heading: string): string {\n const lines = content.split(/\\r?\\n/u);\n const startIndex = findSectionStart(lines, heading);\n\n if (startIndex === -1) {\n return content;\n }\n\n let endIndex = lines.length;\n for (let index = startIndex + 1; index < lines.length; index += 1) {\n if (/^##\\s+/u.test(lines[index])) {\n endIndex = index;\n break;\n }\n }\n\n return [...lines.slice(0, startIndex), ...lines.slice(endIndex)].join(\"\\n\");\n}\n\nfunction findSectionStart(lines: string[], heading: string): number {\n const normalizedHeading = `## ${heading.toLowerCase()}`;\n\n return lines.findIndex((line) => line.trim().toLowerCase() === normalizedHeading);\n}\n\nfunction isPlaceholder(value: string): boolean {\n const normalized = value\n .replace(/[`*_>#-]/gu, \" \")\n .replace(/\\s+/gu, \" \")\n .trim()\n .toLowerCase()\n .replace(/\\.$/u, \"\");\n\n if (normalized.length === 0) {\n return true;\n }\n\n if (\n normalized === \"tbd\" ||\n normalized === \"todo\" ||\n normalized === \"pending\" ||\n normalized === \"pending review\" ||\n normalized === \"draft\" ||\n normalized === \"none\" ||\n normalized === \"n/a\" ||\n normalized === \"not available yet\" ||\n normalized === \"not run yet\"\n ) {\n return true;\n }\n\n return (\n normalized.includes(\"implementation is in progress\") ||\n normalized.includes(\"will be completed after implementation\")\n );\n}\n\nasync function readDirIfExists(rootDir: string, relativePath: string) {\n try {\n return await readdir(path.join(rootDir, relativePath), { withFileTypes: true });\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return [];\n }\n throw error;\n }\n}\n\nasync function readFileIfExists(\n rootDir: string,\n relativePath: string,\n): Promise<string | undefined> {\n try {\n if (!(await isFile(rootDir, relativePath))) {\n return undefined;\n }\n\n return await readFile(path.join(rootDir, relativePath), \"utf8\");\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return undefined;\n }\n throw error;\n }\n}\n\nasync function isFile(rootDir: string, relativePath: string): Promise<boolean> {\n try {\n return (await lstat(path.join(rootDir, relativePath))).isFile();\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return false;\n }\n throw error;\n }\n}\n","import { readFile, readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport type { DoctorCheckContext, DoctorFinding } from \"../doctor-check.js\";\n\nconst adrFilePattern = /^ADR-(\\d{4,})-[a-z0-9]+(?:-[a-z0-9]+)*\\.md$/iu;\nconst adrReferencePattern = /ADR-\\d{4,}/giu;\n\n/**\n * Deterministic, local, read-only superseded-reference check.\n *\n * When a decision changes, `recall adr supersede` marks the old ADR \"Accepted — superseded by …\" and\n * records a new accepted ADR. This check flags feature or module memory that still cites the\n * superseded ADR as authority, so the reasoning trail gets updated instead of silently going stale.\n * It only fires when a superseded ADR exists and is still referenced — a repository with none stays\n * green. Semantic agreement between docs is left to the agent; this only follows the explicit\n * supersede trail.\n */\nexport async function checkSuperseded(context: DoctorCheckContext): Promise<DoctorFinding[]> {\n if (context.config === undefined) {\n return [];\n }\n\n const supersededIds = await loadSupersededAdrIds(context.rootDir, context.config.adrDir);\n if (supersededIds.size === 0) {\n return [];\n }\n\n const findings: DoctorFinding[] = [];\n findings.push(\n ...(await checkReferences(context.rootDir, context.config.featuresDir, supersededIds)),\n );\n findings.push(\n ...(await checkReferences(context.rootDir, context.config.modulesDir, supersededIds)),\n );\n\n return findings;\n}\n\nasync function loadSupersededAdrIds(rootDir: string, adrDir: string): Promise<Set<string>> {\n const superseded = new Set<string>();\n const files = await readMarkdownFiles(rootDir, adrDir);\n\n for (const file of files) {\n const match = adrFilePattern.exec(path.basename(file));\n if (match === null) {\n continue;\n }\n\n const content = await readFile(path.join(rootDir, file), \"utf8\");\n if (statusContains(content, /superseded\\s+by/iu)) {\n superseded.add(`ADR-${match[1]}`.toUpperCase());\n }\n }\n\n return superseded;\n}\n\nasync function checkReferences(\n rootDir: string,\n referenceDir: string,\n supersededIds: Set<string>,\n): Promise<DoctorFinding[]> {\n const findings: DoctorFinding[] = [];\n const files = await readMarkdownFiles(rootDir, referenceDir);\n\n for (const file of files) {\n const content = await readFile(path.join(rootDir, file), \"utf8\");\n const referenced = new Set<string>();\n\n // Ignore ADR identifiers inside fenced code blocks and inline code (illustrative examples).\n for (const match of stripCode(content).matchAll(adrReferencePattern)) {\n referenced.add(match[0].toUpperCase());\n }\n\n for (const id of referenced) {\n if (supersededIds.has(id)) {\n findings.push({\n severity: \"warning\",\n check: \"superseded-reference\",\n message: `Repository memory references ${id}, which has been superseded — update it to the current decision.`,\n path: file,\n });\n }\n }\n }\n\n return findings;\n}\n\nfunction statusContains(content: string, pattern: RegExp): boolean {\n const lines = content.split(/\\r?\\n/u);\n const startIndex = lines.findIndex((line) => line.trim().toLowerCase() === \"## status\");\n if (startIndex === -1) {\n return false;\n }\n\n const body: string[] = [];\n for (let index = startIndex + 1; index < lines.length; index += 1) {\n if (/^##\\s+/u.test(lines[index])) {\n break;\n }\n body.push(lines[index]);\n }\n\n return pattern.test(body.join(\"\\n\"));\n}\n\nfunction stripCode(content: string): string {\n return content\n .replace(/```[\\s\\S]*?```/gu, \" \")\n .replace(/~~~[\\s\\S]*?~~~/gu, \" \")\n .replace(/`[^`]*`/gu, \" \");\n}\n\nasync function readMarkdownFiles(rootDir: string, relativeDir: string): Promise<string[]> {\n const entries = await readDirIfExists(rootDir, relativeDir);\n const files: string[] = [];\n\n for (const entry of entries) {\n const childRelative = path.posix.join(relativeDir, entry.name);\n\n if (entry.isDirectory()) {\n files.push(...(await readMarkdownFiles(rootDir, childRelative)));\n continue;\n }\n\n if (entry.isFile() && entry.name.toLowerCase().endsWith(\".md\")) {\n files.push(childRelative);\n }\n }\n\n return files;\n}\n\nasync function readDirIfExists(rootDir: string, relativePath: string) {\n try {\n return await readdir(path.join(rootDir, relativePath), { withFileTypes: true });\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return [];\n }\n throw error;\n }\n}\n","import { checkCodeReferences } from \"./checks/code-reference-check.js\";\nimport { checkConfig } from \"./checks/config-check.js\";\nimport { checkContent } from \"./checks/content-check.js\";\nimport { checkDrift } from \"./checks/drift-check.js\";\nimport { checkMemoryIntegrity } from \"./checks/memory-integrity-check.js\";\nimport { checkRequiredFiles } from \"./checks/required-files-check.js\";\nimport { checkStandards } from \"./checks/standards-check.js\";\nimport { checkSuperseded } from \"./checks/superseded-check.js\";\n\nexport type DoctorSeverity = \"error\" | \"warning\" | \"info\";\n\nexport type DoctorFinding = {\n severity: DoctorSeverity;\n check: string;\n message: string;\n path?: string;\n};\n\nexport type DoctorReport = {\n findings: DoctorFinding[];\n summary: {\n errors: number;\n warnings: number;\n info: number;\n };\n};\n\nexport type DoctorCheckContext = {\n rootDir: string;\n config?: {\n docsDir: string;\n featuresDir: string;\n modulesDir: string;\n adrDir: string;\n };\n};\n\nexport type DoctorCheck = (\n context: DoctorCheckContext,\n) => Promise<DoctorFinding[]> | DoctorFinding[];\n\nexport async function runDoctor(rootDir: string): Promise<DoctorReport> {\n const findings: DoctorFinding[] = [];\n const configResult = await checkConfig(rootDir);\n\n findings.push(...configResult.findings);\n\n const context: DoctorCheckContext = {\n rootDir,\n config: configResult.config,\n };\n\n findings.push(...(await checkRequiredFiles(context)));\n\n if (configResult.config !== undefined) {\n findings.push(...(await checkMemoryIntegrity(context)));\n findings.push(...(await checkStandards(context)));\n findings.push(...(await checkDrift(context)));\n findings.push(...(await checkContent(context)));\n findings.push(...(await checkCodeReferences(context)));\n findings.push(...(await checkSuperseded(context)));\n }\n\n return createDoctorReport(findings);\n}\n\nexport function createDoctorReport(findings: DoctorFinding[]): DoctorReport {\n return {\n findings,\n summary: {\n errors: findings.filter((finding) => finding.severity === \"error\").length,\n warnings: findings.filter((finding) => finding.severity === \"warning\").length,\n info: findings.filter((finding) => finding.severity === \"info\").length,\n },\n };\n}\n","import type { DoctorFinding, DoctorReport } from \"./doctor-check.js\";\n\nconst severityOrder = [\"error\", \"warning\", \"info\"] as const;\n\nexport function getDoctorExitCode(report: DoctorReport): 0 | 1 | 2 {\n if (report.summary.errors > 0) {\n return 2;\n }\n\n if (report.summary.warnings > 0) {\n return 1;\n }\n\n return 0;\n}\n\nexport function formatDoctorReport(report: DoctorReport): string {\n const lines = [\"Doctor Report\", \"\"];\n\n for (const severity of severityOrder) {\n const findings = report.findings.filter((finding) => finding.severity === severity);\n\n if (findings.length === 0) {\n continue;\n }\n\n lines.push(severity.toUpperCase());\n for (const finding of findings) {\n lines.push(`- ${formatFinding(finding)}`);\n }\n lines.push(\"\");\n }\n\n if (report.findings.length === 0) {\n lines.push(\"INFO\");\n lines.push(\"- No findings.\");\n lines.push(\"\");\n }\n\n lines.push(`Result: ${formatResult(report)}`);\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction formatFinding(finding: DoctorFinding): string {\n if (finding.path === undefined) {\n return finding.message;\n }\n\n return `${finding.message} (${finding.path})`;\n}\n\nfunction formatResult(report: DoctorReport): string {\n if (report.summary.errors > 0) {\n return \"FAILED\";\n }\n\n if (report.summary.warnings > 0) {\n return \"WARNINGS\";\n }\n\n return \"PASSED\";\n}\n","import { runDoctor, type DoctorReport } from \"../core/doctor/doctor-check.js\";\nimport { formatDoctorReport, getDoctorExitCode } from \"../core/doctor/doctor-report.js\";\n\nexport type DoctorOptions = {\n rootDir: string;\n};\n\nexport type DoctorResult = {\n report: DoctorReport;\n exitCode: 0 | 1 | 2;\n};\n\nexport async function doctorProject(options: DoctorOptions): Promise<DoctorResult> {\n const report = await runDoctor(options.rootDir);\n\n return {\n report,\n exitCode: getDoctorExitCode(report),\n };\n}\n\nexport function formatDoctorResult(result: DoctorResult): string {\n return formatDoctorReport(result.report);\n}\n","import { existsSync } from \"node:fs\";\nimport path from \"node:path\";\n\nimport { createDefaultConfig } from \"../core/config/default-config.js\";\nimport { CONFIG_PATH } from \"../core/config/load-config.js\";\nimport {\n createWritePlan,\n type WritePlan,\n type WriteFileInput,\n} from \"../core/filesystem/write-plan.js\";\nimport { executeWritePlan, type WriteResult } from \"../core/filesystem/write-file-safe.js\";\nimport { inspectRepo, summarizeSignals, type RepoSignals } from \"../core/adopt/inspect-repo.js\";\nimport { generateInitFiles } from \"../core/generator/generate-init.js\";\nimport { detectPreCommitGates } from \"../core/hooks/detect-gates.js\";\nimport {\n CLAUDE_SETTINGS_PATH,\n HOOKS_PATH_ACTIVATION_COMMAND,\n PRE_COMMIT_HOOK_PATH,\n SESSION_START_HOOK_PATH,\n renderClaudeSettings,\n renderPreCommitHook,\n renderSessionStartHook,\n} from \"../core/hooks/generate-hook.js\";\nimport { getPreset } from \"../core/presets/preset-registry.js\";\nimport type { Preset } from \"../core/presets/preset-schema.js\";\nimport { generateSkillFiles } from \"../core/skills/generate-skill.js\";\nimport { listCatalogSkillNames } from \"../core/skills/skill-catalog.js\";\nimport { appendNextSteps, appendWriteSummary } from \"./write-summary.js\";\n\nexport type InitOptions = {\n rootDir: string;\n preset?: string;\n dryRun?: boolean;\n force?: boolean;\n reinit?: boolean;\n};\n\nexport type InitResult = {\n preset: string | null;\n dryRun: boolean;\n plan: WritePlan;\n writeResult: WriteResult;\n detected: RepoSignals;\n};\n\nexport type InitErrorCode = \"UNKNOWN_PRESET\" | \"WRITE_PLAN_ERROR\" | \"EXISTING_INSTALLATION\";\n\nexport class InitError extends Error {\n readonly code: InitErrorCode;\n readonly details: string[];\n\n constructor(code: InitErrorCode, message: string, details: string[] = []) {\n super(message);\n this.name = \"InitError\";\n this.code = code;\n this.details = details;\n }\n}\n\nexport async function initProject(options: InitOptions): Promise<InitResult> {\n if (\n options.force === true &&\n options.reinit !== true &&\n existsSync(path.join(options.rootDir, CONFIG_PATH))\n ) {\n throw new InitError(\n \"EXISTING_INSTALLATION\",\n \"Refusing to re-initialize an existing Recall OS installation.\",\n [\n \"An existing .recall/config.json was found in this directory.\",\n \"Running init --force here would overwrite existing repository memory.\",\n \"Pass --reinit together with --force to overwrite an existing installation.\",\n ],\n );\n }\n\n const preset = resolvePreset(options.preset);\n // Read-only inspection of the existing repository so init can surface the detected stack (proposed,\n // never accepted) — run before writes so it reflects the user's repo, not our generated scaffold.\n const detected = await inspectRepo(options.rootDir);\n const preCommitGates = await detectPreCommitGates(options.rootDir);\n const config = createDefaultConfig({ preset: preset?.id ?? null, preCommitGates });\n const files = createInitWriteFiles(options.rootDir, config, preset);\n const plan = createWritePlan({\n rootDir: options.rootDir,\n files,\n force: options.force,\n });\n\n if (plan.hasErrors) {\n throw new InitError(\n \"WRITE_PLAN_ERROR\",\n \"Recall OS init write plan contains errors.\",\n plan.entries\n .filter((entry) => entry.action === \"error\")\n .map((entry) => `${entry.path}: ${entry.reason}`),\n );\n }\n\n const writeResult = await executeWritePlan(plan, { dryRun: options.dryRun });\n\n return {\n preset: preset?.id ?? null,\n dryRun: options.dryRun ?? false,\n plan,\n writeResult,\n detected,\n };\n}\n\nexport function formatInitResult(result: InitResult): string {\n const lines = [\n result.dryRun ? \"Recall OS init dry run complete.\" : \"Recall OS init complete.\",\n `Preset: ${result.preset ?? \"none\"}`,\n ];\n\n if (!result.dryRun) {\n lines.push(\n `Generated repository memory, ${listCatalogSkillNames().length} agent skills, a pre-commit hook, a CI workflow, a Claude SessionStart hook, and a Cursor rule that load memory automatically.`,\n );\n }\n\n appendWriteSummary(lines, {\n dryRun: result.dryRun,\n writeResult: result.writeResult,\n });\n\n appendDetectedStack(lines, result.detected);\n\n const hookWritten =\n result.writeResult.created.includes(PRE_COMMIT_HOOK_PATH) ||\n result.writeResult.overwritten.includes(PRE_COMMIT_HOOK_PATH);\n\n if (hookWritten) {\n lines.push(\"\");\n lines.push(\n result.dryRun\n ? \"Pre-commit hook will be written to .recall/hooks/pre-commit.\"\n : \"Pre-commit hook written to .recall/hooks/pre-commit.\",\n );\n lines.push(`Enable it once per clone: ${HOOKS_PATH_ACTIVATION_COMMAND}`);\n }\n\n if (!result.dryRun) {\n appendNextSteps(lines, [\n \"Read CLAUDE.md and AGENTS.md, then the docs/ memory they point to.\",\n \"AI agent skills are in .claude/skills/ and .agents/skills/ — restart your AI tool to load them.\",\n \"Memory loads automatically per tool: a Claude SessionStart hook (.claude/hooks/session-start.sh), a Cursor rule (.cursor/rules/recall-memory.mdc), and AGENTS.md for Codex.\",\n \"CI is wired in .github/workflows/recall.yml; the pre-commit hook is in .recall/hooks/.\",\n \"Plan your first feature: `recall feature create <name>`.\",\n \"Record a decision: `recall adr create <title>`, then accept it with `recall adr accept`.\",\n \"Check repository memory health anytime: `recall doctor`.\",\n ]);\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction appendDetectedStack(lines: string[], detected: RepoSignals): void {\n const hasSignal =\n detected.languages.length > 0 ||\n detected.frameworks.length > 0 ||\n detected.packageManager !== null ||\n detected.testsEvidence !== null;\n\n if (!hasSignal) {\n return;\n }\n\n // Stack-relevant lines only; README/docs presence is noise right after init writes docs/.\n const stack = summarizeSignals(detected).filter(\n (line) => !line.startsWith(\"- README\") && !line.startsWith(\"- Docs\"),\n );\n\n lines.push(\"\");\n lines.push(\"Detected in this repository (proposed — review, nothing was accepted):\");\n lines.push(...stack);\n lines.push(\n \"If any signal is wrong, correct the source file noted. Run `recall adopt` to record this as proposed memory.\",\n );\n}\n\nfunction resolvePreset(presetId: string | undefined): Preset | null {\n if (presetId === undefined) {\n return null;\n }\n\n const preset = getPreset(presetId);\n\n if (preset === undefined) {\n throw new InitError(\"UNKNOWN_PRESET\", `Unknown preset \"${presetId}\".`);\n }\n\n return preset;\n}\n\nfunction createInitWriteFiles(\n rootDir: string,\n config: ReturnType<typeof createDefaultConfig>,\n preset: Preset | null,\n): WriteFileInput[] {\n return [\n {\n path: CONFIG_PATH,\n content: `${JSON.stringify(config, null, 2)}\\n`,\n },\n ...generateInitFiles({ rootDir, preset }),\n {\n path: PRE_COMMIT_HOOK_PATH,\n content: renderPreCommitHook(config.preCommitGates),\n executable: true,\n },\n // A Claude Code SessionStart hook that injects a memory map every session, so a fresh agent\n // reliably loads durable memory, plus the settings that wire it (skipped if settings exist).\n {\n path: SESSION_START_HOOK_PATH,\n content: renderSessionStartHook(),\n executable: true,\n },\n {\n path: CLAUDE_SETTINGS_PATH,\n content: renderClaudeSettings(),\n },\n // Generate the agent skill set so a fresh repo has the workflows that guide AI agents,\n // not just the docs. Written to both the Claude and portable Agent Skills targets.\n ...listCatalogSkillNames().flatMap((name) => generateSkillFiles(name).files),\n ];\n}\n","import path from \"node:path\";\n\nimport { ensureRequiredAdrSections } from \"../adr/adr-sections.js\";\nimport type { WriteFileInput } from \"../filesystem/write-plan.js\";\nimport type { Preset } from \"../presets/preset-schema.js\";\nimport { createTemplateContext } from \"./template-context.js\";\nimport { renderTemplate } from \"./render-template.js\";\n\nexport type GenerateInitFilesOptions = {\n rootDir: string;\n preset?: Preset | null;\n};\n\ntype InitTemplate = {\n path: string;\n content: string;\n};\n\nconst neutralTemplates: InitTemplate[] = [\n {\n path: \"AGENTS.md\",\n content: `# {{repositoryName}} Agent Instructions\n\nThis repository uses Recall OS repository memory.\n\nStart with durable source-of-truth docs under \\`docs/\\`.\n\nRequired reading:\n\n- \\`docs/00-product/PRD.md\\`\n- \\`docs/10-architecture/ARCHITECTURE.md\\`\n- \\`docs/20-security/SECURITY_MODEL.md\\`\n- \\`docs/50-quality/QUALITY_GATES.md\\`\n- \\`docs/60-engineering/ENGINEERING_STANDARDS.md\\`\n\nRepository rules override model preferences. If instructions conflict, stop and report the conflict.\n\n## Changing an accepted decision\n\nBefore changing anything an accepted ADR governs (framework, database, auth, API shape, and similar):\n\n1. Check \\`docs/adrs/\\` for an accepted ADR that covers it.\n2. If your change contradicts one, stop and confirm with a human first — do not silently change the\n code and leave the ADR saying the opposite.\n3. Record the change as a new decision with \\`recall adr supersede <old> <new-title>\\`. That supersedes\n the old ADR instead of overwriting history, so the reasoning stays auditable.\n\nRepository memory is only trustworthy if decisions change through this trail, not silently.\n`,\n },\n {\n path: \"CLAUDE.md\",\n content: `# {{repositoryName}} Claude Instructions\n\nThis file is loaded automatically every Claude session. The durable project memory lives in \\`docs/\\`;\ndo not rely on chat history as source of truth, and repository rules override model preference.\n\n@AGENTS.md\n\nRead the docs that \\`AGENTS.md\\` routes to before changing code or repository memory. A SessionStart\nhook (\\`.claude/hooks/session-start.sh\\`) also injects a memory map at the start of each session.\n`,\n },\n {\n // Cursor auto-applies rules under .cursor/rules. alwaysApply makes this the portable equivalent\n // of the Claude Code SessionStart hook: Cursor injects it into every request so the agent loads\n // repository memory even though it cannot run the Claude-specific hook.\n path: \".cursor/rules/recall-memory.mdc\",\n content: `---\ndescription: {{repositoryName}} repository memory and rules (Recall OS). Read before non-trivial work.\nglobs:\nalwaysApply: true\n---\n\n# {{repositoryName}} repository memory\n\nThis repository uses Recall OS. Durable memory lives in \\`docs/\\` and is the source of truth over chat\nhistory. Do not treat chat history as truth, and repository rules override model preference.\n\nBefore non-trivial work:\n\n- Read \\`AGENTS.md\\` and the docs it routes to.\n- Accepted decisions live in \\`docs/adrs/\\`; module memory lives in \\`docs/30-modules/\\`.\n- If an instruction conflicts with accepted repository memory, stop and report the conflict.\n- Before changing what an accepted ADR governs, confirm with a human and record it with\n \\`recall adr supersede <old> <new-title>\\` — never silently contradict an accepted decision.\n\nSource-of-truth order: accepted ADRs and repository decisions, then architecture docs, engineering\nstandards, the current PRD, security and testing docs, module docs, feature plans, then chat history.\n\nBefore claiming work is complete, run \\`recall doctor\\` and fix reported errors.\n`,\n },\n {\n path: \"docs/00-product/PRD.md\",\n content: `# PRD: {{repositoryName}}\n\n## Purpose\n\nDescribe what this repository is building and why.\n\n## Current Status\n\nDraft.\n\n## Notes\n\nKeep product intent durable here. Do not rely on chat history as source of truth.\n`,\n },\n {\n path: \"docs/00-product/BRD.md\",\n content: `# BRD: {{repositoryName}}\n\n## Purpose\n\nDescribe the business goal, target users, and success criteria for this repository.\n\n## Current Status\n\nDraft.\n`,\n },\n {\n path: \"docs/10-architecture/ARCHITECTURE.md\",\n content: `# Architecture\n\n## Purpose\n\nDescribe the accepted architecture for this repository.\n\n## Current Status\n\nNo architecture decisions are accepted yet.\n\nUse ADRs to accept architecture choices.\n`,\n },\n {\n path: \"docs/10-architecture/MEMORY_ENGINE.md\",\n content: `# Repository Memory\n\nRepository memory is the durable source of truth for humans and AI agents.\n\nSource-of-truth order:\n\n1. Accepted ADRs and repository decisions\n2. Architecture docs\n3. Engineering standards\n4. Current PRD and accepted change requests\n5. Security and testing docs\n6. Module docs\n7. Feature plans\n8. Task files\n9. External context\n10. Chat history\n`,\n },\n {\n path: \"docs/10-architecture/FILE_WRITE_POLICY.md\",\n content: `# File Write Policy\n\nDefault behavior:\n\n- Skip existing files.\n- Use dry run before risky writes.\n- Require explicit force to overwrite.\n- Never write outside the repository root.\n`,\n },\n {\n path: \"docs/20-security/SECURITY_MODEL.md\",\n content: `# Security Model\n\n## Status\n\nDraft — fill the prompted sections below with this repository's real model as it grows. \\`recall doctor\\`\nflags these as warnings once the repository has real work (a feature, module, or accepted decision).\n\n## Baseline Rules\n\n- Never commit secrets or credentials, and never read or copy \\`.env\\` files into docs.\n- Validate and authorize untrusted input at every trust boundary.\n- Do not add network, telemetry, cloud, MCP runtime, or AI API behavior without explicit review.\n\n## Authentication And Authorization\n\nDescribe how this repository authenticates users or clients and how it authorizes actions, including\nwhere those checks live.\n\n## Secrets And Configuration\n\nDescribe where secrets live, how they are injected, and how configuration is kept out of version\ncontrol.\n\n## Sensitive Data\n\nDescribe the sensitive or personal data this repository handles, and how it is protected at rest and\nin transit.\n\n## Dependencies And Supply Chain\n\nDescribe how third-party dependencies are vetted, pinned, and updated.\n`,\n },\n {\n path: \"docs/20-security/THREAT_MODEL.md\",\n content: `# Threat Model\n\n## Status\n\nDraft — replace the prompts below with this repository's real analysis as it grows. \\`recall doctor\\`\nflags these as warnings once the repository has real work (a feature, module, or accepted decision).\n\n## Assets\n\nDescribe what this repository must protect: user data, credentials, money, availability, or\nreputation.\n\n## Entry Points\n\nDescribe where untrusted input enters: HTTP endpoints, webhooks, file uploads, queues, CLI input, or\nthird-party callbacks.\n\n## Trust Boundaries\n\nDescribe where trust changes: client to server, service to database, your code to third-party APIs.\n\n## Threats\n\nDescribe the concrete threats that apply to this repository, by category:\n\n- Spoofing — how identities are faked or sessions stolen.\n- Tampering — how requests, data, or builds are altered (injection, mass assignment).\n- Repudiation — actions that must remain auditable.\n- Information disclosure — how sensitive data or secrets could leak.\n- Denial of service — how the system can be overwhelmed or abused.\n- Elevation of privilege — how a user could gain access they should not have.\n\n## Mitigations\n\nDescribe the control in place or planned for each threat above.\n\n## Open Risks\n\nDescribe accepted or unresolved risks and who owns them.\n`,\n },\n {\n path: \"docs/50-quality/TESTING_STRATEGY.md\",\n content: `# Testing Strategy\n\nTests should derive from acceptance criteria, risk, security invariants, and module boundaries.\n\nDocument required unit, integration, security, and golden tests as the repository grows.\n`,\n },\n {\n path: \"docs/50-quality/QUALITY_GATES.md\",\n content: `# Quality Gates\n\nDo not claim completion without evidence.\n\nCompletion evidence should include:\n\n- Files changed.\n- Tests run.\n- Results.\n- Skipped checks.\n- Remaining risks.\n`,\n },\n {\n path: \"docs/60-engineering/ENGINEERING_STANDARDS.md\",\n content: `# Engineering Standards\n\nRepository rules override model preferences.\n\nBaseline rules:\n\n- Never commit secrets.\n- Keep changes scoped.\n- Update docs when behavior or architecture changes.\n- Add tests or document why tests were skipped.\n- Do not claim completion without evidence.\n`,\n },\n {\n path: \"docs/60-engineering/AI_AGENT_RULES.md\",\n content: `# AI Agent Rules\n\nAI agents must follow repository memory over model preference.\n\nIf a request conflicts with accepted repository memory or engineering standards, stop and report the conflict.\n\n## Changing an accepted decision\n\nWhen work would change something an accepted ADR governs:\n\n1. Find the accepted ADR in \\`docs/adrs/\\` that covers it.\n2. If the change contradicts it, stop and confirm with a human before changing the code.\n3. Record the new decision with \\`recall adr supersede <old> <new-title>\\` so the old ADR is marked\n superseded and the reasoning is preserved, instead of silently editing or contradicting it.\n`,\n },\n {\n path: \"docs/ai/AI_AGENTS_SKILLS_MCP_STRATEGY.md\",\n content: `# AI Agents, Skills, And MCP Strategy\n\nRoot agent files are entry points, not guarantees.\n\nDurable memory lives in \\`docs/\\`.\n\nMCP is optional external context and does not override accepted repository memory.\n`,\n },\n {\n path: \"docs/ai/MCP_STRATEGY.md\",\n content: `# MCP Strategy\n\nMCP is not required for this repository.\n\nIf MCP is introduced later, document trusted servers, data accessed, permissions, risks, and source-of-truth rules.\n`,\n },\n {\n path: \"docs/ai/RECALL_COMMANDS.md\",\n content: `# Recall OS Commands\n\nThis document records the Recall OS commands available to humans and AI agents.\n\n## Completion Gate\n\nBefore claiming implementation work is complete, run:\n\n\\`\\`\\`txt\npnpm test:run\npnpm typecheck\nrecall doctor\n\\`\\`\\`\n\nIf \\`recall doctor\\` reports errors, fix them or report why they cannot be fixed. If it reports\nwarnings, address them or record why they are acceptable.\n\nPackage binary behavior is covered by binary integration tests.\n\n## Commands\n\n### \\`recall init\\`\n\nInitialize neutral repository memory.\n\nOptions:\n\n- \\`--preset <id>\\`: apply optional preset guidance and proposed decisions.\n- \\`--dry-run\\`: show planned writes without writing files.\n- \\`--force\\`: overwrite existing files explicitly.\n- \\`--reinit\\`: required with \\`--force\\` to overwrite an existing Recall OS installation\n (a directory that already has \\`.recall/config.json\\`). Without it, \\`--force\\` refuses, protecting\n existing repository memory.\n\nInit also generates a tracked pre-commit hook at \\`.recall/hooks/pre-commit\\` that runs \\`recall doctor\\`\nplus any \\`preCommitGates\\` in \\`.recall/config.json\\`. Init proposes, but does not run, the activation\ncommand \\`git config core.hooksPath .recall/hooks\\`.\n\n### \\`recall adopt\\`\n\nInspect an existing repository through read-only manifest and marker files, then write a proposed\nadoption report and proposed framework ADRs for human review. Adopt never executes repository code\nand never produces accepted memory.\n\nOptions:\n\n- \\`--dry-run\\`: show planned writes without writing files.\n- \\`--force\\`: overwrite existing files explicitly.\n\n### \\`recall skill create <name>\\`\n\nGenerate a portable AI agent skill as \\`SKILL.md\\` for both Claude Code (\\`.claude/skills/\\`) and the\nportable Agent Skills target (\\`.agents/skills/\\`). Known names use the built-in catalog; unknown names\nproduce a valid skeleton. Generated skills contain no scripts.\n\nOptions:\n\n- \\`--dry-run\\`: show planned writes without writing files.\n- \\`--force\\`: overwrite existing files explicitly.\n\n### \\`recall skill list\\`\n\nList the built-in catalog skills.\n\n### \\`recall mcp add <server>\\`\n\nGenerate offline, proposed memory for an MCP server (for example \\`figma\\`) as \\`docs/ai/mcp/<server>.md\\`\nplus a proposed adoption ADR. Recall OS never connects to the MCP server or makes network calls; the\nagent records durable MCP-derived context into the generated memory for human review. It also\ninstalls a \\`capture-mcp-context\\` agent skill that prompts the agent to record that context.\n\nOptions:\n\n- \\`--dry-run\\`: show planned writes without writing files.\n- \\`--force\\`: overwrite existing files explicitly.\n\n### \\`recall preset list\\`\n\nList built-in presets.\n\n### \\`recall feature create <name>\\`\n\nCreate feature memory docs under the configured features directory.\n\nOptions:\n\n- \\`--dry-run\\`: show planned writes without writing files.\n- \\`--force\\`: overwrite existing files explicitly.\n\n### \\`recall adr create <title>\\`\n\nCreate a proposed ADR under the configured ADR directory.\n\nOptions:\n\n- \\`--dry-run\\`: show planned writes without writing files.\n- \\`--force\\`: overwrite existing files explicitly.\n\n### \\`recall adr accept <name>\\`\n\nPromote a proposed ADR to accepted repository memory. A proposal under\n\\`docs/adrs/proposed/ADR-PROPOSED-<slug>.md\\` becomes a numbered, accepted \\`ADR-####-<slug>.md\\` and the\nproposal is removed; an existing numbered Proposed ADR is accepted in place.\n\nOptions:\n\n- \\`--dry-run\\`: show planned writes without writing files.\n- \\`--force\\`: overwrite existing files explicitly.\n\n### \\`recall adr supersede <old> <new-title>\\`\n\nRecord a changed decision. Marks an accepted ADR as \\`Accepted — superseded by ADR-####\\` and creates a\nnew accepted ADR that declares what it supersedes, so the reasoning trail stays auditable instead of\nbeing overwritten. Doctor then warns about any memory still referencing the superseded decision.\n\nOptions:\n\n- \\`--dry-run\\`: show planned writes without writing files.\n- \\`--force\\`: overwrite existing files explicitly.\n\n### \\`recall module create <name>\\`\n\nCreate module memory docs under the configured modules directory.\n\nOptions:\n\n- \\`--dry-run\\`: show planned writes without writing files.\n- \\`--force\\`: overwrite existing files explicitly.\n\n### \\`recall doctor\\`\n\nCheck whether repository memory is structurally healthy enough for AI-assisted work, whether basic\nengineering evidence is present, and whether memory references decisions that exist and are accepted.\n\nDoctor also runs deterministic drift checks: feature or module memory that references a missing ADR\nis an error, memory that references a not-yet-accepted ADR is a warning, and memory that still\nreferences a superseded decision is a warning.\n\nExit codes:\n\n- \\`0\\`: healthy\n- \\`1\\`: warnings only\n- \\`2\\`: errors\n`,\n },\n {\n path: \"docs/30-modules/README.md\",\n content: `# Module Memory\n\nModule memory records what each important module owns, how it should be tested, and which decisions affect it.\n\nFuture module folders should use:\n\n\\`\\`\\`txt\ndocs/30-modules/<module>/\n MODULE.md\n TASKS.md\n TEST_PLAN.md\n DECISIONS.md\n\\`\\`\\`\n\nAgents should update module memory when implementation changes responsibilities, boundaries, tests, risks, or decisions.\n`,\n },\n {\n path: \"docs/40-features/README.md\",\n content: `# Feature Memory\n\nFeature memory records requirements, acceptance criteria, plans, tests, reviews, and completion evidence.\n\nFuture feature folders should use:\n\n\\`\\`\\`txt\ndocs/40-features/F-###-<feature>/\n PRD.md\n ACCEPTANCE.md\n ARCHITECTURE_IMPACT.md\n CHANGE_REQUESTS.md\n PLAN.md\n TASKS.md\n TEST_PLAN.md\n REVIEW.md\n COMPLETION_REPORT.md\n\\`\\`\\`\n\nAgents should not implement meaningful feature work without a feature plan or clear source-of-truth reference.\n`,\n },\n {\n path: \"docs/adrs/README.md\",\n content: `# Architecture Decision Records\n\nAccepted ADRs live in this directory as \\`ADR-####-<slug>.md\\` with \\`## Status\\` set to \\`Accepted\\`.\nProposed ADRs live under \\`docs/adrs/proposed/\\`.\n\nThere is no \\`accepted/\\` subdirectory: accepted ADRs sit at the top level of \\`docs/adrs/\\`.\n\nPresets and AI agents may propose decisions; humans accept them with \\`recall adr accept <name>\\`,\nwhich promotes a proposal into an accepted ADR here.\n`,\n },\n {\n path: \".github/workflows/recall.yml\",\n content: `name: Recall OS\n\non:\n push:\n pull_request:\n\njobs:\n doctor:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n - uses: actions/setup-node@v4\n with:\n node-version: 20\n - name: Validate repository memory\n run: npx --yes recall-os@latest doctor\n`,\n },\n];\n\nexport function generateInitFiles(options: GenerateInitFilesOptions): WriteFileInput[] {\n const repositoryName = path.basename(path.resolve(options.rootDir)) || \"repository\";\n const context = createTemplateContext({ repositoryName });\n const files = neutralTemplates.map((template) => ({\n path: template.path,\n content: renderTemplate(template.content, context),\n }));\n\n if (options.preset !== undefined && options.preset !== null) {\n files.push(...generatePresetFiles(options.preset));\n }\n\n return files;\n}\n\nfunction generatePresetFiles(preset: Preset): WriteFileInput[] {\n return [\n ...preset.templates.map((template) => ({\n path: template.destination,\n content: template.content,\n })),\n ...preset.proposedDecisions.map((decision) => ({\n path: decision.destination,\n // Normalize every preset's proposed ADR so it stays Doctor-healthy once accepted.\n content: ensureRequiredAdrSections(decision.body),\n })),\n ];\n}\n","import { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\n/**\n * Scripts that are reasonable to run as pre-commit gates when a target repository defines them.\n * Detection only proposes these as editable config values; it never encodes them as core truth.\n */\nconst KNOWN_SCRIPTS = [\"test\", \"typecheck\", \"lint\"] as const;\n\n/**\n * Neutrally detect proposed pre-commit gates for a target repository.\n *\n * Reads `package.json` scripts and the lockfile to suggest `<pm> run <script>` commands. Returns an\n * empty list when no JavaScript toolchain is detected. The result is a proposal the user reviews in\n * `.recall/config.json`; it is not an accepted decision.\n */\nexport async function detectPreCommitGates(rootDir: string): Promise<string[]> {\n const packageJsonPath = path.join(rootDir, \"package.json\");\n\n if (!existsSync(packageJsonPath)) {\n return [];\n }\n\n let scripts: Record<string, unknown>;\n try {\n const raw = await readFile(packageJsonPath, \"utf8\");\n const parsed = JSON.parse(raw) as { scripts?: Record<string, unknown> };\n scripts = parsed.scripts ?? {};\n } catch {\n return [];\n }\n\n if (typeof scripts !== \"object\" || scripts === null) {\n return [];\n }\n\n const packageManager = detectPackageManager(rootDir);\n\n return KNOWN_SCRIPTS.filter((script) => typeof scripts[script] === \"string\").map(\n (script) => `${packageManager} run ${script}`,\n );\n}\n\nfunction detectPackageManager(rootDir: string): string {\n if (existsSync(path.join(rootDir, \"pnpm-lock.yaml\"))) {\n return \"pnpm\";\n }\n\n if (existsSync(path.join(rootDir, \"yarn.lock\"))) {\n return \"yarn\";\n }\n\n return \"npm\";\n}\n","export const HOOKS_DIR = \".recall/hooks\";\nexport const PRE_COMMIT_HOOK_PATH = \".recall/hooks/pre-commit\";\nexport const HOOKS_PATH_ACTIVATION_COMMAND = \"git config core.hooksPath .recall/hooks\";\n\nexport const SESSION_START_HOOK_PATH = \".claude/hooks/session-start.sh\";\nexport const CLAUDE_SETTINGS_PATH = \".claude/settings.json\";\n\n/**\n * Render a deterministic POSIX `sh` Claude Code SessionStart hook.\n *\n * Claude Code runs this before the first prompt of every session and injects its stdout\n * `additionalContext` into the model. It lists the repository's accepted ADRs and modules so a fresh\n * agent reliably knows the durable memory exists and where to read it. It is strictly read-only:\n * it only lists files and never modifies anything, makes no network calls, and runs no AI.\n */\nexport function renderSessionStartHook(): string {\n return `#!/bin/sh\n# Recall OS Claude Code SessionStart hook.\n# Generated by \\`recall init\\`. Injects a repository-memory map into every Claude Code session so a\n# fresh agent reliably loads durable memory. Wired in .claude/settings.json. Read-only.\n\nadrs=$(ls docs/adrs/ADR-*.md 2>/dev/null | sed 's|.*/||;s|\\\\.md$||' | tr '\\\\n' ' ')\nmodules=$(ls -d docs/30-modules/*/ 2>/dev/null | sed 's|docs/30-modules/||;s|/$||' | tr '\\\\n' ' ')\n\ncontext=\"Recall OS repository memory is the source of truth over chat history. Before non-trivial work, read AGENTS.md and the docs it routes to; repository rules override model preference. Accepted ADRs (docs/adrs/): \\${adrs:-none yet}. Modules (docs/30-modules/): \\${modules:-none yet}. Run 'recall doctor' before claiming work complete.\"\n\nprintf '{\"hookSpecificOutput\":{\"hookEventName\":\"SessionStart\",\"additionalContext\":\"%s\"}}\\\\n' \"$context\"\n`;\n}\n\n/**\n * Claude Code settings that wire the SessionStart hook. Generated only when no settings file exists,\n * since the safe write policy never overwrites a user's existing settings.\n */\nexport function renderClaudeSettings(): string {\n return `${JSON.stringify(\n {\n hooks: {\n SessionStart: [\n {\n matcher: \"startup\",\n hooks: [{ type: \"command\", command: `./${SESSION_START_HOOK_PATH}` }],\n },\n ],\n },\n },\n null,\n 2,\n )}\\n`;\n}\n\n/**\n * Render a deterministic POSIX `sh` pre-commit hook.\n *\n * The hook runs `recall doctor` first, then each configured gate in order. Gates come from\n * `.recall/config.json` (`preCommitGates`), so the toolchain choice stays in user config rather than\n * in core. The hook does not modify git configuration; activation is a deliberate human step.\n */\nexport function renderPreCommitHook(gates: string[]): string {\n const lines = [\n \"#!/bin/sh\",\n \"# Recall OS pre-commit hook.\",\n \"# Generated by `recall init`. Edit gates in .recall/config.json (preCommitGates),\",\n \"# then re-run `recall init --force` to regenerate this hook.\",\n \"# Enable once per clone with:\",\n `# ${HOOKS_PATH_ACTIVATION_COMMAND}`,\n \"set -e\",\n \"\",\n \"recall doctor\",\n ];\n\n for (const gate of gates) {\n lines.push(gate);\n }\n\n lines.push(\"\");\n\n return lines.join(\"\\n\");\n}\n","import type { Preset } from \"../../core/presets/preset-schema.js\";\n\nexport const flutterPreset: Preset = {\n id: \"flutter\",\n name: \"Flutter\",\n description: \"Minimal Flutter-aware opinion pack guidance with proposed decisions only.\",\n templates: [\n {\n destination: \"docs/ai/presets/flutter-guidance.md\",\n description: \"Flutter guidance that remains non-authoritative until accepted.\",\n content:\n \"# Flutter Preset Guidance\\n\\nTreat Flutter package, state management, navigation, and platform choices as proposed guidance until accepted.\\n\",\n },\n ],\n guidance: [\n {\n title: \"Do not silently choose state management\",\n body: \"Flutter state management, navigation, persistence, and backend choices must remain optional guidance or proposed ADRs.\",\n },\n ],\n proposedDecisions: [\n {\n id: \"flutter-platform\",\n title: \"Use Flutter\",\n status: \"proposed\",\n destination: \"docs/adrs/proposed/ADR-PROPOSED-flutter-platform.md\",\n body: \"# Proposed ADR: Use Flutter\\n\\n## Status\\n\\nProposed\\n\\n## Decision\\n\\nConsider Flutter as the application platform. This is not accepted until a human reviews and accepts it.\\n\",\n },\n ],\n};\n","import type { Preset } from \"../../core/presets/preset-schema.js\";\n\nexport const genericPreset: Preset = {\n id: \"generic\",\n name: \"Generic\",\n description: \"Neutral repository memory with no framework or architecture opinions.\",\n templates: [\n {\n destination: \"docs/ai/presets/generic-guidance.md\",\n description: \"Neutral guidance for repository memory initialization.\",\n content:\n \"# Generic Preset Guidance\\n\\nUse neutral repository memory first. Record architecture choices only after a human accepts them.\\n\",\n },\n ],\n guidance: [\n {\n title: \"Neutral memory first\",\n body: \"Use this preset when the repository should start with memory structure only and no stack-specific recommendations.\",\n },\n ],\n proposedDecisions: [],\n};\n","import type { Preset } from \"../../core/presets/preset-schema.js\";\n\nconst guidance = `# iOS Swift Preset Guidance\n\nThis is proposed guidance, not accepted. Convert any choice you adopt into an accepted ADR in\nrepository memory. Until then, treat everything here as a recommendation awaiting human review.\n\n## Decision forks this stack forces\n\n- UI framework: SwiftUI vs UIKit.\n- Concurrency: Swift async/await with the Observation framework vs Combine.\n- Persistence: SwiftData vs Core Data.\n- Presentation pattern: MVVM vs The Composable Architecture (TCA).\n- Testing: XCTest vs the Swift Testing framework.\n\n## Recommended structure (proposed)\n\n- Feature folders with view, model, and view-model separation.\n- A dependency layer abstracted behind protocols for testability.\n- Swift Package Manager for modular code.\n\n## Testing (proposed)\n\n- Unit tests with XCTest or Swift Testing.\n- View-model tests independent of the UI.\n- Snapshot or UI tests for critical flows.\n\n## Security considerations (proposed)\n\n- Store credentials and tokens in the Keychain, never in source or UserDefaults.\n- Enable App Transport Security and consider certificate pinning.\n- Avoid logging sensitive data.\n`;\n\nfunction proposedAdr(topic: string, title: string, body: string) {\n return {\n id: `ios-swift-${topic}`,\n title,\n status: \"proposed\" as const,\n destination: `docs/adrs/proposed/ADR-PROPOSED-ios-swift-${topic}.md`,\n body,\n };\n}\n\nexport const iosSwiftPreset: Preset = {\n id: \"ios-swift\",\n name: \"iOS Swift\",\n description: \"Opinionated iOS Swift opinion pack with proposed decisions only.\",\n templates: [\n {\n destination: \"docs/ai/presets/ios-swift-guidance.md\",\n description: \"iOS Swift guidance that remains proposed until accepted.\",\n content: guidance,\n },\n ],\n guidance: [\n {\n title: \"Separate platform guidance from decisions\",\n body: \"SwiftUI vs UIKit, concurrency, persistence, presentation pattern, and testing choices must be documented as proposed before acceptance.\",\n },\n {\n title: \"Abstract dependencies behind protocols\",\n body: \"Hide platform services behind protocols for testability, but record this as a proposed decision before treating it as accepted.\",\n },\n ],\n proposedDecisions: [\n proposedAdr(\n \"platform\",\n \"Use iOS Swift\",\n `# Proposed ADR: Use iOS Swift\n\n## Status\n\nProposed\n\n## Context\n\nThe team needs a primary platform and language for the iOS application.\n\n## Decision\n\nConsider iOS Swift as the platform direction. This is not accepted until a human reviews and accepts\nit.\n\n## Alternatives Considered\n\n- Objective-C.\n- A cross-platform stack such as Flutter or React Native.\n\n## Consequences\n\n- Native performance and first-class Apple APIs.\n- Requires Swift and Apple toolchain proficiency.\n`,\n ),\n proposedAdr(\n \"ui-swiftui\",\n \"Use SwiftUI for UI\",\n `# Proposed ADR: Use SwiftUI\n\n## Status\n\nProposed\n\n## Context\n\nThe app needs a UI framework. SwiftUI and UIKit are the main options.\n\n## Decision\n\nConsider SwiftUI as the UI framework, awaiting human acceptance.\n\n## Alternatives Considered\n\n- UIKit.\n- A hybrid of SwiftUI and UIKit during migration.\n\n## Consequences\n\n- Declarative UI and less boilerplate.\n- Some advanced cases still require UIKit interop.\n`,\n ),\n proposedAdr(\n \"concurrency-async\",\n \"Use async/await and Observation\",\n `# Proposed ADR: Use async/await and Observation\n\n## Status\n\nProposed\n\n## Context\n\nThe app needs a concurrency and state-observation approach.\n\n## Decision\n\nConsider Swift async/await with the Observation framework, awaiting human acceptance.\n\n## Alternatives Considered\n\n- Combine.\n- Completion handlers and delegates.\n\n## Consequences\n\n- Structured concurrency and simpler state flow.\n- Requires a recent deployment target.\n`,\n ),\n proposedAdr(\n \"persistence-swiftdata\",\n \"Use SwiftData for persistence\",\n `# Proposed ADR: Use SwiftData\n\n## Status\n\nProposed\n\n## Context\n\nThe app needs local persistence.\n\n## Decision\n\nConsider SwiftData for local persistence, awaiting human acceptance.\n\n## Alternatives Considered\n\n- Core Data directly.\n- A lightweight store such as GRDB.\n\n## Consequences\n\n- Swift-native modeling and SwiftUI integration.\n- Requires a recent deployment target and migration care.\n`,\n ),\n proposedAdr(\n \"architecture-mvvm\",\n \"Use MVVM presentation pattern\",\n `# Proposed ADR: Use MVVM\n\n## Status\n\nProposed\n\n## Context\n\nThe app needs a presentation architecture.\n\n## Decision\n\nConsider MVVM with observable view models, awaiting human acceptance.\n\n## Alternatives Considered\n\n- The Composable Architecture (TCA).\n- Plain views with embedded logic.\n\n## Consequences\n\n- Clear separation of UI and state.\n- Teams must agree on view-model conventions.\n`,\n ),\n ],\n};\n","import type { Preset } from \"../../core/presets/preset-schema.js\";\n\nconst guidance = `# Kotlin Android Preset Guidance\n\nThis guidance is proposed, not accepted. Convert any choice you adopt into an accepted ADR in\nrepository memory. Until then, treat everything here as a recommendation awaiting human review.\n\n## Decision forks this stack forces\n\n- UI toolkit: Jetpack Compose vs Android Views/XML.\n- Asynchrony: Kotlin Coroutines and Flow vs RxJava/callbacks.\n- Dependency injection: Hilt vs Koin vs manual.\n- Local persistence: Room vs SQLDelight vs DataStore.\n- Presentation pattern: MVVM vs MVI.\n\n## Recommended structure (proposed)\n\n- Feature-based modules or packages (\\`feature/\\`, \\`core/\\`, \\`data/\\`, \\`ui/\\`).\n- A repository layer between ViewModels and data sources.\n- Immutable UI state exposed as \\`StateFlow\\` from ViewModels.\n\n## Testing (proposed)\n\n- Unit tests with JUnit5 and coroutine test dispatchers.\n- Flow assertions with Turbine.\n- UI tests with Compose UI testing or Espresso.\n\n## Security considerations (proposed)\n\n- Store secrets with the Android Keystore, never in source or version control.\n- Use EncryptedSharedPreferences or DataStore with encryption for sensitive local data.\n- Enforce network security config and certificate pinning where appropriate.\n`;\n\nfunction proposedAdr(topic: string, title: string, body: string) {\n return {\n id: `kotlin-android-${topic}`,\n title,\n status: \"proposed\" as const,\n destination: `docs/adrs/proposed/ADR-PROPOSED-kotlin-android-${topic}.md`,\n body,\n };\n}\n\nexport const kotlinAndroidPreset: Preset = {\n id: \"kotlin-android\",\n name: \"Kotlin Android\",\n description: \"Opinionated Kotlin Android opinion pack with proposed decisions only.\",\n templates: [\n {\n destination: \"docs/ai/presets/kotlin-android-guidance.md\",\n description: \"Kotlin Android guidance that remains proposed until accepted.\",\n content: guidance,\n },\n ],\n guidance: [\n {\n title: \"Keep stack choices proposed\",\n body: \"Compose vs Views, Coroutines/Flow vs RxJava, DI framework, persistence, and presentation pattern must remain proposed until accepted in repository memory.\",\n },\n {\n title: \"Prefer unidirectional state\",\n body: \"Expose immutable UI state from ViewModels and keep side effects explicit, but record this as a proposed decision before treating it as accepted.\",\n },\n ],\n proposedDecisions: [\n proposedAdr(\n \"platform\",\n \"Use Kotlin for Android\",\n `# Proposed ADR: Use Kotlin for Android\n\n## Status\n\nProposed\n\n## Context\n\nThe team needs a primary language and platform for the Android application.\n\n## Decision\n\nConsider Kotlin as the Android application language. This is not accepted until a human reviews and\naccepts it.\n\n## Alternatives Considered\n\n- Java for Android.\n- A cross-platform stack such as Flutter or React Native.\n\n## Consequences\n\n- Idiomatic Android APIs and coroutines support.\n- Requires Kotlin proficiency across the team.\n`,\n ),\n proposedAdr(\n \"ui-compose\",\n \"Use Jetpack Compose for UI\",\n `# Proposed ADR: Use Jetpack Compose\n\n## Status\n\nProposed\n\n## Context\n\nThe app needs a UI toolkit. Compose and the legacy View/XML system are the main options.\n\n## Decision\n\nConsider Jetpack Compose as the UI toolkit, awaiting human acceptance.\n\n## Alternatives Considered\n\n- Android Views with XML layouts.\n- A hybrid of Compose and Views during migration.\n\n## Consequences\n\n- Declarative UI and less boilerplate.\n- Requires Compose tooling and team ramp-up.\n`,\n ),\n proposedAdr(\n \"async-coroutines\",\n \"Use Coroutines and Flow for async\",\n `# Proposed ADR: Use Coroutines and Flow\n\n## Status\n\nProposed\n\n## Context\n\nThe app needs a concurrency and reactive streams approach.\n\n## Decision\n\nConsider Kotlin Coroutines with Flow for asynchronous work and streams, awaiting human acceptance.\n\n## Alternatives Considered\n\n- RxJava/RxKotlin.\n- Callbacks and \\`LiveData\\` only.\n\n## Consequences\n\n- Structured concurrency and cancellation.\n- Requires discipline around dispatchers and scope.\n`,\n ),\n proposedAdr(\n \"di-hilt\",\n \"Use Hilt for dependency injection\",\n `# Proposed ADR: Use Hilt\n\n## Status\n\nProposed\n\n## Context\n\nThe app needs a dependency injection approach for testability and lifecycle scoping.\n\n## Decision\n\nConsider Hilt for dependency injection, awaiting human acceptance.\n\n## Alternatives Considered\n\n- Koin.\n- Manual constructor injection.\n\n## Consequences\n\n- Compile-time validation and Android lifecycle scopes.\n- Adds annotation processing to the build.\n`,\n ),\n proposedAdr(\n \"persistence-room\",\n \"Use Room for local persistence\",\n `# Proposed ADR: Use Room\n\n## Status\n\nProposed\n\n## Context\n\nThe app needs structured local persistence.\n\n## Decision\n\nConsider Room for local relational persistence, awaiting human acceptance.\n\n## Alternatives Considered\n\n- SQLDelight.\n- DataStore for simple key-value needs.\n\n## Consequences\n\n- Compile-time verified SQL and Flow integration.\n- Schema migrations must be maintained.\n`,\n ),\n proposedAdr(\n \"architecture-mvvm\",\n \"Use MVVM presentation pattern\",\n `# Proposed ADR: Use MVVM\n\n## Status\n\nProposed\n\n## Context\n\nThe app needs a presentation architecture for separating UI from logic.\n\n## Decision\n\nConsider MVVM with unidirectional state from ViewModels, awaiting human acceptance.\n\n## Alternatives Considered\n\n- MVI with explicit intents and reducers.\n- Plain ViewModels without a strict pattern.\n\n## Consequences\n\n- Clear separation of UI and state.\n- Teams must agree on state and event conventions.\n`,\n ),\n ],\n};\n","import type { PresetGuidance, PresetProposedDecision } from \"../../core/presets/preset-schema.js\";\n\n/**\n * Shared building blocks for the Laravel opinion packs. Three presets compose these: `laravel-react`\n * and `laravel-vue` (Inertia SPAs) and `laravel-api` (API/SPA backend). Every decision is *proposed*\n * — a human accepts it with `recall adr accept`. Nothing here is accepted truth.\n */\nexport type LaravelVariant = \"react\" | \"vue\" | \"api\";\n\ntype VariantProfile = {\n id: string;\n label: string;\n description: string;\n frontendLine: string;\n deliveryLine: string;\n};\n\nconst VARIANTS: Record<LaravelVariant, VariantProfile> = {\n react: {\n id: \"laravel-react\",\n label: \"React via Inertia\",\n description:\n \"Opinionated Laravel + Inertia + React opinion pack (proposed decisions only). Matches the official Laravel React starter kit.\",\n frontendLine:\n \"Frontend: Inertia 2 + React 19 + TypeScript + Tailwind, built with Vite (the official React starter kit, with shadcn/ui for components).\",\n deliveryLine:\n \"The app is a server-driven SPA: Laravel controllers return Inertia responses with typed props; there is no separate REST client for first-party screens.\",\n },\n vue: {\n id: \"laravel-vue\",\n label: \"Vue via Inertia\",\n description:\n \"Opinionated Laravel + Inertia + Vue opinion pack (proposed decisions only). Matches the official Laravel Vue starter kit.\",\n frontendLine:\n \"Frontend: Inertia 2 + Vue 3 (script setup) + TypeScript + Tailwind, built with Vite (the official Vue starter kit).\",\n deliveryLine:\n \"The app is a server-driven SPA: Laravel controllers return Inertia responses with typed props; there is no separate REST client for first-party screens.\",\n },\n api: {\n id: \"laravel-api\",\n label: \"API / SPA backend\",\n description:\n \"Opinionated Laravel API-only opinion pack (proposed decisions only) for a decoupled SPA or mobile client.\",\n frontendLine:\n \"No server-rendered frontend: Laravel is an HTTP JSON API consumed by a separate SPA or mobile app.\",\n deliveryLine:\n \"Controllers return JSON via API Resources; first-party SPAs authenticate with Sanctum cookies, mobile clients with Sanctum tokens.\",\n },\n};\n\nfunction adr(presetId: string, topic: string, title: string, body: string): PresetProposedDecision {\n return {\n id: `${presetId}-${topic}`,\n title,\n status: \"proposed\",\n destination: `docs/adrs/proposed/ADR-PROPOSED-${presetId}-${topic}.md`,\n body,\n };\n}\n\nfunction related(presetId: string, ...extra: string[]): string {\n return [\n `## Related Documents`,\n ``,\n `- \\`docs/ai/presets/${presetId}-guidance.md\\` — the proposed Laravel stack guidance.`,\n `- \\`docs/10-architecture/ARCHITECTURE.md\\` — record the accepted architecture here once promoted.`,\n ...extra.map((line) => `- ${line}`),\n ``,\n ].join(\"\\n\");\n}\n\nexport function laravelGuidance(variant: LaravelVariant): string {\n const profile = VARIANTS[variant];\n\n return `# Laravel Preset Guidance (${profile.label})\n\nThis is proposed guidance, not accepted. Convert any architecture choice into a proposed ADR, then an\naccepted ADR, before treating it as repository truth. Repository rules override model preference.\n\n## The stack (proposed)\n\n- Laravel 12 on PHP 8.3+, using the official conventions and directory layout.\n- ${profile.frontendLine}\n- Database: PostgreSQL (MySQL is the alternative) through Eloquent and migrations.\n- Auth: Laravel Sanctum for first-party SPA and mobile clients (Passport only if you need third-party OAuth2).\n- Background work: queues, with Redis and Laravel Horizon when throughput grows.\n- Tests: Pest, with database factories and feature tests over real routes.\n\n${profile.deliveryLine}\n\n## Decision forks this stack forces\n\n- Frontend delivery: Inertia (server-driven SPA) vs a decoupled API + separate SPA vs Blade + Livewire.\n- Auth: Sanctum (first-party SPA and mobile) vs Passport (third-party OAuth2) vs a managed identity provider.\n- Database: PostgreSQL vs MySQL, and where read scaling and queues live (Redis vs database driver).\n- Authorization: Policies and Gates vs ad-hoc checks; validation via Form Requests vs inline.\n- Business logic: thin controllers with Action/Service classes vs fat controllers and models.\n- Testing: Pest vs PHPUnit.\n\n## Recommended structure (proposed)\n\n- Keep controllers thin: they validate, authorize, delegate, and return a response — nothing more.\n- Put request validation **and** authorization in Form Requests (\\`authorize()\\` + \\`rules()\\`).\n- Put per-model and per-action permission logic in Policies and Gates, not in controllers.\n- Put business logic in single-purpose Action or Service classes, not in controllers or models.\n- Shape every outbound payload with API Resources (or typed Inertia props), never raw models.\n- Declare \\`$fillable\\` (or \\`$guarded\\`) explicitly on every Eloquent model to stop mass assignment.\n\n## Data and performance (proposed)\n\n- Eager-load relationships (\\`with(...)\\`) to avoid N+1 queries; enable \\`Model::preventLazyLoading()\\` in local and CI.\n- Wrap multi-write operations in database transactions.\n- Paginate list endpoints; never return unbounded collections.\n- Move email, exports, third-party calls, and other slow work into queued jobs.\n- Cache expensive reads deliberately, with explicit invalidation.\n\n## Testing (proposed)\n\n- Write Pest feature tests that exercise real routes end to end, using \\`RefreshDatabase\\`.\n- Build state with model factories, not hand-rolled fixtures.\n- Test authorization explicitly: a forbidden action must assert a 403, not just a happy path.\n- Cover validation failures, not only the success case.\n\n## Security considerations (proposed)\n\n- Validate every inbound request through Form Requests; persist only validated data.\n- Authorize every state-changing action through a Policy or Gate.\n- Keep secrets in \\`.env\\`; never commit \\`.env\\` or hardcode credentials.\n- Apply rate limiting to auth and write endpoints.\n- Keep mass assignment locked down and never trust client-supplied IDs without an ownership check.\n${\n variant === \"api\"\n ? \"- Scope Sanctum tokens to least privilege; SPA clients use the cookie guard with CSRF protection.\\n\"\n : \"- Inertia uses Laravel's session and CSRF protection; keep auth and authorization on the server, never the client.\\n\"\n}`;\n}\n\nexport function laravelGuidanceItems(): PresetGuidance[] {\n return [\n {\n title: \"Keep stack choices proposed\",\n body: \"Framework, frontend delivery, database, auth, and testing choices stay proposed until accepted in repository memory.\",\n },\n {\n title: \"Thin controllers, explicit authorization\",\n body: \"Validate and authorize in Form Requests and Policies, keep business logic in Action or Service classes, and shape output with Resources — propose these as decisions before treating them as truth.\",\n },\n ];\n}\n\nexport function laravelProposedDecisions(variant: LaravelVariant): PresetProposedDecision[] {\n const presetId = VARIANTS[variant].id;\n\n const base: PresetProposedDecision[] = [\n adr(\n presetId,\n \"framework\",\n \"Use Laravel\",\n `# Proposed ADR: Use Laravel\n\n## Status\n\nProposed\n\n## Context\n\nThe team needs a productive, batteries-included PHP framework for a production web application.\n\n## Decision\n\nConsider Laravel 12 on PHP 8.3+ as the application framework, following its standard conventions and\ndirectory structure. This is not accepted until a human reviews and accepts it.\n\n## Alternatives Considered\n\n- Symfony for a more component-assembled approach.\n- A different language or framework entirely.\n\n## Consequences\n\n- A mature ecosystem (Eloquent, queues, Sanctum, Horizon) and strong conventions.\n- Couples the application to Laravel's conventions and release cadence.\n\n${related(presetId)}`,\n ),\n adr(\n presetId,\n \"database-eloquent\",\n \"Use Eloquent and migrations on PostgreSQL\",\n `# Proposed ADR: Use Eloquent and migrations on PostgreSQL\n\n## Status\n\nProposed\n\n## Context\n\nThe application needs a relational database and a schema workflow.\n\n## Decision\n\nConsider PostgreSQL (MySQL as the alternative) accessed through Eloquent and versioned migrations,\nawaiting human acceptance.\n\n## Alternatives Considered\n\n- MySQL or MariaDB.\n- The query builder or raw SQL without Eloquent.\n\n## Consequences\n\n- Expressive models, relationships, and reproducible schema migrations.\n- Requires discipline against N+1 queries and unbounded result sets.\n\n${related(presetId, \"`docs/50-quality/TESTING_STRATEGY.md` — how database tests use factories and a disposable database.\")}`,\n ),\n adr(\n presetId,\n \"auth-sanctum\",\n \"Use Laravel Sanctum for authentication\",\n `# Proposed ADR: Use Laravel Sanctum for authentication\n\n## Status\n\nProposed\n\n## Context\n\nThe application needs authentication for first-party clients (${\n variant === \"api\"\n ? \"a separate SPA and mobile apps\"\n : \"an Inertia SPA, and possibly mobile apps\"\n }).\n\n## Decision\n\nConsider Laravel Sanctum: the cookie-based guard for first-party SPAs and API tokens for mobile or\nscripted clients. This is not accepted until a human reviews and accepts it.\n\n## Alternatives Considered\n\n- Laravel Passport for full OAuth2 (third-party delegated access).\n- A managed identity provider.\n\n## Consequences\n\n- Lightweight first-party auth without standing up a full OAuth2 server.\n- If third-party delegated access is ever required, revisit with Passport.\n\n${related(presetId, \"`docs/20-security/SECURITY_MODEL.md` — record the accepted auth and session model here.\")}`,\n ),\n adr(\n presetId,\n \"validation-authorization\",\n \"Validate with Form Requests and authorize with Policies\",\n `# Proposed ADR: Validate with Form Requests and authorize with Policies\n\n## Status\n\nProposed\n\n## Context\n\nInput validation and authorization must be consistent and centralized, not scattered across\ncontrollers.\n\n## Decision\n\nConsider Form Requests for validation (and request-level authorization) plus Policies and Gates for\nper-model and per-action permission checks, awaiting human acceptance.\n\n## Alternatives Considered\n\n- Inline validation and authorization in controllers.\n- A third-party permissions package layered on top.\n\n## Consequences\n\n- Controllers stay thin; validation and authorization are testable in isolation.\n- Every state-changing action must have an explicit authorization path.\n\n${related(presetId)}`,\n ),\n adr(\n presetId,\n \"application-structure\",\n \"Keep controllers thin with Action and Service classes\",\n `# Proposed ADR: Keep controllers thin with Action and Service classes\n\n## Status\n\nProposed\n\n## Context\n\nBusiness logic tends to accumulate in controllers and models, which makes it hard to test and reuse.\n\n## Decision\n\nConsider thin controllers that delegate to single-purpose Action or Service classes, with outbound\npayloads shaped by API Resources (or typed Inertia props). This is not accepted until a human accepts\nit.\n\n## Alternatives Considered\n\n- Fat controllers.\n- Fat models holding business logic.\n\n## Consequences\n\n- Reusable, unit-testable business logic and consistent response shapes.\n- More classes and a convention the team must follow.\n\n${related(presetId)}`,\n ),\n adr(\n presetId,\n \"queues-horizon\",\n \"Run slow work on queues\",\n `# Proposed ADR: Run slow work on queues\n\n## Status\n\nProposed\n\n## Context\n\nEmail, exports, and third-party calls slow down requests and can fail independently.\n\n## Decision\n\nConsider queued jobs for slow or failure-prone work, using the database driver early and Redis with\nLaravel Horizon as throughput grows. This is not accepted until a human reviews and accepts it.\n\n## Alternatives Considered\n\n- Doing the work synchronously in the request.\n- An external task queue or serverless functions.\n\n## Consequences\n\n- Faster responses and isolated, retryable background work.\n- Adds a worker process and queue infrastructure to operate and monitor.\n\n${related(presetId)}`,\n ),\n adr(\n presetId,\n \"testing-pest\",\n \"Use Pest for testing\",\n `# Proposed ADR: Use Pest for testing\n\n## Status\n\nProposed\n\n## Context\n\nThe application needs a fast, readable testing workflow.\n\n## Decision\n\nConsider Pest with model factories and feature tests that exercise real routes against a disposable\ndatabase, awaiting human acceptance.\n\n## Alternatives Considered\n\n- PHPUnit directly.\n- A thinner test suite focused only on unit tests.\n\n## Consequences\n\n- Concise, expressive tests that cover routes, validation, and authorization.\n- The team standardizes on Pest's syntax and plugins.\n\n${related(presetId, \"`docs/50-quality/TESTING_STRATEGY.md` — record the accepted testing approach here.\")}`,\n ),\n ];\n\n return [...base, frontendDecision(variant)];\n}\n\nfunction frontendDecision(variant: LaravelVariant): PresetProposedDecision {\n const presetId = VARIANTS[variant].id;\n\n if (variant === \"api\") {\n return adr(\n presetId,\n \"api-design-rest\",\n \"Expose a versioned REST API with API Resources\",\n `# Proposed ADR: Expose a versioned REST API with API Resources\n\n## Status\n\nProposed\n\n## Context\n\nA decoupled SPA or mobile client consumes Laravel over HTTP, so the API contract must be stable and\nexplicit.\n\n## Decision\n\nConsider a versioned REST API (for example \\`/api/v1\\`) whose responses are shaped by API Resources,\nauthenticated with Sanctum, and documented (OpenAPI). This is not accepted until a human accepts it.\n\n## Alternatives Considered\n\n- GraphQL.\n- Server-driven Inertia pages instead of a decoupled API.\n\n## Consequences\n\n- A stable, documented contract that multiple clients can rely on.\n- Versioning and serialization become an explicit, maintained concern.\n\n${related(presetId, \"`docs/20-security/SECURITY_MODEL.md` — record token scopes and the SPA cookie guard here.\")}`,\n );\n }\n\n const framework = variant === \"react\" ? \"React 19\" : \"Vue 3\";\n const components =\n variant === \"react\"\n ? \"shadcn/ui components on Tailwind\"\n : \"Tailwind with single-file components (script setup)\";\n\n return adr(\n presetId,\n `frontend-inertia-${variant}`,\n `Use Inertia with ${framework}`,\n `# Proposed ADR: Use Inertia with ${framework}\n\n## Status\n\nProposed\n\n## Context\n\nThe application needs a modern SPA experience without standing up and securing a separate API for\nfirst-party screens.\n\n## Decision\n\nConsider Inertia 2 with ${framework} and TypeScript, built with Vite, using ${components}. Controllers\nreturn Inertia responses with typed props. This is not accepted until a human reviews and accepts it.\n\n## Alternatives Considered\n\n- A decoupled REST or GraphQL API with a standalone SPA.\n- Blade with Livewire.\n\n## Consequences\n\n- Server-driven routing and auth with a reactive ${framework} frontend and no duplicate API layer.\n- Couples the frontend to Inertia's model and the ${framework} ecosystem.\n\n${related(presetId)}`,\n );\n}\n","import type { Preset } from \"../../core/presets/preset-schema.js\";\nimport {\n laravelGuidance,\n laravelGuidanceItems,\n laravelProposedDecisions,\n} from \"../laravel/shared.js\";\n\nexport const laravelApiPreset: Preset = {\n id: \"laravel-api\",\n name: \"Laravel API\",\n description: \"Opinionated Laravel API-only opinion pack with proposed decisions only.\",\n templates: [\n {\n destination: \"docs/ai/presets/laravel-api-guidance.md\",\n description: \"Laravel API-only guidance that remains proposed until accepted.\",\n content: laravelGuidance(\"api\"),\n },\n ],\n guidance: laravelGuidanceItems(),\n proposedDecisions: laravelProposedDecisions(\"api\"),\n};\n","import type { Preset } from \"../../core/presets/preset-schema.js\";\nimport {\n laravelGuidance,\n laravelGuidanceItems,\n laravelProposedDecisions,\n} from \"../laravel/shared.js\";\n\nexport const laravelReactPreset: Preset = {\n id: \"laravel-react\",\n name: \"Laravel + React\",\n description: \"Opinionated Laravel + Inertia + React opinion pack with proposed decisions only.\",\n templates: [\n {\n destination: \"docs/ai/presets/laravel-react-guidance.md\",\n description: \"Laravel + React (Inertia) guidance that remains proposed until accepted.\",\n content: laravelGuidance(\"react\"),\n },\n ],\n guidance: laravelGuidanceItems(),\n proposedDecisions: laravelProposedDecisions(\"react\"),\n};\n","import type { Preset } from \"../../core/presets/preset-schema.js\";\nimport {\n laravelGuidance,\n laravelGuidanceItems,\n laravelProposedDecisions,\n} from \"../laravel/shared.js\";\n\nexport const laravelVuePreset: Preset = {\n id: \"laravel-vue\",\n name: \"Laravel + Vue\",\n description: \"Opinionated Laravel + Inertia + Vue opinion pack with proposed decisions only.\",\n templates: [\n {\n destination: \"docs/ai/presets/laravel-vue-guidance.md\",\n description: \"Laravel + Vue (Inertia) guidance that remains proposed until accepted.\",\n content: laravelGuidance(\"vue\"),\n },\n ],\n guidance: laravelGuidanceItems(),\n proposedDecisions: laravelProposedDecisions(\"vue\"),\n};\n","import type { Preset } from \"../../core/presets/preset-schema.js\";\n\nconst guidance = `# Next.js Preset Guidance\n\nThis is proposed guidance, not accepted. Convert any architecture choice into a proposed ADR, then an\naccepted ADR, before treating it as repository truth.\n\n## Decision forks this stack forces\n\n- Routing: App Router vs Pages Router.\n- Rendering: Server Components and server actions vs client-heavy rendering.\n- Data layer: Drizzle or Prisma with PostgreSQL vs a hosted backend.\n- Styling: Tailwind CSS vs CSS Modules vs a component library.\n- Testing: Vitest with Testing Library and Playwright vs other runners.\n\n## Recommended structure (proposed)\n\n- The App Router with route groups and colocated server components.\n- A typed data layer isolated from UI components.\n- Shared UI primitives and a consistent styling system.\n\n## Testing (proposed)\n\n- Unit and component tests with Vitest and Testing Library.\n- End-to-end tests with Playwright for critical flows.\n- Type-safe data access tested against a disposable database.\n\n## Security considerations (proposed)\n\n- Keep secrets in server-only environment variables, never in client bundles.\n- Validate input on the server, including server actions and route handlers.\n- Scope authentication and authorization on the server, not the client.\n`;\n\nfunction proposedAdr(topic: string, title: string, body: string) {\n return {\n id: `nextjs-${topic}`,\n title,\n status: \"proposed\" as const,\n destination: `docs/adrs/proposed/ADR-PROPOSED-nextjs-${topic}.md`,\n body,\n };\n}\n\nexport const nextjsPreset: Preset = {\n id: \"nextjs\",\n name: \"Next.js\",\n description: \"Opinionated Next.js opinion pack with proposed decisions only.\",\n templates: [\n {\n destination: \"docs/ai/presets/nextjs-guidance.md\",\n description: \"Next.js guidance that remains proposed until accepted.\",\n content: guidance,\n },\n ],\n guidance: [\n {\n title: \"Keep framework choices proposed\",\n body: \"Routing, rendering, data layer, styling, and testing choices must remain proposed until accepted in repository memory.\",\n },\n {\n title: \"Keep secrets server-side\",\n body: \"Never expose secrets to the client bundle, and record the data and auth approach as proposed decisions before acceptance.\",\n },\n ],\n proposedDecisions: [\n proposedAdr(\n \"framework\",\n \"Use Next.js\",\n `# Proposed ADR: Use Next.js\n\n## Status\n\nProposed\n\n## Context\n\nThe team needs a React framework for a production web application.\n\n## Decision\n\nConsider Next.js as the application framework. This is not accepted until a human reviews and accepts\nit.\n\n## Alternatives Considered\n\n- A Vite single-page app with a separate API.\n- Remix or another framework.\n\n## Consequences\n\n- Server rendering, routing, and a large ecosystem.\n- Couples the app to Next.js conventions.\n`,\n ),\n proposedAdr(\n \"routing-app-router\",\n \"Use the App Router\",\n `# Proposed ADR: Use the App Router\n\n## Status\n\nProposed\n\n## Context\n\nNext.js offers the App Router and the legacy Pages Router.\n\n## Decision\n\nConsider the App Router with Server Components, awaiting human acceptance.\n\n## Alternatives Considered\n\n- The Pages Router.\n- A mix during migration.\n\n## Consequences\n\n- Server Components and nested layouts.\n- Requires understanding server and client boundaries.\n`,\n ),\n proposedAdr(\n \"data-layer\",\n \"Use a typed data layer with PostgreSQL\",\n `# Proposed ADR: Use a typed data layer with PostgreSQL\n\n## Status\n\nProposed\n\n## Context\n\nThe app needs a database and a typed access layer.\n\n## Decision\n\nConsider Drizzle or Prisma with PostgreSQL, awaiting human acceptance.\n\n## Alternatives Considered\n\n- A hosted backend or BaaS.\n- Raw SQL.\n\n## Consequences\n\n- Type-safe queries and migrations.\n- Adds an ORM and schema workflow.\n`,\n ),\n proposedAdr(\n \"styling-tailwind\",\n \"Use Tailwind CSS\",\n `# Proposed ADR: Use Tailwind CSS\n\n## Status\n\nProposed\n\n## Context\n\nThe app needs a styling approach.\n\n## Decision\n\nConsider Tailwind CSS for styling, awaiting human acceptance.\n\n## Alternatives Considered\n\n- CSS Modules.\n- A component library with its own styling.\n\n## Consequences\n\n- Fast, consistent utility-based styling.\n- Markup includes utility classes that teams must standardize.\n`,\n ),\n proposedAdr(\n \"testing\",\n \"Use Vitest and Playwright\",\n `# Proposed ADR: Use Vitest and Playwright\n\n## Status\n\nProposed\n\n## Context\n\nThe app needs unit, component, and end-to-end testing.\n\n## Decision\n\nConsider Vitest with Testing Library and Playwright, awaiting human acceptance.\n\n## Alternatives Considered\n\n- Jest.\n- Cypress for end-to-end tests.\n\n## Consequences\n\n- Fast unit and component tests plus reliable end-to-end coverage.\n- Teams maintain two test toolchains.\n`,\n ),\n ],\n};\n","import type { Preset } from \"../../core/presets/preset-schema.js\";\n\nconst guidance = `# Python FastAPI Preset Guidance\n\nThis guidance is proposed, not accepted. Convert any choice you adopt into an accepted ADR in\nrepository memory. Until then, treat everything here as a recommendation awaiting human review.\n\n## Decision forks this stack forces\n\n- Web framework: FastAPI vs Flask vs Django REST.\n- Database and access: PostgreSQL with SQLAlchemy and Alembic vs an async ORM vs raw SQL.\n- Validation and settings: Pydantic v2 models and settings.\n- Testing: pytest with httpx vs unittest.\n- Background work and caching: Redis, task queues, and async workers.\n\n## Recommended structure (proposed)\n\n- A layered layout: \\`api/\\` routers, \\`services/\\` logic, \\`repositories/\\` data access, \\`models/\\` schemas.\n- Dependency injection through FastAPI dependencies.\n- Configuration via Pydantic settings loaded from environment variables.\n\n## Testing (proposed)\n\n- pytest with the FastAPI test client or httpx \\`AsyncClient\\`.\n- A disposable test database and transactional fixtures.\n- Contract tests for request and response schemas.\n\n## Security considerations (proposed)\n\n- Load secrets from environment or a secret manager, never from source.\n- Validate and constrain all input with Pydantic models.\n- Scope authentication and authorization at the dependency layer.\n`;\n\nfunction proposedAdr(topic: string, title: string, body: string) {\n return {\n id: `python-fastapi-${topic}`,\n title,\n status: \"proposed\" as const,\n destination: `docs/adrs/proposed/ADR-PROPOSED-python-fastapi-${topic}.md`,\n body,\n };\n}\n\nexport const pythonFastapiPreset: Preset = {\n id: \"python-fastapi\",\n name: \"Python FastAPI\",\n description: \"Opinionated Python FastAPI opinion pack with proposed decisions only.\",\n templates: [\n {\n destination: \"docs/ai/presets/python-fastapi-guidance.md\",\n description: \"Python FastAPI guidance that remains proposed until accepted.\",\n content: guidance,\n },\n ],\n guidance: [\n {\n title: \"Keep framework and data choices proposed\",\n body: \"FastAPI, the database and ORM, validation, and testing choices must remain proposed until accepted in repository memory.\",\n },\n {\n title: \"Validate all input\",\n body: \"Use Pydantic models at the boundary, but record the validation approach as a proposed decision before treating it as accepted.\",\n },\n ],\n proposedDecisions: [\n proposedAdr(\n \"framework\",\n \"Use FastAPI\",\n `# Proposed ADR: Use FastAPI\n\n## Status\n\nProposed\n\n## Context\n\nThe service needs a Python web framework for an async API.\n\n## Decision\n\nConsider FastAPI as the web framework, awaiting human acceptance.\n\n## Alternatives Considered\n\n- Flask.\n- Django REST Framework.\n\n## Consequences\n\n- Async support and automatic OpenAPI docs.\n- Requires comfort with type hints and dependency injection.\n`,\n ),\n proposedAdr(\n \"database-postgres\",\n \"Use PostgreSQL with SQLAlchemy and Alembic\",\n `# Proposed ADR: Use PostgreSQL with SQLAlchemy\n\n## Status\n\nProposed\n\n## Context\n\nThe service needs a relational database and a migration strategy.\n\n## Decision\n\nConsider PostgreSQL with SQLAlchemy and Alembic migrations, awaiting human acceptance.\n\n## Alternatives Considered\n\n- An async ORM such as Tortoise or SQLModel only.\n- Raw SQL with a lightweight driver.\n\n## Consequences\n\n- Mature tooling and explicit migrations.\n- Requires session and connection management discipline.\n`,\n ),\n proposedAdr(\n \"validation-pydantic\",\n \"Use Pydantic for validation and settings\",\n `# Proposed ADR: Use Pydantic\n\n## Status\n\nProposed\n\n## Context\n\nThe service needs request validation and typed configuration.\n\n## Decision\n\nConsider Pydantic v2 models for validation and settings, awaiting human acceptance.\n\n## Alternatives Considered\n\n- Marshmallow.\n- Hand-written validation.\n\n## Consequences\n\n- Strong typing at the boundary and clear settings.\n- Adds Pydantic to the dependency surface.\n`,\n ),\n proposedAdr(\n \"testing-pytest\",\n \"Use pytest for testing\",\n `# Proposed ADR: Use pytest\n\n## Status\n\nProposed\n\n## Context\n\nThe service needs a test framework and HTTP testing approach.\n\n## Decision\n\nConsider pytest with httpx for API tests, awaiting human acceptance.\n\n## Alternatives Considered\n\n- unittest.\n- nose-style runners.\n\n## Consequences\n\n- Concise fixtures and rich plugins.\n- Teams must standardize fixture and database setup.\n`,\n ),\n proposedAdr(\n \"cache-redis\",\n \"Use Redis for caching and background work\",\n `# Proposed ADR: Use Redis\n\n## Status\n\nProposed\n\n## Context\n\nThe service may need caching, rate limiting, or a task queue backend.\n\n## Decision\n\nConsider Redis for caching and background work, awaiting human acceptance.\n\n## Alternatives Considered\n\n- In-process caching only.\n- A managed queue service.\n\n## Consequences\n\n- Fast shared cache and queue backend.\n- Adds an operational dependency to run and monitor.\n`,\n ),\n ],\n};\n","import { z } from \"zod\";\n\nimport { normalizeOutputPath } from \"../filesystem/safe-path.js\";\n\nconst PRESET_ID_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/u;\n\nconst safeDestinationSchema = z.string().transform((value, context) => {\n try {\n return normalizeOutputPath(value);\n } catch (error) {\n context.addIssue({\n code: \"custom\",\n message: error instanceof Error ? error.message : \"Destination is invalid.\",\n });\n return z.NEVER;\n }\n});\n\nexport class PresetValidationError extends Error {\n readonly issues: string[];\n\n constructor(issues: string[]) {\n super(`Invalid Recall OS preset: ${issues.join(\"; \")}`);\n this.name = \"PresetValidationError\";\n this.issues = issues;\n }\n}\n\nexport const presetTemplateSchema = z\n .object({\n destination: safeDestinationSchema,\n content: z.string().min(1, \"Template content cannot be empty.\"),\n description: z.string().min(1).optional(),\n })\n .strict();\n\nexport const presetGuidanceSchema = z\n .object({\n title: z.string().min(1, \"Guidance title cannot be empty.\"),\n body: z.string().min(1, \"Guidance body cannot be empty.\"),\n })\n .strict();\n\nexport const presetProposedDecisionSchema = z\n .object({\n id: z\n .string()\n .min(1, \"Decision id cannot be empty.\")\n .max(80, \"Decision id cannot exceed 80 characters.\")\n .regex(\n PRESET_ID_PATTERN,\n \"Decision id must use lowercase letters, numbers, and single hyphens.\",\n ),\n title: z.string().min(1, \"Decision title cannot be empty.\"),\n status: z.literal(\"proposed\"),\n destination: safeDestinationSchema,\n body: z.string().min(1, \"Decision body cannot be empty.\"),\n })\n .strict();\n\nexport const presetSchema = z\n .object({\n id: z\n .string()\n .min(1, \"Preset id cannot be empty.\")\n .max(80, \"Preset id cannot exceed 80 characters.\")\n .regex(\n PRESET_ID_PATTERN,\n \"Preset id must use lowercase letters, numbers, and single hyphens.\",\n ),\n name: z.string().min(1, \"Preset name cannot be empty.\"),\n description: z.string().min(1, \"Preset description cannot be empty.\"),\n templates: z.array(presetTemplateSchema).min(1, \"Preset must include a template.\"),\n guidance: z.array(presetGuidanceSchema).default([]),\n proposedDecisions: z.array(presetProposedDecisionSchema).default([]),\n })\n .strict()\n .superRefine((preset, context) => {\n const destinations = new Set<string>();\n\n for (const [index, template] of preset.templates.entries()) {\n if (destinations.has(template.destination)) {\n context.addIssue({\n code: \"custom\",\n path: [\"templates\", index, \"destination\"],\n message: `Duplicate destination \"${template.destination}\".`,\n });\n }\n\n destinations.add(template.destination);\n }\n\n for (const [index, decision] of preset.proposedDecisions.entries()) {\n if (destinations.has(decision.destination)) {\n context.addIssue({\n code: \"custom\",\n path: [\"proposedDecisions\", index, \"destination\"],\n message: `Duplicate destination \"${decision.destination}\".`,\n });\n }\n\n destinations.add(decision.destination);\n }\n });\n\nexport type PresetTemplate = z.infer<typeof presetTemplateSchema>;\nexport type PresetGuidance = z.infer<typeof presetGuidanceSchema>;\nexport type PresetProposedDecision = z.infer<typeof presetProposedDecisionSchema>;\nexport type Preset = z.infer<typeof presetSchema>;\n\nexport function parsePreset(value: unknown): Preset {\n const result = presetSchema.safeParse(value);\n\n if (!result.success) {\n throw new PresetValidationError(\n result.error.issues.map((issue) => {\n const path = issue.path.length > 0 ? `${issue.path.join(\".\")}: ` : \"\";\n return `${path}${issue.message}`;\n }),\n );\n }\n\n return result.data;\n}\n","import { parsePreset, PresetValidationError, type Preset } from \"./preset-schema.js\";\n\nexport function validatePreset(preset: Preset): Preset {\n return parsePreset(preset);\n}\n\nexport function validatePresetRegistry(presets: readonly Preset[]): Preset[] {\n const validatedPresets = presets.map((preset) => parsePreset(preset));\n const seenIds = new Set<string>();\n\n for (const preset of validatedPresets) {\n if (seenIds.has(preset.id)) {\n throw new PresetValidationError([`Duplicate preset id \"${preset.id}\".`]);\n }\n\n seenIds.add(preset.id);\n }\n\n return [...validatedPresets].sort((left, right) => left.id.localeCompare(right.id));\n}\n","import { flutterPreset } from \"../../presets/flutter/preset.js\";\nimport { genericPreset } from \"../../presets/generic/preset.js\";\nimport { iosSwiftPreset } from \"../../presets/ios-swift/preset.js\";\nimport { kotlinAndroidPreset } from \"../../presets/kotlin-android/preset.js\";\nimport { laravelApiPreset } from \"../../presets/laravel-api/preset.js\";\nimport { laravelReactPreset } from \"../../presets/laravel-react/preset.js\";\nimport { laravelVuePreset } from \"../../presets/laravel-vue/preset.js\";\nimport { nextjsPreset } from \"../../presets/nextjs/preset.js\";\nimport { pythonFastapiPreset } from \"../../presets/python-fastapi/preset.js\";\nimport { validatePresetRegistry } from \"./validate-preset.js\";\nimport type { Preset } from \"./preset-schema.js\";\n\nconst builtInPresets = validatePresetRegistry([\n flutterPreset,\n genericPreset,\n iosSwiftPreset,\n kotlinAndroidPreset,\n laravelApiPreset,\n laravelReactPreset,\n laravelVuePreset,\n nextjsPreset,\n pythonFastapiPreset,\n]);\n\nexport function listPresets(): Preset[] {\n return [...builtInPresets];\n}\n\nexport function getPreset(id: string): Preset | undefined {\n return builtInPresets.find((preset) => preset.id === id);\n}\n","import type { SkillDefinition } from \"./skill-catalog.js\";\n\n/**\n * Render a SkillDefinition into a valid Agent Skills SKILL.md.\n *\n * The output uses only the standard portable fields (`name`, `description`) and contains no scripts,\n * so the same file works in Claude Code and other Agent Skills-compatible tools.\n */\nexport function renderSkill(skill: SkillDefinition): string {\n const lines: string[] = [\n \"---\",\n `name: ${skill.name}`,\n // JSON-stringify yields a valid double-quoted YAML scalar, so descriptions with any punctuation\n // stay valid Agent Skills frontmatter.\n `description: ${JSON.stringify(skill.description)}`,\n \"---\",\n \"\",\n `# Skill: ${skill.title}`,\n \"\",\n \"## Purpose\",\n \"\",\n ...paragraphs(skill.purpose),\n \"\",\n \"## Inputs\",\n \"\",\n ...bullets(skill.inputs),\n \"\",\n \"## Required Reading\",\n \"\",\n ...bullets(skill.requiredReading),\n \"\",\n \"## Output Files\",\n \"\",\n ...bullets(skill.outputFiles),\n \"\",\n \"## Process\",\n \"\",\n ...numbered(skill.process),\n \"\",\n ];\n\n for (const section of skill.extraSections ?? []) {\n lines.push(`## ${section.heading}`, \"\", ...bullets(section.bullets), \"\");\n }\n\n lines.push(\n \"## Stop Conditions\",\n \"\",\n \"Stop and request human decision if:\",\n \"\",\n ...bullets(skill.stopConditions),\n \"\",\n \"## Quality Bar\",\n \"\",\n ...bullets(skill.qualityBar),\n );\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction paragraphs(values: string[]): string[] {\n const out: string[] = [];\n values.forEach((value, index) => {\n if (index > 0) {\n out.push(\"\");\n }\n out.push(value);\n });\n return out;\n}\n\nfunction bullets(values: string[]): string[] {\n return values.map((value) => `- ${value}`);\n}\n\nfunction numbered(values: string[]): string[] {\n return values.map((value, index) => `${index + 1}. ${value}`);\n}\n","export type SkillDefinition = {\n name: string;\n title: string;\n description: string;\n purpose: string[];\n inputs: string[];\n requiredReading: string[];\n outputFiles: string[];\n process: string[];\n extraSections?: { heading: string; bullets: string[] }[];\n stopConditions: string[];\n qualityBar: string[];\n};\n\n/**\n * Built-in catalog of Recall OS workflow skills.\n *\n * Each skill is portable (standard Agent Skills fields only) and contains no scripts, so the same\n * SKILL.md works across Claude Code and other Agent Skills-compatible tools. Descriptions include\n * \"Use when ...\" trigger language so agents invoke them at the right moment.\n */\nexport const SKILL_CATALOG: SkillDefinition[] = [\n {\n name: \"create-prd\",\n title: \"Create PRD\",\n description:\n \"Create or update a feature PRD with user intent, scope, acceptance criteria, non-goals, security notes, test expectations, and source-of-truth links. Use when starting a feature, drafting or updating a PRD, or defining acceptance criteria.\",\n purpose: [\n \"Create a useful feature PRD that helps humans and AI agents understand what should be built and why.\",\n ],\n inputs: [\n \"Feature name or problem statement.\",\n \"User goal or business reason.\",\n \"Any existing product notes, tickets, or change requests.\",\n ],\n requiredReading: [\n \"`docs/00-product/BRD.md`\",\n \"`docs/00-product/PRD.md`\",\n \"Relevant existing `docs/40-features/<feature>/`\",\n \"Relevant accepted ADRs in `docs/adrs/`\",\n ],\n outputFiles: [\n \"`docs/40-features/<feature>/PRD.md`\",\n \"`docs/40-features/<feature>/ACCEPTANCE.md`, when acceptance criteria are part of the request.\",\n \"`docs/40-features/<feature>/CHANGE_REQUESTS.md`, when changing existing requirements.\",\n ],\n process: [\n \"Identify the user, problem, desired outcome, and non-goals.\",\n \"Link the feature to product goals and existing source-of-truth docs.\",\n \"Define acceptance criteria that can be tested.\",\n \"Capture security, privacy, file write, dependency, and MCP implications.\",\n \"Identify architecture areas that require follow-up review.\",\n \"Keep the PRD concise and implementation-guiding.\",\n ],\n stopConditions: [\n \"Product intent is contradictory.\",\n \"A requested behavior conflicts with an accepted ADR.\",\n \"The feature adds network, telemetry, AI API, cloud, MCP runtime, auth, secrets, or file write behavior without explicit approval.\",\n \"Scope is too broad to define testable acceptance criteria.\",\n ],\n qualityBar: [\n \"The PRD states goals, non-goals, users, acceptance criteria, risks, and source links.\",\n \"Acceptance criteria are concrete enough to drive tests.\",\n \"Security and architecture implications are not generic filler.\",\n \"The PRD does not duplicate full architecture docs.\",\n ],\n },\n {\n name: \"plan-feature\",\n title: \"Plan Feature\",\n description:\n \"Plan a feature from approved requirements by producing implementation tasks, architecture impact, test plan, review expectations, and completion evidence. Use when turning an approved PRD into a plan, tasks, and a test plan.\",\n purpose: [\n \"Turn product intent into a scoped engineering plan that an implementation agent can follow safely.\",\n ],\n inputs: [\n \"Feature PRD.\",\n \"Acceptance criteria.\",\n \"Relevant module or architecture docs.\",\n \"Known constraints or release target.\",\n ],\n requiredReading: [\n \"`docs/10-architecture/ARCHITECTURE.md`\",\n \"`docs/10-architecture/FILE_WRITE_POLICY.md`\",\n \"`docs/20-security/SECURITY_MODEL.md`\",\n \"`docs/50-quality/QUALITY_GATES.md`\",\n \"`docs/60-engineering/ENGINEERING_STANDARDS.md`\",\n \"Relevant feature docs under `docs/40-features/`\",\n \"Relevant module docs under `docs/30-modules/`\",\n \"Relevant ADRs under `docs/adrs/`\",\n ],\n outputFiles: [\n \"`docs/40-features/<feature>/PLAN.md`\",\n \"`docs/40-features/<feature>/TASKS.md`\",\n \"`docs/40-features/<feature>/ARCHITECTURE_IMPACT.md`\",\n \"`docs/40-features/<feature>/TEST_PLAN.md`\",\n ],\n process: [\n \"Restate the feature objective and acceptance criteria.\",\n \"Identify modules, docs, templates, and tests affected.\",\n \"Document architecture impact and ADR needs.\",\n \"Break work into ordered tasks with clear completion evidence.\",\n \"Define tests from requirements, risk, security invariants, and regressions.\",\n \"For module requests, treat the module as a mini product and create feature delivery docs before implementation tasks.\",\n ],\n stopConditions: [\n \"Requirements are missing or contradictory.\",\n \"Architecture impact cannot be determined.\",\n \"The plan conflicts with engineering standards.\",\n \"A task requires changing accepted non-goals.\",\n \"A module request tries to start implementation before PRD, acceptance, architecture impact, test plan, and tasks exist.\",\n ],\n qualityBar: [\n \"Tasks are ordered and independently reviewable.\",\n \"Tests map to acceptance criteria and risks.\",\n \"Architecture impact is explicit.\",\n \"Engineering standards are accounted for in tasks and completion evidence.\",\n \"The plan does not include implementation code when only planning is requested.\",\n ],\n },\n {\n name: \"plan-module\",\n title: \"Plan Module\",\n description:\n \"Plan a module as a mini product by creating feature delivery docs, module memory, acceptance criteria, architecture impact, test plan, and ordered tasks before implementation. Use when asked to build, create, redesign, or materially change a module.\",\n purpose: [\n \"Turn a module request into a complete delivery workflow before implementation starts.\",\n ],\n inputs: [\n \"Module name or request.\",\n \"Product goal or user need.\",\n \"Existing architecture, feature, or module docs.\",\n \"Known constraints or priority stage.\",\n ],\n requiredReading: [\n \"`AGENTS.md`\",\n \"`docs/00-product/PRD.md`\",\n \"`docs/10-architecture/ARCHITECTURE.md`\",\n \"`docs/20-security/SECURITY_MODEL.md`\",\n \"`docs/50-quality/TESTING_STRATEGY.md`\",\n \"`docs/60-engineering/ENGINEERING_STANDARDS.md`\",\n \"`docs/ai/MODULE_DELIVERY_WORKFLOW.md`\",\n \"Relevant ADRs under `docs/adrs/`\",\n ],\n outputFiles: [\n \"`docs/40-features/F-###-<module>-module/` delivery docs (PRD, ACCEPTANCE, ARCHITECTURE_IMPACT, PLAN, TASKS, TEST_PLAN, REVIEW, COMPLETION_REPORT).\",\n \"`docs/30-modules/<module>/MODULE.md`\",\n \"`docs/30-modules/<module>/TASKS.md`\",\n \"`docs/30-modules/<module>/TEST_PLAN.md`\",\n \"`docs/30-modules/<module>/DECISIONS.md`\",\n ],\n process: [\n \"Create a module brief: ownership, non-ownership, public interfaces, users, and use cases.\",\n \"Define behavior and edge cases.\",\n \"Write testable acceptance criteria.\",\n \"Document architecture impact, dependency impact, config impact, template impact, and ADR needs.\",\n \"Write the test plan from acceptance criteria, security invariants, and regression risk.\",\n \"Break work into ordered tasks with status, scope, acceptance, tests, and do-not-do boundaries.\",\n \"Mark implementation as blocked until the first task is selected.\",\n ],\n stopConditions: [\n \"The module ownership or public interface is unclear.\",\n \"The module conflicts with accepted ADRs or architecture docs.\",\n \"The module conflicts with engineering standards.\",\n \"The module requires runtime network, telemetry, cloud, MCP, AI API, auth, secrets, storage, or file write behavior changes without ADR or security review.\",\n \"The user asks to implement before PRD, acceptance, architecture impact, test plan, and tasks exist.\",\n ],\n qualityBar: [\n \"The module is planned as a mini product, not a file list.\",\n \"PRD, acceptance, architecture impact, test plan, and tasks are all present.\",\n \"Tasks are small enough to execute one at a time.\",\n \"Module memory captures what future agents need to remember.\",\n \"No implementation code is written by this skill.\",\n ],\n },\n {\n name: \"create-adr\",\n title: \"Create ADR\",\n description:\n \"Create an Architecture Decision Record for a meaningful architecture, dependency, security, file-write, MCP, or workflow decision. Use when recording such a decision so future agents do not contradict it.\",\n purpose: [\n \"Record durable architecture decisions so future humans and agents do not rediscover or contradict them.\",\n ],\n inputs: [\n \"Decision topic.\",\n \"Context and constraints.\",\n \"Options considered.\",\n \"Recommended or selected decision.\",\n ],\n requiredReading: [\n \"`docs/10-architecture/ARCHITECTURE.md`\",\n \"`docs/10-architecture/FILE_WRITE_POLICY.md`\",\n \"`docs/20-security/SECURITY_MODEL.md`\",\n \"Relevant existing ADRs in `docs/adrs/`\",\n ],\n outputFiles: [\"`docs/adrs/ADR-####-<slug>.md`\"],\n process: [\n \"Determine whether the change needs an ADR.\",\n \"Find the next ADR number without reusing existing numbers.\",\n \"Write context, decision, alternatives, consequences, and related docs.\",\n \"Mark the status as `Proposed` unless the human has accepted the decision.\",\n \"Link to affected PRDs, architecture docs, feature docs, and security docs.\",\n ],\n stopConditions: [\n \"The decision changes security posture, network behavior, telemetry, file writes, auth, secrets, cloud, or runtime MCP.\",\n \"The requested decision conflicts with an accepted ADR.\",\n \"The decision is not actually made yet and should remain a proposal.\",\n ],\n qualityBar: [\n \"The ADR explains why the decision exists, not just what changed.\",\n \"Alternatives and consequences are honest.\",\n \"Status is clear.\",\n \"Related documents are linked.\",\n ],\n },\n {\n name: \"implement-task\",\n title: \"Implement Task\",\n description:\n \"Implement one scoped engineering task while preserving requirements, architecture boundaries, security posture, tests, docs, and completion evidence. Use when implementing a single task from an approved plan.\",\n purpose: [\"Implement a bounded task safely from approved requirements and plans.\"],\n inputs: [\n \"Task description.\",\n \"Feature plan or acceptance criteria.\",\n \"Relevant module and architecture docs.\",\n ],\n requiredReading: [\n \"`AGENTS.md`\",\n \"`docs/10-architecture/ARCHITECTURE.md`\",\n \"`docs/10-architecture/FILE_WRITE_POLICY.md`\",\n \"`docs/20-security/SECURITY_MODEL.md`\",\n \"`docs/60-engineering/ENGINEERING_STANDARDS.md`\",\n \"Relevant feature, module, and ADR docs.\",\n ],\n outputFiles: [\n \"Implementation files for the scoped task.\",\n \"Tests for changed behavior.\",\n \"Updated module, feature, or completion docs when behavior changes.\",\n ],\n process: [\n \"Confirm the task has clear acceptance criteria.\",\n \"Confirm the task comes after PRD, acceptance, architecture impact, and test plan.\",\n \"Identify affected modules and tests.\",\n \"Implement the smallest safe change.\",\n \"Add or update tests based on risk.\",\n \"Update docs when behavior, architecture, or module ownership changes.\",\n \"Prepare completion evidence with commands and results.\",\n ],\n stopConditions: [\n \"The task conflicts with source-of-truth docs.\",\n \"The task conflicts with engineering standards.\",\n \"The task requires adding runtime network, telemetry, cloud, MCP, AI API, or generated production app behavior without review.\",\n \"A dependency is needed without ADR consideration.\",\n \"Tests cannot be designed from the available requirements.\",\n ],\n qualityBar: [\n \"Scope stays narrow.\",\n \"Tests cover behavior and risk.\",\n \"File write and security rules are preserved.\",\n \"Engineering standards are followed.\",\n \"Completion evidence is concrete.\",\n \"One task is implemented at a time.\",\n ],\n },\n {\n name: \"write-tests\",\n title: \"Write Tests\",\n description:\n \"Write meaningful tests from acceptance criteria, risk, security invariants, module boundaries, and regression history. Use when adding or updating tests, writing a test plan, or covering a new feature or bug fix.\",\n purpose: [\"Create professional tests that prove important behavior, not random happy paths.\"],\n inputs: [\n \"Feature PRD or task.\",\n \"Acceptance criteria.\",\n \"Changed files or planned modules.\",\n \"Known risks.\",\n ],\n requiredReading: [\n \"`docs/50-quality/TESTING_STRATEGY.md`\",\n \"`docs/50-quality/QUALITY_GATES.md`\",\n \"`docs/20-security/SECURITY_MODEL.md`\",\n \"`docs/60-engineering/ENGINEERING_STANDARDS.md`\",\n \"Relevant feature `TEST_PLAN.md`\",\n \"Relevant module `TEST_PLAN.md`\",\n ],\n outputFiles: [\n \"Test files under the appropriate `tests/` area.\",\n \"Updated `TEST_PLAN.md` when test strategy changes.\",\n \"Completion evidence listing commands and results.\",\n ],\n process: [\n \"Map acceptance criteria to test cases.\",\n \"Add risk-based tests for unsafe paths, overwrites, symlinks, config validation, generated output, and CLI behavior as relevant.\",\n \"Prefer unit tests for pure logic and integration tests for command behavior.\",\n \"Add golden tests for generated docs and templates.\",\n \"Name tests by behavior.\",\n \"Document skipped tests and remaining risk.\",\n ],\n stopConditions: [\n \"Requirements are not testable.\",\n \"The requested test would require runtime network, telemetry, cloud, MCP, or AI API behavior without review.\",\n \"Security-sensitive behavior lacks a documented expected result.\",\n \"The test approach conflicts with engineering standards.\",\n ],\n qualityBar: [\n \"Tests derive from requirements and risk.\",\n \"Security invariants are covered.\",\n \"Test names describe behavior.\",\n \"Engineering standards for evidence and skipped checks are followed.\",\n \"The completion report includes commands and results.\",\n ],\n },\n {\n name: \"security-review\",\n title: \"Security Review\",\n description:\n \"Review a change for file write safety, path traversal, symlink risk, overwrite behavior, dependencies, secrets, telemetry, network, MCP, and supply chain risk. Use when reviewing a change for security before it is accepted.\",\n purpose: [\"Find security risks before a change is accepted.\"],\n inputs: [\n \"Change summary or diff.\",\n \"Feature docs.\",\n \"Architecture and security docs.\",\n \"Test results.\",\n ],\n requiredReading: [\n \"`docs/20-security/SECURITY_MODEL.md`\",\n \"`docs/20-security/THREAT_MODEL.md`\",\n \"`docs/10-architecture/FILE_WRITE_POLICY.md`\",\n \"`docs/60-engineering/ENGINEERING_STANDARDS.md`\",\n \"`docs/ai/MCP_STRATEGY.md`\",\n ],\n outputFiles: [\n \"Relevant feature `REVIEW.md`\",\n \"Relevant feature `COMPLETION_REPORT.md`\",\n \"Security docs, if the accepted behavior changes.\",\n ],\n process: [\n \"Identify changed trust boundaries.\",\n \"Check path validation, overwrite policy, symlink policy, and dry-run behavior.\",\n \"Check dependency, package, template, and preset risk.\",\n \"Check for network, telemetry, secrets, `.env`, cloud, AI API, or runtime MCP behavior.\",\n \"Check tests for security-sensitive behavior.\",\n \"Classify findings as blockers, risks, or documented acceptable tradeoffs.\",\n ],\n stopConditions: [\n \"Runtime network, telemetry, cloud, MCP, AI API, auth, secrets, storage, or file write behavior changes without ADR or security review.\",\n \"Existing files can be overwritten by default.\",\n \"Writes can escape the project root.\",\n \"Secrets could be read, logged, or generated into docs.\",\n \"Engineering standards are bypassed for secrets, dependencies, migrations, tests, or completion evidence.\",\n ],\n qualityBar: [\n \"Findings are specific and actionable.\",\n \"Security claims cite docs or test evidence.\",\n \"Remaining risks are explicit.\",\n ],\n },\n {\n name: \"architecture-drift-review\",\n title: \"Architecture Drift Review\",\n description:\n \"Review a change for undocumented architecture, dependency, module, security, testing, or documentation drift. Use when checking whether a change diverges from accepted repository memory.\",\n purpose: [\n \"Find changes that diverge from accepted repository memory.\",\n \"Drift is not difference from a Recall OS recommendation. Recall OS is architecture-neutral.\",\n ],\n inputs: [\"Change summary or diff.\", \"Feature docs.\", \"Module docs.\", \"ADRs.\", \"Test results.\"],\n requiredReading: [\n \"`docs/10-architecture/ARCHITECTURE.md`\",\n \"`docs/60-engineering/ENGINEERING_STANDARDS.md`\",\n \"`docs/20-security/SECURITY_MODEL.md`\",\n \"Relevant `docs/30-modules/<module>/MODULE.md`\",\n \"Relevant `docs/40-features/<feature>/PRD.md`\",\n \"Relevant `docs/adrs/*.md`\",\n ],\n outputFiles: [\n \"Relevant feature `REVIEW.md`\",\n \"Relevant feature `COMPLETION_REPORT.md`\",\n \"Updated docs only when the human accepts documented evolution.\",\n ],\n process: [\n \"Review the change and identify changed modules and generated outputs.\",\n \"Compare changes against accepted ADRs and repository decisions.\",\n \"Compare changes against module boundaries.\",\n \"Check for new dependencies and security-sensitive changes.\",\n \"Check whether tests and docs were updated.\",\n \"Classify findings.\",\n ],\n extraSections: [\n {\n heading: \"Finding Types\",\n bullets: [\n \"Architecture drift\",\n \"Dependency drift\",\n \"Module drift\",\n \"Security drift\",\n \"Testing drift\",\n \"Documentation drift\",\n \"Engineering standards drift\",\n \"Acceptable documented evolution\",\n ],\n },\n ],\n stopConditions: [\n \"An accepted ADR conflicts with the implementation.\",\n \"The implementation conflicts with engineering standards.\",\n \"A dependency was added without ADR consideration.\",\n \"Authentication, authorization, storage, networking, secrets, telemetry, cloud, runtime MCP, or file write behavior changed without security review.\",\n \"Feature behavior changed without a PRD or change request update.\",\n ],\n qualityBar: [\n \"Findings distinguish drift from documented evolution.\",\n \"Findings compare against accepted repository memory, not Recall OS preferences.\",\n \"Each blocker names the missing source-of-truth update.\",\n \"Review output is concrete enough to act on.\",\n ],\n },\n {\n name: \"update-module-memory\",\n title: \"Update Module Memory\",\n description:\n \"Update module memory docs after module behavior, ownership, boundaries, tests, risks, or decisions change. Use when a module's behavior, ownership, boundaries, tests, risks, or decisions change.\",\n purpose: [\n \"Keep module docs accurate so agents do not rediscover ownership, boundaries, tests, and decisions.\",\n ],\n inputs: [\n \"Changed module or feature.\",\n \"Implementation summary.\",\n \"Test results.\",\n \"Architecture or ADR changes.\",\n ],\n requiredReading: [\n \"`docs/60-engineering/ENGINEERING_STANDARDS.md`\",\n \"`docs/ai/MODULE_DELIVERY_WORKFLOW.md`\",\n \"Relevant `docs/30-modules/<module>/MODULE.md`\",\n \"Relevant `docs/30-modules/<module>/DECISIONS.md`\",\n \"Relevant feature docs and ADRs.\",\n ],\n outputFiles: [\n \"`docs/30-modules/<module>/MODULE.md`\",\n \"`docs/30-modules/<module>/TASKS.md`\",\n \"`docs/30-modules/<module>/TEST_PLAN.md`\",\n \"`docs/30-modules/<module>/DECISIONS.md`\",\n ],\n process: [\n \"Identify affected modules.\",\n \"Confirm module memory is linked to feature delivery docs when the module is new or materially changed.\",\n \"Update module purpose, responsibilities, non-responsibilities, public interfaces, and boundaries when behavior changes.\",\n \"Update task status only when supported by completion evidence.\",\n \"Update test expectations when risks or behavior change.\",\n \"Record decisions or link ADRs when architecture changes.\",\n \"Avoid copying full feature docs into module docs.\",\n ],\n stopConditions: [\n \"Module ownership is unclear.\",\n \"A change crosses module boundaries without architecture review.\",\n \"Module memory updates would conflict with engineering standards.\",\n \"A decision belongs in an ADR instead of a module note.\",\n \"Feature delivery docs are missing for new module work.\",\n ],\n qualityBar: [\n \"Module docs are concise and current.\",\n \"Boundaries are clear.\",\n \"Test expectations are actionable.\",\n \"Decisions link to ADRs where appropriate.\",\n \"Future agents can tell what the module owns and what it must not own.\",\n ],\n },\n {\n name: \"completion-report\",\n title: \"Completion Report\",\n description:\n \"Write a completion report with files changed, tests run, results, skipped checks, docs updated, remaining risks, and release readiness notes. Use when recording evidence that a task or feature is complete and ready for review.\",\n purpose: [\"Record evidence that a task is complete and safe to review.\"],\n inputs: [\n \"Task or feature summary.\",\n \"Files changed.\",\n \"Commands run.\",\n \"Test results.\",\n \"Docs updated.\",\n \"Known risks.\",\n ],\n requiredReading: [\n \"`docs/50-quality/QUALITY_GATES.md`\",\n \"`docs/60-engineering/ENGINEERING_STANDARDS.md`\",\n \"Relevant feature `TASKS.md`\",\n \"Relevant feature `TEST_PLAN.md`\",\n \"Relevant feature `REVIEW.md`\",\n ],\n outputFiles: [\n \"Relevant feature `COMPLETION_REPORT.md`\",\n \"Task or feature docs that need final status updates.\",\n ],\n process: [\n \"Summarize the completed scope.\",\n \"List files changed by category.\",\n \"List commands run and results.\",\n \"List skipped checks and why.\",\n \"List docs updated.\",\n \"State whether engineering standards were followed.\",\n \"List remaining risks and follow-up work.\",\n \"State whether the task meets the definition of done.\",\n ],\n stopConditions: [\n \"Test results are missing for risky changes.\",\n \"Completion claims conflict with evidence.\",\n \"Required docs were not updated.\",\n \"Engineering standards were violated.\",\n \"Remaining risks are release blockers.\",\n ],\n qualityBar: [\n \"The report is evidence-based.\",\n \"It does not hide skipped checks.\",\n \"It separates completed work from remaining risk.\",\n \"A reviewer can decide what to do next from the report alone.\",\n ],\n },\n {\n name: \"capture-mcp-context\",\n title: \"Capture MCP Context\",\n description:\n \"Record durable context from MCP servers and design or project tools into repository memory as proposed. Use when working with an MCP server like Figma, Linear, Jira, or Sentry, or after pulling design, ticket, or error context, to persist it for future sessions.\",\n purpose: [\n \"Persist the durable parts of MCP-derived external context so future sessions remember them instead of re-deriving them.\",\n \"MCP provides context, not architectural truth.\",\n ],\n inputs: [\n \"The MCP server or external tool in use (for example Figma, Linear, Jira, Sentry).\",\n \"The external context retrieved (design tokens, tickets, errors, docs).\",\n \"The current feature or task.\",\n ],\n requiredReading: [\n \"`docs/ai/MCP_STRATEGY.md`\",\n \"Relevant `docs/ai/mcp/<server>.md`\",\n \"Relevant feature and architecture docs.\",\n ],\n outputFiles: [\n \"The Captured Context section of `docs/ai/mcp/<server>.md`.\",\n \"An ADR via `recall adr create` when a captured decision is accepted.\",\n ],\n process: [\n \"Identify the MCP server and the durable facts worth remembering (design tokens, component mappings, ticket acceptance criteria, recurring error signatures).\",\n \"If `docs/ai/mcp/<server>.md` does not exist, create it with `recall mcp add <server>`.\",\n \"Record the durable context in the Captured Context section as proposed memory, with enough detail to reuse.\",\n \"Capture decisions, mappings, and constraints, not raw exports or full dumps.\",\n \"Treat MCP content as context, not truth; if it conflicts with accepted memory, stop and report.\",\n \"Promote any accepted decision into an ADR.\",\n ],\n stopConditions: [\n \"MCP content conflicts with accepted repository memory.\",\n \"Capturing the context would require storing secrets or sensitive data.\",\n \"The MCP server is untrusted or its access is unclear.\",\n ],\n qualityBar: [\n \"Captured context is durable and reusable, not a raw dump.\",\n \"Each entry is concrete enough to guide future work.\",\n \"MCP context is recorded as proposed, not accepted.\",\n \"Accepted decisions are promoted to ADRs.\",\n ],\n },\n];\n\nexport function getCatalogSkill(name: string): SkillDefinition | undefined {\n return SKILL_CATALOG.find((skill) => skill.name === name);\n}\n\nexport function listCatalogSkillNames(): string[] {\n return SKILL_CATALOG.map((skill) => skill.name);\n}\n","import type { WriteFileInput } from \"../filesystem/write-plan.js\";\nimport { renderSkill } from \"./render-skill.js\";\nimport { getCatalogSkill, type SkillDefinition } from \"./skill-catalog.js\";\n\n/**\n * Skills are emitted to both the Claude Code target and the portable Agent Skills target so the same\n * SKILL.md is available across tools.\n */\nexport const SKILL_TARGETS = [\".claude/skills\", \".agents/skills\"] as const;\n\nexport type GenerateSkillResult = {\n files: WriteFileInput[];\n fromCatalog: boolean;\n};\n\nexport function generateSkillFiles(name: string): GenerateSkillResult {\n const catalogSkill = getCatalogSkill(name);\n const skill = catalogSkill ?? skeletonSkill(name);\n const content = renderSkill(skill);\n\n return {\n files: SKILL_TARGETS.map((target) => ({\n path: `${target}/${name}/SKILL.md`,\n content,\n })),\n fromCatalog: catalogSkill !== undefined,\n };\n}\n\nfunction skeletonSkill(name: string): SkillDefinition {\n return {\n name,\n title: titleize(name),\n description: `Describe what the ${name} skill does and when to use it. Use when ... (replace this with concrete trigger keywords).`,\n purpose: [\"Describe the single job this skill performs.\"],\n inputs: [\"List the inputs this skill needs.\"],\n requiredReading: [\"List the source-of-truth docs this skill must read.\"],\n outputFiles: [\"List the files this skill produces or updates.\"],\n process: [\"Describe the steps, one job, routing to source-of-truth docs.\"],\n stopConditions: [\n \"A request conflicts with accepted repository memory or engineering standards.\",\n \"The work would add network, telemetry, MCP runtime, AI API, or other accepted non-goals.\",\n ],\n qualityBar: [\"State how to tell the skill did its job well.\"],\n };\n}\n\nfunction titleize(name: string): string {\n return name\n .split(\"-\")\n .filter((part) => part.length > 0)\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(\" \");\n}\n","export type KnownServer = {\n title: string;\n purpose: string;\n dataAccessed: string[];\n};\n\n/**\n * Purpose and data hints for well-known MCP servers, drawn from the MCP strategy guidance. Used to\n * pre-fill generated MCP memory. Recall OS never connects to these servers; this is static guidance.\n */\nconst KNOWN_SERVERS: Record<string, KnownServer> = {\n figma: {\n title: \"Figma\",\n purpose: \"Design variables, components, and layout metadata for building consistent UI.\",\n dataAccessed: [\n \"Design tokens and variables.\",\n \"Component and layout metadata.\",\n \"Frames and styles.\",\n ],\n },\n linear: {\n title: \"Linear\",\n purpose: \"Tickets, project status, and acceptance criteria.\",\n dataAccessed: [\n \"Issues and tickets.\",\n \"Project and cycle status.\",\n \"Acceptance criteria in issues.\",\n ],\n },\n jira: {\n title: \"Jira\",\n purpose: \"Tickets, sprints, and acceptance criteria for knocking out tasks.\",\n dataAccessed: [\n \"Issues and tickets.\",\n \"Sprint and board status.\",\n \"Acceptance criteria in issues.\",\n ],\n },\n github: {\n title: \"GitHub\",\n purpose: \"Pull requests, issues, and review comments.\",\n dataAccessed: [\"Pull requests and diffs.\", \"Issues.\", \"Review comments.\"],\n },\n sentry: {\n title: \"Sentry\",\n purpose: \"Crash reports and production errors.\",\n dataAccessed: [\"Error events and stack traces.\", \"Release health.\", \"Issue frequency.\"],\n },\n notion: {\n title: \"Notion\",\n purpose: \"Product background and documentation.\",\n dataAccessed: [\"Product docs and pages.\", \"Project background.\", \"Specifications.\"],\n },\n};\n\nexport function getKnownServer(id: string): KnownServer | undefined {\n return KNOWN_SERVERS[id];\n}\n","import type { WriteFileInput } from \"../filesystem/write-plan.js\";\nimport { getKnownServer } from \"./known-servers.js\";\n\nexport type GenerateMcpOptions = {\n adrDir: string;\n server: string;\n};\n\nexport function mcpDocPath(server: string): string {\n return `docs/ai/mcp/${server}.md`;\n}\n\nexport function generateMcpFiles(options: GenerateMcpOptions): WriteFileInput[] {\n const known = getKnownServer(options.server);\n const title = known?.title ?? titleize(options.server);\n const purpose = known?.purpose ?? \"Describe why this MCP server is used.\";\n const dataAccessed = known?.dataAccessed ?? [\"Describe the data this MCP server exposes.\"];\n\n return [\n {\n path: mcpDocPath(options.server),\n content: renderMcpDoc(title, purpose, dataAccessed),\n },\n {\n path: `${options.adrDir}/proposed/ADR-PROPOSED-mcp-${options.server}.md`,\n content: renderProposedAdr(title, options.server),\n },\n ];\n}\n\nfunction renderMcpDoc(title: string, purpose: string, dataAccessed: string[]): string {\n return `# MCP: ${title}\n\n## Status\n\nProposed. Using this MCP server is a proposed workflow addition. Accept the proposed ADR before\ntreating it as part of the workflow.\n\n## Purpose\n\n${purpose}\n\n## Data Accessed\n\n${bullets(dataAccessed)}\n\n## Permissions Required\n\n- Use least-privilege access.\n- Document the exact scopes granted.\n\n## Security Risks\n\n- Treat external MCP content as untrusted until validated.\n- Do not send secrets or sensitive repository data unnecessarily.\n- Use trusted MCP servers only.\n\n## Source-Of-Truth Rule\n\nMCP provides context, not architectural truth. Accepted ADRs and repository decisions outrank MCP\ncontext. If MCP data conflicts with repository memory, stop and report the conflict.\n\n## Captured Context\n\nRecord durable context learned from this MCP server here, as proposed memory for human review.\nPromote any decision you accept into an ADR with \\`recall adr create\\`.\n\n- (none captured yet)\n\n## Review Cadence\n\n- Review this MCP integration when its access, purpose, or captured context changes.\n`;\n}\n\nfunction renderProposedAdr(title: string, server: string): string {\n return `# Proposed ADR: Use ${title} MCP\n\n## Status\n\nProposed\n\n## Context\n\nThe team is considering ${title} as an MCP context source. Adopting an MCP server into the workflow\nis a decision that should be reviewed.\n\n## Decision\n\nConsider adopting ${title} MCP as an external context source, documented in \\`docs/ai/mcp/\\`. This is\nnot accepted until a human reviews and accepts it.\n\n## Alternatives Considered\n\n- Do not use this MCP server.\n- Use a different source for the same context.\n\n## Consequences\n\n- The team gains durable, reviewable context from ${title}.\n- MCP context never overrides accepted repository memory.\n- Captured context remains proposed until promoted to an ADR.\n\n## Related Documents\n\n- \\`docs/ai/mcp/${server}.md\\` — captured ${title} MCP context.\n- \\`docs/ai/MCP_STRATEGY.md\\` — how MCP context is captured and ranked.\n`;\n}\n\nfunction bullets(values: string[]): string {\n return values.map((value) => `- ${value}`).join(\"\\n\");\n}\n\nfunction titleize(value: string): string {\n return value\n .split(\"-\")\n .filter((part) => part.length > 0)\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(\" \");\n}\n","import { createDefaultConfig } from \"../../core/config/default-config.js\";\nimport { ConfigValidationError } from \"../../core/config/config-schema.js\";\nimport { loadConfig, ConfigLoadError } from \"../../core/config/load-config.js\";\nimport { generateMcpFiles, mcpDocPath } from \"../../core/mcp/generate-mcp.js\";\nimport { generateSkillFiles } from \"../../core/skills/generate-skill.js\";\nimport { createWritePlan, type WritePlan } from \"../../core/filesystem/write-plan.js\";\nimport { executeWritePlan, type WriteResult } from \"../../core/filesystem/write-file-safe.js\";\nimport { SlugifyError, slugify } from \"../../core/naming/slugify.js\";\nimport { appendNextSteps, appendWriteSummary } from \"../write-summary.js\";\n\nexport type McpAddOptions = {\n rootDir: string;\n server: string;\n dryRun?: boolean;\n force?: boolean;\n};\n\nexport type McpAddResult = {\n server: string;\n docPath: string;\n dryRun: boolean;\n plan: WritePlan;\n writeResult: WriteResult;\n};\n\nexport type McpAddErrorCode = \"INVALID_SERVER_NAME\" | \"WRITE_PLAN_ERROR\";\n\nexport class McpAddError extends Error {\n readonly code: McpAddErrorCode;\n readonly details: string[];\n\n constructor(code: McpAddErrorCode, message: string, details: string[] = []) {\n super(message);\n this.name = \"McpAddError\";\n this.code = code;\n this.details = details;\n }\n}\n\nexport async function mcpAdd(options: McpAddOptions): Promise<McpAddResult> {\n const server = createServerSlug(options.server);\n const config = await loadConfigOrDefault(options.rootDir);\n // The memory doc and adoption ADR, plus the capture skill that tells agents to record durable\n // MCP-derived context into that doc. The skill is shared across servers and skipped if it exists.\n const files = [\n ...generateMcpFiles({ adrDir: config.adrDir, server }),\n ...generateSkillFiles(\"capture-mcp-context\").files,\n ];\n const plan = createWritePlan({\n rootDir: options.rootDir,\n files,\n force: options.force,\n });\n\n if (plan.hasErrors) {\n throw new McpAddError(\n \"WRITE_PLAN_ERROR\",\n \"Recall OS mcp add write plan contains errors.\",\n plan.entries\n .filter((entry) => entry.action === \"error\")\n .map((entry) => `${entry.path}: ${entry.reason}`),\n );\n }\n\n const writeResult = await executeWritePlan(plan, { dryRun: options.dryRun });\n\n return {\n server,\n docPath: mcpDocPath(server),\n dryRun: options.dryRun ?? false,\n plan,\n writeResult,\n };\n}\n\nexport function formatMcpAddResult(result: McpAddResult): string {\n const lines = [\n result.dryRun ? \"Recall OS mcp add dry run complete.\" : \"Recall OS mcp add complete.\",\n `MCP memory: ${result.docPath} (proposed — review before adopting)`,\n \"Capture skill installed so agents record durable MCP context into this memory.\",\n ];\n\n appendWriteSummary(lines, {\n dryRun: result.dryRun,\n writeResult: result.writeResult,\n });\n\n if (!result.dryRun) {\n appendNextSteps(lines, [\n `Open ${result.docPath} and confirm purpose, data accessed, and permissions.`,\n \"Your agent records durable context into the Captured Context section via the capture-mcp-context skill.\",\n \"Accept the proposed ADR once you adopt the server.\",\n ]);\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction createServerSlug(server: string): string {\n try {\n return slugify(server);\n } catch (error) {\n if (error instanceof SlugifyError) {\n throw new McpAddError(\"INVALID_SERVER_NAME\", error.message);\n }\n\n throw error;\n }\n}\n\nasync function loadConfigOrDefault(rootDir: string) {\n try {\n return await loadConfig(rootDir);\n } catch (error) {\n if (error instanceof ConfigLoadError || error instanceof ConfigValidationError) {\n return createDefaultConfig();\n }\n\n throw error;\n }\n}\n","import path from \"node:path\";\n\nimport type { WriteFileInput } from \"../filesystem/write-plan.js\";\nimport { slugify } from \"../naming/slugify.js\";\nimport { createTemplateContext } from \"./template-context.js\";\nimport { renderTemplate } from \"./render-template.js\";\n\nexport type GenerateModuleFilesOptions = {\n modulesDir: string;\n moduleName: string;\n};\n\ntype ModuleTemplate = {\n fileName: string;\n content: string;\n};\n\nconst moduleTemplates: ModuleTemplate[] = [\n {\n fileName: \"MODULE.md\",\n content: `# Module: {{title}}\n\n## Purpose\n\nDescribe what this module owns and why it exists.\n\n## Owns\n\n- TBD\n\n## Does Not Own\n\n- TBD\n\n## Public Interfaces\n\n- TBD\n\n## Boundaries\n\nDescribe important dependencies, callers, and constraints.\n`,\n },\n {\n fileName: \"TASKS.md\",\n content: `# Module Tasks: {{title}}\n\n## Active Work\n\n- TBD\n\n## Tasks\n\n- Todo: Define module responsibilities.\n- Todo: Define tests.\n- Todo: Update decisions as behavior changes.\n`,\n },\n {\n fileName: \"TEST_PLAN.md\",\n content: `# Module Test Plan: {{title}}\n\n## Unit Tests\n\n- TBD\n\n## Integration Tests\n\n- TBD\n\n## Security Tests\n\n- TBD\n`,\n },\n {\n fileName: \"DECISIONS.md\",\n content: `# Module Decisions: {{title}}\n\nRecord durable module decisions here.\n\n## Current Decisions\n\n- TBD\n`,\n },\n];\n\nexport function generateModuleFiles(options: GenerateModuleFilesOptions): WriteFileInput[] {\n const slug = slugify(options.moduleName);\n const moduleDir = path.posix.join(options.modulesDir, slug);\n const title = titleizeModuleName(options.moduleName);\n const context = createTemplateContext({\n slug,\n title,\n });\n\n return moduleTemplates.map((template) => ({\n path: path.posix.join(moduleDir, template.fileName),\n content: renderTemplate(template.content, context),\n }));\n}\n\nfunction titleizeModuleName(moduleName: string): string {\n return moduleName\n .trim()\n .replace(/[-_]+/gu, \" \")\n .replace(/\\s+/gu, \" \")\n .replace(/\\b\\w/gu, (character) => character.toUpperCase());\n}\n","import { ConfigValidationError } from \"../../core/config/config-schema.js\";\nimport { loadConfig, ConfigLoadError } from \"../../core/config/load-config.js\";\nimport { createWritePlan, type WritePlan } from \"../../core/filesystem/write-plan.js\";\nimport { executeWritePlan, type WriteResult } from \"../../core/filesystem/write-file-safe.js\";\nimport { generateModuleFiles } from \"../../core/generator/generate-module.js\";\nimport { SlugifyError, slugify } from \"../../core/naming/slugify.js\";\nimport { appendNextSteps, appendWriteSummary } from \"../write-summary.js\";\n\nexport type ModuleCreateOptions = {\n rootDir: string;\n name: string;\n dryRun?: boolean;\n force?: boolean;\n};\n\nexport type ModuleCreateResult = {\n slug: string;\n modulePath: string;\n dryRun: boolean;\n plan: WritePlan;\n writeResult: WriteResult;\n};\n\nexport type ModuleCreateErrorCode = \"CONFIG_REQUIRED\" | \"INVALID_MODULE_NAME\" | \"WRITE_PLAN_ERROR\";\n\nexport class ModuleCreateError extends Error {\n readonly code: ModuleCreateErrorCode;\n readonly details: string[];\n\n constructor(code: ModuleCreateErrorCode, message: string, details: string[] = []) {\n super(message);\n this.name = \"ModuleCreateError\";\n this.code = code;\n this.details = details;\n }\n}\n\nexport async function createModule(options: ModuleCreateOptions): Promise<ModuleCreateResult> {\n const slug = createModuleSlug(options.name);\n const config = await loadRequiredConfig(options.rootDir);\n const files = generateModuleFiles({\n modulesDir: config.modulesDir,\n moduleName: options.name,\n });\n const plan = createWritePlan({\n rootDir: options.rootDir,\n files,\n force: options.force,\n });\n\n if (plan.hasErrors) {\n throw new ModuleCreateError(\n \"WRITE_PLAN_ERROR\",\n \"Module create write plan contains errors.\",\n plan.entries\n .filter((entry) => entry.action === \"error\")\n .map((entry) => `${entry.path}: ${entry.reason}`),\n );\n }\n\n const writeResult = await executeWritePlan(plan, { dryRun: options.dryRun });\n\n return {\n slug,\n modulePath: `${config.modulesDir}/${slug}`,\n dryRun: options.dryRun ?? false,\n plan,\n writeResult,\n };\n}\n\nexport function formatModuleCreateResult(result: ModuleCreateResult): string {\n const lines = [\n result.dryRun\n ? \"Recall OS module create dry run complete.\"\n : \"Recall OS module create complete.\",\n `Module: ${result.modulePath}`,\n ];\n\n appendWriteSummary(lines, {\n dryRun: result.dryRun,\n writeResult: result.writeResult,\n });\n\n if (!result.dryRun) {\n appendNextSteps(lines, [\n `Open ${result.modulePath}/MODULE.md and describe what this module owns and does not own.`,\n \"Record durable decisions in DECISIONS.md, or link an ADR.\",\n ]);\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction createModuleSlug(name: string): string {\n try {\n return slugify(name);\n } catch (error) {\n if (error instanceof SlugifyError) {\n throw new ModuleCreateError(\"INVALID_MODULE_NAME\", error.message);\n }\n\n throw error;\n }\n}\n\nasync function loadRequiredConfig(rootDir: string) {\n try {\n return await loadConfig(rootDir);\n } catch (error) {\n if (error instanceof ConfigLoadError || error instanceof ConfigValidationError) {\n throw new ModuleCreateError(\n \"CONFIG_REQUIRED\",\n \"Recall OS config not found or invalid. Run `recall init` first.\",\n [error.message],\n );\n }\n\n throw error;\n }\n}\n","import { listPresets } from \"../../core/presets/preset-registry.js\";\n\nexport type PresetListEntry = {\n id: string;\n name: string;\n description: string;\n};\n\nexport type PresetListResult = {\n presets: PresetListEntry[];\n};\n\nexport function listPresetEntries(): PresetListResult {\n return {\n presets: listPresets()\n .map((preset) => ({\n id: preset.id,\n name: preset.name,\n description: preset.description,\n }))\n .sort((left, right) => left.id.localeCompare(right.id)),\n };\n}\n\nexport function formatPresetListResult(result: PresetListResult): string {\n const lines = [\"Recall OS presets\", \"\"];\n\n for (const preset of result.presets) {\n lines.push(`- ${preset.id}: ${preset.name}`);\n lines.push(` ${preset.description}`);\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n","import { createWritePlan, type WritePlan } from \"../../core/filesystem/write-plan.js\";\nimport { executeWritePlan, type WriteResult } from \"../../core/filesystem/write-file-safe.js\";\nimport { generateSkillFiles } from \"../../core/skills/generate-skill.js\";\nimport { SlugifyError, slugify } from \"../../core/naming/slugify.js\";\nimport { appendNextSteps, appendWriteSummary } from \"../write-summary.js\";\n\nexport type SkillCreateOptions = {\n rootDir: string;\n name: string;\n dryRun?: boolean;\n force?: boolean;\n};\n\nexport type SkillCreateResult = {\n slug: string;\n fromCatalog: boolean;\n dryRun: boolean;\n plan: WritePlan;\n writeResult: WriteResult;\n};\n\nexport type SkillCreateErrorCode = \"INVALID_SKILL_NAME\" | \"WRITE_PLAN_ERROR\";\n\nexport class SkillCreateError extends Error {\n readonly code: SkillCreateErrorCode;\n readonly details: string[];\n\n constructor(code: SkillCreateErrorCode, message: string, details: string[] = []) {\n super(message);\n this.name = \"SkillCreateError\";\n this.code = code;\n this.details = details;\n }\n}\n\nexport async function createSkill(options: SkillCreateOptions): Promise<SkillCreateResult> {\n const slug = createSkillSlug(options.name);\n const { files, fromCatalog } = generateSkillFiles(slug);\n const plan = createWritePlan({\n rootDir: options.rootDir,\n files,\n force: options.force,\n });\n\n if (plan.hasErrors) {\n throw new SkillCreateError(\n \"WRITE_PLAN_ERROR\",\n \"Recall OS skill create write plan contains errors.\",\n plan.entries\n .filter((entry) => entry.action === \"error\")\n .map((entry) => `${entry.path}: ${entry.reason}`),\n );\n }\n\n const writeResult = await executeWritePlan(plan, { dryRun: options.dryRun });\n\n return {\n slug,\n fromCatalog,\n dryRun: options.dryRun ?? false,\n plan,\n writeResult,\n };\n}\n\nexport function formatSkillCreateResult(result: SkillCreateResult): string {\n const lines = [\n result.dryRun ? \"Recall OS skill create dry run complete.\" : \"Recall OS skill create complete.\",\n `Skill: ${result.slug}${result.fromCatalog ? \" (from catalog)\" : \" (skeleton — fill it in)\"}`,\n ];\n\n appendWriteSummary(lines, {\n dryRun: result.dryRun,\n writeResult: result.writeResult,\n });\n\n if (!result.dryRun) {\n appendNextSteps(\n lines,\n result.fromCatalog\n ? [\n `The skill is ready in .claude/skills/${result.slug}/ and .agents/skills/${result.slug}/.`,\n \"Restart your AI tool to load it; the agent triggers it from the description.\",\n ]\n : [\n `Open .claude/skills/${result.slug}/SKILL.md and fill the description, process, and quality bar.`,\n \"Keep the same content in .agents/skills/ for portability.\",\n ],\n );\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction createSkillSlug(name: string): string {\n try {\n return slugify(name);\n } catch (error) {\n if (error instanceof SlugifyError) {\n throw new SkillCreateError(\"INVALID_SKILL_NAME\", error.message);\n }\n\n throw error;\n }\n}\n","import { SKILL_CATALOG } from \"../../core/skills/skill-catalog.js\";\n\nexport function formatSkillListResult(): string {\n const lines = [\"Recall OS skill catalog\", \"\"];\n\n for (const skill of SKILL_CATALOG) {\n lines.push(`- ${skill.name}: ${skill.title}`);\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n"],"mappings":"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","names":["existsSync","readFile","readdir","path","path","path","CONTROL_CHARS","existsSync","numbered","readFile","readdir","path","path","TEMPLATE_KEY_PATTERN","RESERVED_TEMPLATE_KEYS","path","loadRequiredConfig","readFile","readdir","path","createSlug","loadRequiredConfig","write","escapeRegExp","readdir","readFile","path","path","path","readdir","readdir","loadRequiredConfig","existsSync","readFile","readdir","path","formatList","existsSync","readFile","readdir","path","readFile","readFile","readFile","readdir","path","featureFolderPattern","readDirIfExists","readFileIfExists","readFile","readdir","path","readDirIfExists","getSection","lstat","readFile","readdir","path","featureFolderPattern","adrFilePattern","readDirIfExists","path","readFile","readdir","lstat","lstat","path","isFile","lstat","readFile","readdir","path","featureFolderPattern","adrFilePattern","readDirIfExists","readFileIfExists","sectionContains","getSection","isFile","readFile","readdir","path","adrFilePattern","adrReferencePattern","checkReferences","readMarkdownFiles","stripCode","readDirIfExists","existsSync","path","path","path","existsSync","readFile","path","detectPackageManager","guidance","proposedAdr","guidance","proposedAdr","guidance","proposedAdr","z","PRESET_ID_PATTERN","z","presetSchema","path","existsSync","path","titleize","renderProposedAdr","bullets","loadConfigOrDefault","path","path","loadRequiredConfig"]}
1
+ {"version":3,"sources":["../src/cli/main.ts","../src/commands/adr/accept.ts","../src/core/config/config-schema.ts","../src/core/filesystem/safe-path.ts","../src/core/config/load-config.ts","../src/core/filesystem/write-plan.ts","../src/core/filesystem/conflict-policy.ts","../src/core/filesystem/write-file-safe.ts","../src/core/naming/adr-number.ts","../src/core/naming/slugify.ts","../src/commands/write-summary.ts","../src/core/generator/generate-adr.ts","../src/core/generator/template-context.ts","../src/core/generator/render-template.ts","../src/commands/adr/create.ts","../src/commands/adr/supersede.ts","../src/core/generator/generate-feature.ts","../src/core/naming/feature-number.ts","../src/commands/feature/create.ts","../src/core/config/default-config.ts","../src/core/adopt/inspect-repo.ts","../src/core/adopt/generate-adoption.ts","../src/commands/adopt.ts","../src/core/doctor/checks/code-reference-check.ts","../src/core/doctor/checks/config-check.ts","../src/core/doctor/checks/content-check.ts","../src/core/doctor/checks/drift-check.ts","../src/core/doctor/checks/memory-integrity-check.ts","../src/core/adr/adr-sections.ts","../src/core/doctor/checks/required-files-check.ts","../src/core/doctor/checks/standards-check.ts","../src/core/doctor/checks/superseded-check.ts","../src/core/doctor/doctor-check.ts","../src/core/doctor/doctor-report.ts","../src/commands/doctor.ts","../src/commands/init.ts","../src/core/generator/generate-init.ts","../src/core/hooks/detect-gates.ts","../src/core/hooks/generate-hook.ts","../src/presets/flutter/preset.ts","../src/presets/generic/preset.ts","../src/presets/ios-swift/preset.ts","../src/presets/kotlin-android/preset.ts","../src/presets/laravel/shared.ts","../src/presets/laravel-api/preset.ts","../src/presets/laravel-react/preset.ts","../src/presets/laravel-vue/preset.ts","../src/presets/nextjs/preset.ts","../src/presets/python-fastapi/preset.ts","../src/core/presets/preset-schema.ts","../src/core/presets/validate-preset.ts","../src/core/presets/preset-registry.ts","../src/core/skills/render-skill.ts","../src/core/skills/skill-catalog.ts","../src/core/skills/generate-skill.ts","../src/core/mcp/known-servers.ts","../src/core/mcp/generate-mcp.ts","../src/commands/mcp/add.ts","../src/core/generator/generate-module.ts","../src/commands/module/create.ts","../src/commands/preset/list.ts","../src/commands/skill/create.ts","../src/commands/skill/list.ts"],"sourcesContent":["import { Command, CommanderError } from \"commander\";\n\nimport { acceptAdr, AdrAcceptError, formatAdrAcceptResult } from \"../commands/adr/accept.js\";\nimport { createAdr, AdrCreateError, formatAdrCreateResult } from \"../commands/adr/create.js\";\nimport {\n supersedeAdr,\n AdrSupersedeError,\n formatAdrSupersedeResult,\n} from \"../commands/adr/supersede.js\";\nimport {\n createFeature,\n FeatureCreateError,\n formatFeatureCreateResult,\n} from \"../commands/feature/create.js\";\nimport { adoptProject, AdoptError, formatAdoptResult } from \"../commands/adopt.js\";\nimport { doctorProject, formatDoctorResult } from \"../commands/doctor.js\";\nimport { formatInitResult, initProject, InitError } from \"../commands/init.js\";\nimport { mcpAdd, McpAddError, formatMcpAddResult } from \"../commands/mcp/add.js\";\nimport {\n createModule,\n formatModuleCreateResult,\n ModuleCreateError,\n} from \"../commands/module/create.js\";\nimport { formatPresetListResult, listPresetEntries } from \"../commands/preset/list.js\";\nimport {\n createSkill,\n formatSkillCreateResult,\n SkillCreateError,\n} from \"../commands/skill/create.js\";\nimport { formatSkillListResult } from \"../commands/skill/list.js\";\n\nexport type CliWritable = {\n write(message: string): void;\n};\n\nexport type CliIo = {\n cwd?: string;\n stdout?: CliWritable;\n stderr?: CliWritable;\n};\n\nexport function createCliProgram(\n io: CliIo = {},\n state: { exitCode: number } = { exitCode: 0 },\n): Command {\n const stdout = io.stdout ?? process.stdout;\n const stderr = io.stderr ?? process.stderr;\n const cwd = io.cwd ?? process.cwd();\n const program = new Command();\n\n program\n .name(\"recall\")\n .description(\"Initialize and maintain repository memory for AI-assisted software work.\")\n .exitOverride()\n .configureOutput({\n writeOut: (message) => stdout.write(message),\n writeErr: (message) => stderr.write(message),\n });\n\n program\n .command(\"init\")\n .description(\"Initialize Recall OS repository memory.\")\n .option(\"--preset <id>\", \"Apply optional preset guidance and proposed decisions.\")\n .option(\"--dry-run\", \"Show planned writes without writing files.\")\n .option(\"--force\", \"Overwrite existing files explicitly.\")\n .option(\"--reinit\", \"Allow --force to overwrite an existing Recall OS installation.\")\n .action(\n async (options: { preset?: string; dryRun?: boolean; force?: boolean; reinit?: boolean }) => {\n const result = await initProject({\n rootDir: cwd,\n preset: options.preset,\n dryRun: options.dryRun,\n force: options.force,\n reinit: options.reinit,\n });\n\n stdout.write(formatInitResult(result));\n },\n );\n\n program\n .command(\"adopt\")\n .description(\"Inspect an existing repository and propose reviewable memory.\")\n .option(\"--dry-run\", \"Show planned writes without writing files.\")\n .option(\"--force\", \"Overwrite existing files explicitly.\")\n .action(async (options: { dryRun?: boolean; force?: boolean }) => {\n const result = await adoptProject({\n rootDir: cwd,\n dryRun: options.dryRun,\n force: options.force,\n });\n\n stdout.write(formatAdoptResult(result));\n });\n\n const featureCommand = program.command(\"feature\").description(\"Manage Recall OS feature memory.\");\n\n featureCommand\n .command(\"create\")\n .description(\"Create feature memory docs.\")\n .argument(\"<name>\", \"Feature name.\")\n .option(\"--dry-run\", \"Show planned writes without writing files.\")\n .option(\"--force\", \"Overwrite existing files explicitly.\")\n .action(async (name: string, options: { dryRun?: boolean; force?: boolean }) => {\n const result = await createFeature({\n rootDir: cwd,\n name,\n dryRun: options.dryRun,\n force: options.force,\n });\n\n stdout.write(formatFeatureCreateResult(result));\n });\n\n const adrCommand = program.command(\"adr\").description(\"Manage Recall OS ADR memory.\");\n\n adrCommand\n .command(\"create\")\n .description(\"Create a proposed ADR.\")\n .argument(\"<title>\", \"ADR title.\")\n .option(\"--dry-run\", \"Show planned writes without writing files.\")\n .option(\"--force\", \"Overwrite existing files explicitly.\")\n .action(async (title: string, options: { dryRun?: boolean; force?: boolean }) => {\n const result = await createAdr({\n rootDir: cwd,\n title,\n dryRun: options.dryRun,\n force: options.force,\n });\n\n stdout.write(formatAdrCreateResult(result));\n });\n\n adrCommand\n .command(\"accept\")\n .description(\"Promote a proposed ADR to accepted repository memory.\")\n .argument(\"<name>\", \"Proposed ADR name or slug, e.g. mcp-figma.\")\n .option(\"--dry-run\", \"Show planned writes without writing files.\")\n .option(\"--force\", \"Overwrite existing files explicitly.\")\n .action(async (name: string, options: { dryRun?: boolean; force?: boolean }) => {\n const result = await acceptAdr({\n rootDir: cwd,\n name,\n dryRun: options.dryRun,\n force: options.force,\n });\n\n stdout.write(formatAdrAcceptResult(result));\n });\n\n adrCommand\n .command(\"supersede\")\n .description(\n \"Record a changed decision: mark an accepted ADR superseded by a new accepted ADR.\",\n )\n .argument(\"<old>\", \"Accepted ADR name or slug being superseded, e.g. database-postgres.\")\n .argument(\"<new-title>\", \"Title of the new decision that replaces it.\")\n .option(\"--dry-run\", \"Show planned writes without writing files.\")\n .option(\"--force\", \"Overwrite existing files explicitly.\")\n .action(\n async (oldName: string, newTitle: string, options: { dryRun?: boolean; force?: boolean }) => {\n const result = await supersedeAdr({\n rootDir: cwd,\n oldName,\n newTitle,\n dryRun: options.dryRun,\n force: options.force,\n });\n\n stdout.write(formatAdrSupersedeResult(result));\n },\n );\n\n const moduleCommand = program.command(\"module\").description(\"Manage Recall OS module memory.\");\n\n moduleCommand\n .command(\"create\")\n .description(\"Create module memory docs.\")\n .argument(\"<name>\", \"Module name.\")\n .option(\"--dry-run\", \"Show planned writes without writing files.\")\n .option(\"--force\", \"Overwrite existing files explicitly.\")\n .action(async (name: string, options: { dryRun?: boolean; force?: boolean }) => {\n const result = await createModule({\n rootDir: cwd,\n name,\n dryRun: options.dryRun,\n force: options.force,\n });\n\n stdout.write(formatModuleCreateResult(result));\n });\n\n program\n .command(\"doctor\")\n .description(\"Check whether Recall OS repository memory is healthy.\")\n .action(async () => {\n const result = await doctorProject({ rootDir: cwd });\n\n stdout.write(formatDoctorResult(result));\n state.exitCode = result.exitCode;\n });\n\n const mcpCommand = program.command(\"mcp\").description(\"Manage Recall OS MCP context memory.\");\n\n mcpCommand\n .command(\"add\")\n .description(\"Generate proposed, offline memory for an MCP server.\")\n .argument(\"<server>\", \"MCP server name, e.g. figma.\")\n .option(\"--dry-run\", \"Show planned writes without writing files.\")\n .option(\"--force\", \"Overwrite existing files explicitly.\")\n .action(async (server: string, options: { dryRun?: boolean; force?: boolean }) => {\n const result = await mcpAdd({\n rootDir: cwd,\n server,\n dryRun: options.dryRun,\n force: options.force,\n });\n\n stdout.write(formatMcpAddResult(result));\n });\n\n const skillCommand = program.command(\"skill\").description(\"Manage Recall OS agent skills.\");\n\n skillCommand\n .command(\"create\")\n .description(\"Generate an agent skill for Claude Code and the portable Agent Skills target.\")\n .argument(\"<name>\", \"Skill name.\")\n .option(\"--dry-run\", \"Show planned writes without writing files.\")\n .option(\"--force\", \"Overwrite existing files explicitly.\")\n .action(async (name: string, options: { dryRun?: boolean; force?: boolean }) => {\n const result = await createSkill({\n rootDir: cwd,\n name,\n dryRun: options.dryRun,\n force: options.force,\n });\n\n stdout.write(formatSkillCreateResult(result));\n });\n\n skillCommand\n .command(\"list\")\n .description(\"List built-in catalog skills.\")\n .action(() => {\n stdout.write(formatSkillListResult());\n });\n\n const presetCommand = program.command(\"preset\").description(\"Inspect Recall OS presets.\");\n\n presetCommand\n .command(\"list\")\n .description(\"List built-in presets.\")\n .action(() => {\n stdout.write(formatPresetListResult(listPresetEntries()));\n });\n\n return program;\n}\n\nexport async function main(\n argv: string[] = process.argv.slice(2),\n io: CliIo = {},\n): Promise<number> {\n const stderr = io.stderr ?? process.stderr;\n const state = { exitCode: 0 };\n const program = createCliProgram(io, state);\n\n try {\n await program.parseAsync(argv, { from: \"user\" });\n return state.exitCode;\n } catch (error) {\n if (error instanceof InitError) {\n stderr.write(`${error.message}\\n`);\n for (const detail of error.details) {\n stderr.write(`- ${detail}\\n`);\n }\n return 1;\n }\n\n if (error instanceof FeatureCreateError) {\n stderr.write(`${error.message}\\n`);\n for (const detail of error.details) {\n stderr.write(`- ${detail}\\n`);\n }\n return 1;\n }\n\n if (error instanceof AdoptError) {\n stderr.write(`${error.message}\\n`);\n for (const detail of error.details) {\n stderr.write(`- ${detail}\\n`);\n }\n return 1;\n }\n\n if (error instanceof AdrCreateError) {\n stderr.write(`${error.message}\\n`);\n for (const detail of error.details) {\n stderr.write(`- ${detail}\\n`);\n }\n return 1;\n }\n\n if (error instanceof AdrAcceptError) {\n stderr.write(`${error.message}\\n`);\n for (const detail of error.details) {\n stderr.write(`- ${detail}\\n`);\n }\n return 1;\n }\n\n if (error instanceof AdrSupersedeError) {\n stderr.write(`${error.message}\\n`);\n for (const detail of error.details) {\n stderr.write(`- ${detail}\\n`);\n }\n return 1;\n }\n\n if (error instanceof ModuleCreateError) {\n stderr.write(`${error.message}\\n`);\n for (const detail of error.details) {\n stderr.write(`- ${detail}\\n`);\n }\n return 1;\n }\n\n if (error instanceof SkillCreateError) {\n stderr.write(`${error.message}\\n`);\n for (const detail of error.details) {\n stderr.write(`- ${detail}\\n`);\n }\n return 1;\n }\n\n if (error instanceof McpAddError) {\n stderr.write(`${error.message}\\n`);\n for (const detail of error.details) {\n stderr.write(`- ${detail}\\n`);\n }\n return 1;\n }\n\n if (error instanceof CommanderError) {\n return error.exitCode;\n }\n\n stderr.write(error instanceof Error ? `${error.message}\\n` : \"Unknown error.\\n\");\n return 1;\n }\n}\n","import { existsSync } from \"node:fs\";\nimport { readFile, readdir, rm } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { ConfigValidationError } from \"../../core/config/config-schema.js\";\nimport { loadConfig, ConfigLoadError } from \"../../core/config/load-config.js\";\nimport { resolveSafePath } from \"../../core/filesystem/safe-path.js\";\nimport { createWritePlan, type WritePlan } from \"../../core/filesystem/write-plan.js\";\nimport { executeWritePlan, type WriteResult } from \"../../core/filesystem/write-file-safe.js\";\nimport { getNextAdrNumber } from \"../../core/naming/adr-number.js\";\nimport { SlugifyError, slugify } from \"../../core/naming/slugify.js\";\nimport { appendNextSteps, appendWriteSummary } from \"../write-summary.js\";\n\nexport type AdrAcceptOptions = {\n rootDir: string;\n name: string;\n dryRun?: boolean;\n force?: boolean;\n};\n\nexport type AdrAcceptResult = {\n slug: string;\n acceptedPath: string;\n source: \"proposed\" | \"in-place\";\n proposedRemoved: string | null;\n dryRun: boolean;\n writeResult: WriteResult;\n};\n\nexport type AdrAcceptErrorCode =\n | \"CONFIG_REQUIRED\"\n | \"INVALID_ADR_NAME\"\n | \"NOT_FOUND\"\n | \"WRITE_PLAN_ERROR\";\n\nexport class AdrAcceptError extends Error {\n readonly code: AdrAcceptErrorCode;\n readonly details: string[];\n\n constructor(code: AdrAcceptErrorCode, message: string, details: string[] = []) {\n super(message);\n this.name = \"AdrAcceptError\";\n this.code = code;\n this.details = details;\n }\n}\n\nexport async function acceptAdr(options: AdrAcceptOptions): Promise<AdrAcceptResult> {\n const slug = createSlug(options.name);\n const config = await loadRequiredConfig(options.rootDir);\n const adrDirAbsolute = resolveSafePath(options.rootDir, config.adrDir).absolutePath;\n\n const proposedRelative = `${config.adrDir}/proposed/ADR-PROPOSED-${slug}.md`;\n const proposedAbsolute = resolveSafePath(options.rootDir, proposedRelative).absolutePath;\n\n if (existsSync(proposedAbsolute)) {\n return promoteProposed(\n options,\n config.adrDir,\n adrDirAbsolute,\n proposedRelative,\n proposedAbsolute,\n slug,\n );\n }\n\n const numbered = await findNumberedAdr(adrDirAbsolute, slug);\n if (numbered !== null) {\n return acceptInPlace(options, config.adrDir, numbered);\n }\n\n throw new AdrAcceptError(\"NOT_FOUND\", `No proposed ADR found for \"${slug}\".`, [\n `Looked for ${proposedRelative} and a Proposed ADR matching the slug in ${config.adrDir}.`,\n ]);\n}\n\nasync function promoteProposed(\n options: AdrAcceptOptions,\n adrDir: string,\n adrDirAbsolute: string,\n proposedRelative: string,\n proposedAbsolute: string,\n slug: string,\n): Promise<AdrAcceptResult> {\n const content = await readFile(proposedAbsolute, \"utf8\");\n const next = await getNextAdrNumber(adrDirAbsolute);\n const acceptedRelative = `${adrDir}/${next.id}-${slug}.md`;\n const accepted = renderAccepted(content, next.id);\n\n const writeResult = await write(options, acceptedRelative, accepted);\n\n let proposedRemoved: string | null = null;\n if (!options.dryRun) {\n await rm(proposedAbsolute);\n proposedRemoved = proposedRelative;\n }\n\n return {\n slug,\n acceptedPath: acceptedRelative,\n source: \"proposed\",\n proposedRemoved,\n dryRun: options.dryRun ?? false,\n writeResult,\n };\n}\n\nasync function acceptInPlace(\n options: AdrAcceptOptions,\n adrDir: string,\n numbered: { fileName: string; content: string },\n): Promise<AdrAcceptResult> {\n const relativePath = `${adrDir}/${numbered.fileName}`;\n const accepted = renderAccepted(numbered.content, null);\n\n // The file already exists; promotion is an explicit accept, so overwrite it in place.\n const writeResult = await write({ ...options, force: true }, relativePath, accepted);\n\n return {\n slug: numbered.fileName,\n acceptedPath: relativePath,\n source: \"in-place\",\n proposedRemoved: null,\n dryRun: options.dryRun ?? false,\n writeResult,\n };\n}\n\nasync function write(\n options: AdrAcceptOptions,\n relativePath: string,\n content: string,\n): Promise<WriteResult> {\n const plan = createWritePlan({\n rootDir: options.rootDir,\n files: [{ path: relativePath, content }],\n force: options.force,\n });\n\n if (plan.hasErrors) {\n throw new AdrAcceptError(\n \"WRITE_PLAN_ERROR\",\n \"ADR accept write plan contains errors.\",\n plan.entries\n .filter(\n (entry): entry is Extract<WritePlan[\"entries\"][number], { action: \"error\" }> =>\n entry.action === \"error\",\n )\n .map((entry) => `${entry.path}: ${entry.reason}`),\n );\n }\n\n return executeWritePlan(plan, { dryRun: options.dryRun });\n}\n\nfunction renderAccepted(content: string, id: string | null): string {\n let out = content.replace(/(##\\s+Status\\r?\\n\\r?\\n)Proposed\\b/u, \"$1Accepted\");\n\n if (id !== null) {\n out = out.replace(/^# Proposed ADR: (.+)$/mu, `# ${id}: $1`);\n }\n\n return out;\n}\n\nasync function findNumberedAdr(\n adrDirAbsolute: string,\n slug: string,\n): Promise<{ fileName: string; content: string } | null> {\n const pattern = new RegExp(`^ADR-\\\\d{4,}-${escapeRegExp(slug)}\\\\.md$`, \"u\");\n\n let entries;\n try {\n entries = await readdir(adrDirAbsolute, { withFileTypes: true });\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return null;\n }\n throw error;\n }\n\n const match = entries.find((entry) => entry.isFile() && pattern.test(entry.name));\n if (match === undefined) {\n return null;\n }\n\n const content = await readFile(path.join(adrDirAbsolute, match.name), \"utf8\");\n if (!/(##\\s+Status\\r?\\n\\r?\\n)Proposed\\b/u.test(content)) {\n throw new AdrAcceptError(\"NOT_FOUND\", `ADR ${match.name} is not Proposed.`);\n }\n\n return { fileName: match.name, content };\n}\n\nexport function formatAdrAcceptResult(result: AdrAcceptResult): string {\n const lines = [\n result.dryRun ? \"Recall OS ADR accept dry run complete.\" : \"Recall OS ADR accept complete.\",\n `Accepted: ${result.acceptedPath}`,\n ];\n\n appendWriteSummary(lines, { dryRun: result.dryRun, writeResult: result.writeResult });\n\n if (result.proposedRemoved !== null) {\n lines.push(`Removed proposal: ${result.proposedRemoved}`);\n }\n\n if (!result.dryRun) {\n appendNextSteps(lines, [\n `${result.acceptedPath} is now Accepted and is repository source of truth.`,\n \"Drift checks now treat references to it as resolved.\",\n ]);\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction createSlug(name: string): string {\n const withoutPrefix = name.replace(/^ADR-PROPOSED-/iu, \"\");\n try {\n return slugify(withoutPrefix);\n } catch (error) {\n if (error instanceof SlugifyError) {\n throw new AdrAcceptError(\"INVALID_ADR_NAME\", error.message);\n }\n throw error;\n }\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/gu, \"\\\\$&\");\n}\n\nasync function loadRequiredConfig(rootDir: string) {\n try {\n return await loadConfig(rootDir);\n } catch (error) {\n if (error instanceof ConfigLoadError || error instanceof ConfigValidationError) {\n throw new AdrAcceptError(\n \"CONFIG_REQUIRED\",\n \"Recall OS config not found or invalid. Run `recall init` first.\",\n [error.message],\n );\n }\n throw error;\n }\n}\n","import { z } from \"zod\";\n\nimport type { ConflictPolicy } from \"../filesystem/conflict-policy.js\";\nimport { normalizeOutputPath } from \"../filesystem/safe-path.js\";\n\nconst PRESET_ID_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/u;\nconst VERSION_PATTERN = /^\\d+\\.\\d+\\.\\d+$/u;\n// Reject empty strings and any ASCII control characters (including newlines and tabs).\nconst PRE_COMMIT_GATE_PATTERN = /^[^\\u0000-\\u001f\\u007f]+$/u;\n\nexport const memoryProfileSchema = z.enum([\"lite\", \"standard\", \"strict\"]);\nexport const aiToolTargetSchema = z.enum([\"claude\", \"codex\", \"cursor\", \"generic\"]);\nexport const configWritePolicySchema = z.enum([\"skip-existing\", \"overwrite\"]);\n\nexport type MemoryProfile = z.infer<typeof memoryProfileSchema>;\nexport type AiToolTarget = z.infer<typeof aiToolTargetSchema>;\nexport type ConfigWritePolicy = Extract<ConflictPolicy, \"skip-existing\" | \"overwrite\">;\n\nexport class ConfigValidationError extends Error {\n readonly issues: string[];\n\n constructor(issues: string[]) {\n super(`Invalid Recall OS config: ${issues.join(\"; \")}`);\n this.name = \"ConfigValidationError\";\n this.issues = issues;\n }\n}\n\nconst versionSchema = z\n .string()\n .regex(VERSION_PATTERN, \"Version must use MAJOR.MINOR.PATCH format.\");\n\nconst presetSchema = z.union([\n z.null(),\n z\n .string()\n .min(1, \"Preset cannot be empty.\")\n .max(80, \"Preset cannot exceed 80 characters.\")\n .regex(PRESET_ID_PATTERN, \"Preset must use lowercase letters, numbers, and single hyphens.\"),\n]);\n\nconst preCommitGateSchema = z\n .string()\n .min(1, \"Pre-commit gate cannot be empty.\")\n .max(200, \"Pre-commit gate cannot exceed 200 characters.\")\n .regex(\n PRE_COMMIT_GATE_PATTERN,\n \"Pre-commit gate must be a single line without control characters.\",\n );\n\nconst safeRelativePathSchema = z.string().transform((value, context) => {\n try {\n return normalizeOutputPath(value);\n } catch (error) {\n context.addIssue({\n code: \"custom\",\n message: error instanceof Error ? error.message : \"Path is invalid.\",\n });\n return z.NEVER;\n }\n});\n\nexport const recallConfigSchema = z\n .object({\n version: versionSchema,\n templateVersion: versionSchema,\n preset: presetSchema,\n memoryProfile: memoryProfileSchema,\n mode: memoryProfileSchema,\n aiTools: z.array(aiToolTargetSchema).min(1, \"At least one AI tool is required.\"),\n docsDir: safeRelativePathSchema,\n featuresDir: safeRelativePathSchema,\n modulesDir: safeRelativePathSchema,\n adrDir: safeRelativePathSchema,\n writePolicy: configWritePolicySchema,\n preCommitGates: z.array(preCommitGateSchema).max(50, \"Too many pre-commit gates.\").default([]),\n })\n .strict()\n .superRefine((config, context) => {\n if (config.memoryProfile !== config.mode) {\n context.addIssue({\n code: \"custom\",\n path: [\"mode\"],\n message: \"Mode must match memoryProfile.\",\n });\n }\n\n const seenAiTools = new Set<AiToolTarget>();\n for (const aiTool of config.aiTools) {\n if (seenAiTools.has(aiTool)) {\n context.addIssue({\n code: \"custom\",\n path: [\"aiTools\"],\n message: `Duplicate AI tool \"${aiTool}\".`,\n });\n }\n seenAiTools.add(aiTool);\n }\n });\n\nexport type RecallConfig = z.infer<typeof recallConfigSchema>;\n\nexport function parseConfig(value: unknown): RecallConfig {\n const result = recallConfigSchema.safeParse(value);\n\n if (!result.success) {\n throw new ConfigValidationError(\n result.error.issues.map((issue) => {\n const path = issue.path.length > 0 ? `${issue.path.join(\".\")}: ` : \"\";\n return `${path}${issue.message}`;\n }),\n );\n }\n\n return result.data;\n}\n","import path from \"node:path\";\nimport { realpathSync } from \"node:fs\";\n\nconst CONTROL_CHARS = /[\\u0000-\\u001f\\u007f]/u;\n\nexport class SafePathError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"SafePathError\";\n }\n}\n\nexport type SafePath = {\n path: string;\n absolutePath: string;\n};\n\nexport function normalizeOutputPath(relativePath: string): string {\n if (relativePath.length === 0) {\n throw new SafePathError(\"Path cannot be empty.\");\n }\n\n if (CONTROL_CHARS.test(relativePath)) {\n throw new SafePathError(\"Path cannot contain null bytes or control characters.\");\n }\n\n if (relativePath.includes(\"\\\\\")) {\n throw new SafePathError(\"Path must use forward slashes.\");\n }\n\n if (path.posix.isAbsolute(relativePath) || path.win32.isAbsolute(relativePath)) {\n throw new SafePathError(\"Path must be relative.\");\n }\n\n const segments = relativePath.split(\"/\");\n\n if (segments.some((segment) => segment.length === 0)) {\n throw new SafePathError(\"Path cannot contain empty segments.\");\n }\n\n if (segments.some((segment) => segment === \"..\")) {\n throw new SafePathError(\"Path cannot contain path traversal.\");\n }\n\n const normalized = path.posix.normalize(relativePath);\n\n if (normalized === \".\" || normalized.startsWith(\"../\") || normalized === \"..\") {\n throw new SafePathError(\"Path cannot escape the project root.\");\n }\n\n return normalized;\n}\n\nexport function resolveSafePath(rootDir: string, relativePath: string): SafePath {\n const normalizedPath = normalizeOutputPath(relativePath);\n const absoluteRoot = realpathSync.native(rootDir);\n const absolutePath = path.resolve(absoluteRoot, normalizedPath);\n const relativeToRoot = path.relative(absoluteRoot, absolutePath);\n\n if (relativeToRoot === \"\" || relativeToRoot.startsWith(\"..\") || path.isAbsolute(relativeToRoot)) {\n throw new SafePathError(\"Resolved path must stay inside the project root.\");\n }\n\n return {\n path: normalizedPath,\n absolutePath,\n };\n}\n","import { readFile } from \"node:fs/promises\";\nimport { resolveSafePath } from \"../filesystem/safe-path.js\";\nimport { parseConfig, type RecallConfig } from \"./config-schema.js\";\n\nexport const CONFIG_PATH = \".recall/config.json\";\n\nexport class ConfigLoadError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ConfigLoadError\";\n }\n}\n\nexport async function loadConfig(rootDir: string): Promise<RecallConfig> {\n const configPath = resolveSafePath(rootDir, CONFIG_PATH);\n\n let rawConfig: string;\n try {\n rawConfig = await readFile(configPath.absolutePath, \"utf8\");\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n throw new ConfigLoadError(`Recall OS config not found at ${CONFIG_PATH}.`);\n }\n throw error;\n }\n\n let parsedJson: unknown;\n try {\n parsedJson = JSON.parse(rawConfig);\n } catch {\n throw new ConfigLoadError(`Recall OS config at ${CONFIG_PATH} is not valid JSON.`);\n }\n\n return parseConfig(parsedJson);\n}\n","import { existsSync } from \"node:fs\";\n\nimport type { ConflictPolicy } from \"./conflict-policy.js\";\nimport { shouldOverwriteExisting } from \"./conflict-policy.js\";\nimport { resolveSafePath } from \"./safe-path.js\";\n\nexport type WriteFileInput = {\n path: string;\n content: string;\n executable?: boolean;\n};\n\nexport type WritePlanCreateEntry = {\n action: \"create\";\n path: string;\n absolutePath: string;\n content: string;\n executable?: boolean;\n};\n\nexport type WritePlanSkipEntry = {\n action: \"skip\";\n path: string;\n absolutePath: string;\n reason: string;\n};\n\nexport type WritePlanOverwriteEntry = {\n action: \"overwrite\";\n path: string;\n absolutePath: string;\n content: string;\n executable?: boolean;\n};\n\nexport type WritePlanErrorEntry = {\n action: \"error\";\n path: string;\n reason: string;\n};\n\nexport type WritePlanEntry =\n | WritePlanCreateEntry\n | WritePlanSkipEntry\n | WritePlanOverwriteEntry\n | WritePlanErrorEntry;\n\nexport type WritePlan = {\n entries: WritePlanEntry[];\n hasErrors: boolean;\n};\n\nexport type CreateWritePlanOptions = {\n rootDir: string;\n files: WriteFileInput[];\n policy?: ConflictPolicy;\n force?: boolean;\n};\n\nexport function createWritePlan(options: CreateWritePlanOptions): WritePlan {\n const policy = options.policy ?? (options.force ? \"overwrite\" : \"skip-existing\");\n const seen = new Map<string, string>();\n const entries: WritePlanEntry[] = [];\n\n for (const file of options.files) {\n try {\n const safePath = resolveSafePath(options.rootDir, file.path);\n const existingPath = seen.get(safePath.path);\n\n if (existingPath !== undefined) {\n entries.push({\n action: \"error\",\n path: file.path,\n reason: `Duplicate output path \"${safePath.path}\" also used by \"${existingPath}\".`,\n });\n continue;\n }\n\n seen.set(safePath.path, file.path);\n\n if (existsSync(safePath.absolutePath)) {\n if (shouldOverwriteExisting(policy)) {\n entries.push({\n action: \"overwrite\",\n path: safePath.path,\n absolutePath: safePath.absolutePath,\n content: file.content,\n executable: file.executable,\n });\n } else {\n entries.push({\n action: \"skip\",\n path: safePath.path,\n absolutePath: safePath.absolutePath,\n reason: \"File already exists.\",\n });\n }\n continue;\n }\n\n entries.push({\n action: \"create\",\n path: safePath.path,\n absolutePath: safePath.absolutePath,\n content: file.content,\n executable: file.executable,\n });\n } catch (error) {\n entries.push({\n action: \"error\",\n path: file.path,\n reason: error instanceof Error ? error.message : \"Invalid output path.\",\n });\n }\n }\n\n return {\n entries,\n hasErrors: entries.some((entry) => entry.action === \"error\"),\n };\n}\n","export type ConflictPolicy = \"skip-existing\" | \"overwrite\";\n\nexport function shouldOverwriteExisting(policy: ConflictPolicy): boolean {\n return policy === \"overwrite\";\n}\n\nexport function resolveConflictPolicy(force = false): ConflictPolicy {\n return force ? \"overwrite\" : \"skip-existing\";\n}\n","import { chmod, mkdir, writeFile, lstat } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport type {\n WritePlan,\n WritePlanCreateEntry,\n WritePlanEntry,\n WritePlanOverwriteEntry,\n} from \"./write-plan.js\";\n\nexport type WriteResult = {\n created: string[];\n overwritten: string[];\n skipped: string[];\n dryRun: boolean;\n};\n\nexport class WriteSafetyError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"WriteSafetyError\";\n }\n}\n\nexport type ExecuteWritePlanOptions = {\n dryRun?: boolean;\n};\n\nexport async function executeWritePlan(\n plan: WritePlan,\n options: ExecuteWritePlanOptions = {},\n): Promise<WriteResult> {\n if (plan.hasErrors) {\n throw new WriteSafetyError(\"Refusing to execute a write plan with errors.\");\n }\n\n const result: WriteResult = {\n created: [],\n overwritten: [],\n skipped: [],\n dryRun: options.dryRun ?? false,\n };\n\n for (const entry of plan.entries) {\n if (entry.action === \"skip\") {\n result.skipped.push(entry.path);\n continue;\n }\n\n if (entry.action !== \"create\" && entry.action !== \"overwrite\") {\n continue;\n }\n\n if (result.dryRun) {\n if (entry.action === \"create\") {\n result.created.push(entry.path);\n } else {\n result.overwritten.push(entry.path);\n }\n continue;\n }\n\n await writeFileSafe(entry);\n\n if (entry.action === \"create\") {\n result.created.push(entry.path);\n } else {\n result.overwritten.push(entry.path);\n }\n }\n\n return result;\n}\n\nexport async function writeFileSafe(\n entry: WritePlanCreateEntry | WritePlanOverwriteEntry,\n): Promise<void> {\n await assertNoSymlinkInExistingPath(entry.absolutePath);\n await mkdir(path.dirname(entry.absolutePath), { recursive: true });\n await writeFile(entry.absolutePath, entry.content, {\n encoding: \"utf8\",\n flag: entry.action === \"create\" ? \"wx\" : \"w\",\n });\n\n if (entry.executable === true) {\n await chmod(entry.absolutePath, 0o755);\n }\n}\n\nasync function assertNoSymlinkInExistingPath(absolutePath: string): Promise<void> {\n const segments = path.resolve(absolutePath).split(path.sep);\n let current = segments[0] === \"\" ? path.sep : segments[0];\n const startIndex = segments[0] === \"\" ? 1 : 1;\n\n for (let index = startIndex; index < segments.length; index += 1) {\n current =\n current === path.sep\n ? path.join(current, segments[index] ?? \"\")\n : path.join(current, segments[index] ?? \"\");\n\n try {\n const stats = await lstat(current);\n if (stats.isSymbolicLink()) {\n throw new WriteSafetyError(`Refusing to write through symlink: ${current}`);\n }\n } catch (error) {\n if (error instanceof WriteSafetyError) {\n throw error;\n }\n\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return;\n }\n\n throw error;\n }\n }\n}\n\nexport function assertExecutableEntry(\n entry: WritePlanEntry,\n): asserts entry is WritePlanCreateEntry | WritePlanOverwriteEntry {\n if (entry.action !== \"create\" && entry.action !== \"overwrite\") {\n throw new WriteSafetyError(`Entry action \"${entry.action}\" is not executable.`);\n }\n}\n","import { readdir } from \"node:fs/promises\";\n\nconst ADR_FILE_PATTERN = /^ADR-(\\d{4,})-([a-z0-9]+(?:-[a-z0-9]+)*)\\.md$/u;\n\nexport type AdrNumber = {\n number: number;\n id: string;\n};\n\nexport type AdrFile = AdrNumber & {\n slug: string;\n fileName: string;\n};\n\nexport async function getNextAdrNumber(adrDirAbsolutePath: string): Promise<AdrNumber> {\n const existingFiles = await readExistingAdrFiles(adrDirAbsolutePath);\n return getNextAdrNumberFromFiles(existingFiles);\n}\n\nexport async function getAdrFileForSlug(\n adrDirAbsolutePath: string,\n slug: string,\n): Promise<AdrFile> {\n const existingFiles = await readExistingAdrFiles(adrDirAbsolutePath);\n const existingFile = existingFiles\n .filter((file) => file.slug === slug)\n .sort((left, right) => left.number - right.number)[0];\n\n if (existingFile !== undefined) {\n return existingFile;\n }\n\n const nextAdrNumber = getNextAdrNumberFromFiles(existingFiles);\n\n return {\n ...nextAdrNumber,\n slug,\n fileName: `${nextAdrNumber.id}-${slug}.md`,\n };\n}\n\nfunction getNextAdrNumberFromFiles(existingFiles: AdrFile[]): AdrNumber {\n const existingNumbers = existingFiles.map((file) => file.number);\n const highestNumber = existingNumbers.length === 0 ? 0 : Math.max(...existingNumbers);\n const nextNumber = highestNumber + 1;\n\n return {\n number: nextNumber,\n id: formatAdrNumber(nextNumber),\n };\n}\n\nexport function formatAdrNumber(adrNumber: number): string {\n if (!Number.isInteger(adrNumber) || adrNumber < 1) {\n throw new Error(\"ADR number must be a positive integer.\");\n }\n\n return `ADR-${String(adrNumber).padStart(4, \"0\")}`;\n}\n\nexport function parseAdrNumber(fileName: string): number | null {\n const match = ADR_FILE_PATTERN.exec(fileName);\n\n if (match === null) {\n return null;\n }\n\n return Number.parseInt(match[1] ?? \"\", 10);\n}\n\nasync function readExistingAdrFiles(adrDirAbsolutePath: string): Promise<AdrFile[]> {\n let entries;\n\n try {\n entries = await readdir(adrDirAbsolutePath, { withFileTypes: true });\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return [];\n }\n\n throw error;\n }\n\n return entries\n .filter((entry) => entry.isFile())\n .map((entry) => parseAdrFile(entry.name))\n .filter((adrFile): adrFile is AdrFile => adrFile !== null);\n}\n\nfunction parseAdrFile(fileName: string): AdrFile | null {\n const match = ADR_FILE_PATTERN.exec(fileName);\n\n if (match === null) {\n return null;\n }\n\n const number = Number.parseInt(match[1] ?? \"\", 10);\n const id = formatAdrNumber(number);\n const slug = match[2] ?? \"\";\n\n return {\n number,\n id,\n slug,\n fileName,\n };\n}\n","const MAX_SLUG_LENGTH = 80;\nconst CONTROL_CHARS = /[\\u0000-\\u001f\\u007f]/u;\nconst WINDOWS_RESERVED_NAMES = new Set([\n \"con\",\n \"prn\",\n \"aux\",\n \"nul\",\n \"com1\",\n \"com2\",\n \"com3\",\n \"com4\",\n \"com5\",\n \"com6\",\n \"com7\",\n \"com8\",\n \"com9\",\n \"lpt1\",\n \"lpt2\",\n \"lpt3\",\n \"lpt4\",\n \"lpt5\",\n \"lpt6\",\n \"lpt7\",\n \"lpt8\",\n \"lpt9\",\n]);\n\nexport class SlugifyError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"SlugifyError\";\n }\n}\n\nexport type SlugifyOptions = {\n maxLength?: number;\n};\n\nexport function slugify(input: string, options: SlugifyOptions = {}): string {\n const maxLength = options.maxLength ?? MAX_SLUG_LENGTH;\n\n if (!Number.isInteger(maxLength) || maxLength < 1) {\n throw new SlugifyError(\"Slug max length must be a positive integer.\");\n }\n\n const original = input;\n const trimmed = original.trim();\n\n if (trimmed.length === 0) {\n throw new SlugifyError(\"Name cannot be empty.\");\n }\n\n if (original.endsWith(\".\") || original.endsWith(\" \")) {\n throw new SlugifyError(\"Name cannot end with a dot or space.\");\n }\n\n if (CONTROL_CHARS.test(original)) {\n throw new SlugifyError(\"Name cannot contain null bytes or control characters.\");\n }\n\n if (/[\\\\/]/u.test(original)) {\n throw new SlugifyError(\"Name cannot contain path separators.\");\n }\n\n if (trimmed === \".\" || trimmed === \"..\" || trimmed.includes(\"..\")) {\n throw new SlugifyError(\"Name cannot contain path traversal.\");\n }\n\n const withoutDiacritics = trimmed.normalize(\"NFKD\").replace(/[\\u0300-\\u036f]/gu, \"\");\n const slug = withoutDiacritics\n .toLowerCase()\n .replace(/[^a-z0-9]+/gu, \"-\")\n .replace(/-+/gu, \"-\")\n .replace(/^-|-$/gu, \"\")\n .slice(0, maxLength)\n .replace(/-$/u, \"\");\n\n if (slug.length === 0) {\n throw new SlugifyError(\"Name must include at least one letter or number.\");\n }\n\n if (WINDOWS_RESERVED_NAMES.has(slug)) {\n throw new SlugifyError(`Name \"${slug}\" is reserved on Windows.`);\n }\n\n return slug;\n}\n","import type { WriteResult } from \"../core/filesystem/write-file-safe.js\";\n\nexport type WriteSummaryOptions = {\n dryRun: boolean;\n writeResult: WriteResult;\n};\n\nexport function appendWriteSummary(lines: string[], options: WriteSummaryOptions): void {\n appendFileList(\n lines,\n options.dryRun ? \"Planned creates\" : \"Created\",\n options.writeResult.created,\n );\n appendFileList(\n lines,\n options.dryRun ? \"Planned overwrites\" : \"Overwritten\",\n options.writeResult.overwritten,\n );\n appendFileList(lines, \"Skipped\", options.writeResult.skipped);\n}\n\n/**\n * Append a \"Next steps\" guidance block so the CLI tells the user what each artifact is for and what\n * to do next, instead of only listing created paths.\n */\nexport function appendNextSteps(lines: string[], steps: string[]): void {\n if (steps.length === 0) {\n return;\n }\n\n lines.push(\"\");\n lines.push(\"Next steps:\");\n for (const step of steps) {\n lines.push(`- ${step}`);\n }\n}\n\nfunction appendFileList(lines: string[], label: string, paths: string[]): void {\n if (paths.length === 0) {\n return;\n }\n\n lines.push(`${label}:`);\n for (const filePath of paths) {\n lines.push(`- ${filePath}`);\n }\n}\n","import path from \"node:path\";\n\nimport type { WriteFileInput } from \"../filesystem/write-plan.js\";\nimport { slugify } from \"../naming/slugify.js\";\nimport { createTemplateContext } from \"./template-context.js\";\nimport { renderTemplate } from \"./render-template.js\";\n\nexport type GenerateAdrFileOptions = {\n adrDir: string;\n adrId: string;\n title: string;\n};\n\nconst adrTemplate = `# {{adrId}}: {{title}}\n\n## Status\n\nProposed\n\n## Context\n\nWhat decision needs to be made, and why now?\n\n## Decision\n\nWhat option is proposed?\n\n## Alternatives Considered\n\nWhat other options were considered?\n\n## Consequences\n\nWhat improves, what worsens, and what risks remain?\n\n## Related Documents\n\n- PRD:\n- Architecture:\n- Security:\n- Feature:\n`;\n\nexport function generateAdrFile(options: GenerateAdrFileOptions): WriteFileInput[] {\n const slug = slugify(options.title);\n const title = titleizeAdrTitle(options.title);\n const context = createTemplateContext({\n adrId: options.adrId,\n slug,\n title,\n });\n\n return [\n {\n path: path.posix.join(options.adrDir, `${options.adrId}-${slug}.md`),\n content: renderTemplate(adrTemplate, context),\n },\n ];\n}\n\nexport type GenerateSupersedingAdrOptions = {\n adrDir: string;\n adrId: string;\n title: string;\n supersedesRef: string;\n};\n\nconst supersedingAdrTemplate = `# {{adrId}}: {{title}}\n\n## Status\n\nAccepted\n\n## Supersedes\n\n- {{supersedesRef}}\n\n## Context\n\nWhat changed, and why the previous decision no longer holds?\n\n## Decision\n\nWhat is the new decision?\n\n## Alternatives Considered\n\nWhat other options were considered?\n\n## Consequences\n\nWhat improves, what worsens, and what risks remain?\n\n## Related Documents\n\n- PRD:\n- Architecture:\n- Security:\n- Feature:\n`;\n\n/**\n * Render a new, accepted ADR that supersedes an existing one. Used by `recall adr supersede`: a human\n * recording a changed decision, so the new ADR is Accepted and carries a `## Supersedes` link back to\n * the decision it replaces.\n */\nexport function generateSupersedingAdr(options: GenerateSupersedingAdrOptions): {\n path: string;\n content: string;\n slug: string;\n} {\n const slug = slugify(options.title);\n const title = titleizeAdrTitle(options.title);\n const context = createTemplateContext({\n adrId: options.adrId,\n slug,\n title,\n supersedesRef: options.supersedesRef,\n });\n\n return {\n path: path.posix.join(options.adrDir, `${options.adrId}-${slug}.md`),\n content: renderTemplate(supersedingAdrTemplate, context),\n slug,\n };\n}\n\nfunction titleizeAdrTitle(title: string): string {\n return title\n .trim()\n .replace(/[-_]+/gu, \" \")\n .replace(/\\s+/gu, \" \")\n .replace(/\\b\\w/gu, (character) => character.toUpperCase());\n}\n","const TEMPLATE_KEY_PATTERN = /^[A-Za-z][A-Za-z0-9_]*$/u;\nconst RESERVED_TEMPLATE_KEYS = new Set([\"constructor\", \"__proto__\", \"prototype\"]);\n\nexport type TemplateValue = string | number | boolean;\nexport type TemplateContext = Readonly<Record<string, TemplateValue>>;\n\nexport class TemplateRenderError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"TemplateRenderError\";\n }\n}\n\nfunction isTemplateValue(value: unknown): value is TemplateValue {\n return typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\";\n}\n\nfunction validateTemplateKey(key: string): void {\n if (!TEMPLATE_KEY_PATTERN.test(key)) {\n throw new TemplateRenderError(\n `Invalid template key \"${key}\". Keys must match [A-Za-z][A-Za-z0-9_]*.`,\n );\n }\n\n if (RESERVED_TEMPLATE_KEYS.has(key)) {\n throw new TemplateRenderError(`Invalid template key \"${key}\". Key is reserved.`);\n }\n}\n\nexport function createTemplateContext(values: Readonly<Record<string, unknown>>): TemplateContext {\n if (values === null || typeof values !== \"object\" || Array.isArray(values)) {\n throw new TemplateRenderError(\"Template context must be an object.\");\n }\n\n const context = Object.create(null) as Record<string, TemplateValue>;\n\n for (const [key, value] of Object.entries(values)) {\n validateTemplateKey(key);\n\n if (!isTemplateValue(value)) {\n throw new TemplateRenderError(\n `Invalid value for template key \"${key}\". Values must be strings, numbers, or booleans.`,\n );\n }\n\n context[key] = value;\n }\n\n return Object.freeze(context);\n}\n","import {\n createTemplateContext,\n TemplateRenderError,\n type TemplateContext,\n type TemplateValue,\n} from \"./template-context.js\";\n\nconst TEMPLATE_KEY_PATTERN = /^[A-Za-z][A-Za-z0-9_]*$/u;\nconst RESERVED_TEMPLATE_KEYS = new Set([\"constructor\", \"__proto__\", \"prototype\"]);\nconst EXECUTION_MARKERS = [\"<%\", \"%>\"];\nconst LOGIC_MARKERS = [\"{{#\", \"{{/\", \"{{^\", \"{{>\"];\n\nfunction validatePlaceholderKey(key: string): void {\n if (!TEMPLATE_KEY_PATTERN.test(key)) {\n throw new TemplateRenderError(\n `Invalid placeholder \"${key}\". Placeholders must match [A-Za-z][A-Za-z0-9_]*.`,\n );\n }\n\n if (RESERVED_TEMPLATE_KEYS.has(key)) {\n throw new TemplateRenderError(`Invalid placeholder \"${key}\". Placeholder is reserved.`);\n }\n}\n\nfunction stringifyTemplateValue(value: TemplateValue): string {\n return String(value);\n}\n\nfunction rejectUnsupportedSyntax(template: string): void {\n for (const marker of EXECUTION_MARKERS) {\n if (template.includes(marker)) {\n throw new TemplateRenderError(\n `Unsupported template syntax \"${marker}\". Template execution is not supported.`,\n );\n }\n }\n\n for (const marker of LOGIC_MARKERS) {\n if (template.includes(marker)) {\n throw new TemplateRenderError(\n `Unsupported template syntax \"${marker}\". Template logic is not supported.`,\n );\n }\n }\n}\n\nexport function renderTemplate(template: string, context: TemplateContext): string {\n if (typeof template !== \"string\") {\n throw new TemplateRenderError(\"Template must be a string.\");\n }\n\n const safeContext = createTemplateContext(context);\n rejectUnsupportedSyntax(template);\n\n let output = \"\";\n let cursor = 0;\n\n while (cursor < template.length) {\n const openingIndex = template.indexOf(\"{{\", cursor);\n const closingIndex = template.indexOf(\"}}\", cursor);\n\n if (closingIndex !== -1 && (openingIndex === -1 || closingIndex < openingIndex)) {\n throw new TemplateRenderError(\"Invalid template syntax: unmatched closing braces.\");\n }\n\n if (openingIndex === -1) {\n output += template.slice(cursor);\n break;\n }\n\n output += template.slice(cursor, openingIndex);\n\n const placeholderEnd = template.indexOf(\"}}\", openingIndex + 2);\n\n if (placeholderEnd === -1) {\n throw new TemplateRenderError(\"Invalid template syntax: unmatched opening braces.\");\n }\n\n const placeholder = template.slice(openingIndex + 2, placeholderEnd).trim();\n\n if (placeholder.length === 0) {\n throw new TemplateRenderError(\"Invalid template syntax: placeholder cannot be empty.\");\n }\n\n validatePlaceholderKey(placeholder);\n\n if (!Object.prototype.hasOwnProperty.call(safeContext, placeholder)) {\n throw new TemplateRenderError(`Missing template value for \"${placeholder}\".`);\n }\n\n output += stringifyTemplateValue(safeContext[placeholder]);\n cursor = placeholderEnd + 2;\n }\n\n return output;\n}\n","import { ConfigValidationError } from \"../../core/config/config-schema.js\";\nimport { loadConfig, ConfigLoadError } from \"../../core/config/load-config.js\";\nimport { resolveSafePath } from \"../../core/filesystem/safe-path.js\";\nimport { createWritePlan, type WritePlan } from \"../../core/filesystem/write-plan.js\";\nimport { executeWritePlan, type WriteResult } from \"../../core/filesystem/write-file-safe.js\";\nimport { generateAdrFile } from \"../../core/generator/generate-adr.js\";\nimport { getAdrFileForSlug } from \"../../core/naming/adr-number.js\";\nimport { SlugifyError, slugify } from \"../../core/naming/slugify.js\";\nimport { appendNextSteps, appendWriteSummary } from \"../write-summary.js\";\n\nexport type AdrCreateOptions = {\n rootDir: string;\n title: string;\n dryRun?: boolean;\n force?: boolean;\n};\n\nexport type AdrCreateResult = {\n adrId: string;\n slug: string;\n adrPath: string;\n dryRun: boolean;\n plan: WritePlan;\n writeResult: WriteResult;\n};\n\nexport type AdrCreateErrorCode = \"CONFIG_REQUIRED\" | \"INVALID_ADR_TITLE\" | \"WRITE_PLAN_ERROR\";\n\nexport class AdrCreateError extends Error {\n readonly code: AdrCreateErrorCode;\n readonly details: string[];\n\n constructor(code: AdrCreateErrorCode, message: string, details: string[] = []) {\n super(message);\n this.name = \"AdrCreateError\";\n this.code = code;\n this.details = details;\n }\n}\n\nexport async function createAdr(options: AdrCreateOptions): Promise<AdrCreateResult> {\n const slug = createAdrSlug(options.title);\n const config = await loadRequiredConfig(options.rootDir);\n const adrDirPath = resolveSafePath(options.rootDir, config.adrDir);\n const adrFile = await getAdrFileForSlug(adrDirPath.absolutePath, slug);\n const files = generateAdrFile({\n adrDir: config.adrDir,\n adrId: adrFile.id,\n title: options.title,\n });\n const plan = createWritePlan({\n rootDir: options.rootDir,\n files,\n force: options.force,\n });\n\n if (plan.hasErrors) {\n throw new AdrCreateError(\n \"WRITE_PLAN_ERROR\",\n \"ADR create write plan contains errors.\",\n plan.entries\n .filter((entry) => entry.action === \"error\")\n .map((entry) => `${entry.path}: ${entry.reason}`),\n );\n }\n\n const writeResult = await executeWritePlan(plan, { dryRun: options.dryRun });\n\n return {\n adrId: adrFile.id,\n slug,\n adrPath: `${config.adrDir}/${adrFile.fileName}`,\n dryRun: options.dryRun ?? false,\n plan,\n writeResult,\n };\n}\n\nexport function formatAdrCreateResult(result: AdrCreateResult): string {\n const lines = [\n result.dryRun ? \"Recall OS ADR create dry run complete.\" : \"Recall OS ADR create complete.\",\n `ADR: ${result.adrPath}`,\n ];\n\n appendWriteSummary(lines, {\n dryRun: result.dryRun,\n writeResult: result.writeResult,\n });\n\n if (!result.dryRun) {\n appendNextSteps(lines, [\n `Open ${result.adrPath} and fill: Context, Decision, Alternatives, Consequences.`,\n \"It is Proposed — set Status to Accepted once the team agrees.\",\n ]);\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction createAdrSlug(title: string): string {\n try {\n return slugify(title);\n } catch (error) {\n if (error instanceof SlugifyError) {\n throw new AdrCreateError(\"INVALID_ADR_TITLE\", error.message);\n }\n\n throw error;\n }\n}\n\nasync function loadRequiredConfig(rootDir: string) {\n try {\n return await loadConfig(rootDir);\n } catch (error) {\n if (error instanceof ConfigLoadError || error instanceof ConfigValidationError) {\n throw new AdrCreateError(\n \"CONFIG_REQUIRED\",\n \"Recall OS config not found or invalid. Run `recall init` first.\",\n [error.message],\n );\n }\n\n throw error;\n }\n}\n","import { readFile, readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { ConfigValidationError } from \"../../core/config/config-schema.js\";\nimport { loadConfig, ConfigLoadError } from \"../../core/config/load-config.js\";\nimport { resolveSafePath } from \"../../core/filesystem/safe-path.js\";\nimport { createWritePlan, type WritePlan } from \"../../core/filesystem/write-plan.js\";\nimport { executeWritePlan, type WriteResult } from \"../../core/filesystem/write-file-safe.js\";\nimport { generateSupersedingAdr } from \"../../core/generator/generate-adr.js\";\nimport { getNextAdrNumber } from \"../../core/naming/adr-number.js\";\nimport { SlugifyError, slugify } from \"../../core/naming/slugify.js\";\nimport { appendNextSteps, appendWriteSummary } from \"../write-summary.js\";\n\nexport type AdrSupersedeOptions = {\n rootDir: string;\n oldName: string;\n newTitle: string;\n dryRun?: boolean;\n force?: boolean;\n};\n\nexport type AdrSupersedeResult = {\n oldRef: string;\n oldPath: string;\n newRef: string;\n newPath: string;\n dryRun: boolean;\n writeResult: WriteResult;\n};\n\nexport type AdrSupersedeErrorCode =\n | \"CONFIG_REQUIRED\"\n | \"INVALID_ADR_NAME\"\n | \"NOT_FOUND\"\n | \"NOT_ACCEPTED\"\n | \"WRITE_PLAN_ERROR\";\n\nexport class AdrSupersedeError extends Error {\n readonly code: AdrSupersedeErrorCode;\n readonly details: string[];\n\n constructor(code: AdrSupersedeErrorCode, message: string, details: string[] = []) {\n super(message);\n this.name = \"AdrSupersedeError\";\n this.code = code;\n this.details = details;\n }\n}\n\nexport async function supersedeAdr(options: AdrSupersedeOptions): Promise<AdrSupersedeResult> {\n const oldSlug = createSlug(options.oldName, \"oldName\");\n // Validate the new title is sluggable, with a clean error before any file work.\n createSlug(options.newTitle, \"newTitle\");\n const config = await loadRequiredConfig(options.rootDir);\n const adrDirAbsolute = resolveSafePath(options.rootDir, config.adrDir).absolutePath;\n\n const old = await findAcceptedAdr(adrDirAbsolute, oldSlug);\n const next = await getNextAdrNumber(adrDirAbsolute);\n const oldRef = old.fileName.replace(/\\.md$/u, \"\");\n\n // The new, accepted decision that records why the old one changed.\n const superseding = generateSupersedingAdr({\n adrDir: config.adrDir,\n adrId: next.id,\n title: options.newTitle,\n supersedesRef: oldRef,\n });\n const newRef = `${next.id}-${superseding.slug}`;\n\n // Mark the old ADR superseded, but keep \"Accepted\" in the status so existing drift checks still\n // treat references to it as a real, once-accepted decision — the new superseded-reference check is\n // what flags those references for review.\n const markedOld = old.content.replace(\n /(##\\s+Status\\r?\\n\\r?\\n)Accepted[^\\n]*/u,\n `$1Accepted — superseded by ${newRef}`,\n );\n\n const writeNew = await write(options, superseding.path, superseding.content, options.force);\n const oldRelative = `${config.adrDir}/${old.fileName}`;\n const writeOld = await write(options, oldRelative, markedOld, true);\n\n return {\n oldRef,\n oldPath: oldRelative,\n newRef,\n newPath: superseding.path,\n dryRun: options.dryRun ?? false,\n writeResult: {\n created: [...writeNew.created, ...writeOld.created],\n overwritten: [...writeNew.overwritten, ...writeOld.overwritten],\n skipped: [...writeNew.skipped, ...writeOld.skipped],\n dryRun: options.dryRun ?? false,\n },\n };\n}\n\nasync function findAcceptedAdr(\n adrDirAbsolute: string,\n slug: string,\n): Promise<{ fileName: string; content: string }> {\n const pattern = new RegExp(`^ADR-\\\\d{4,}-${escapeRegExp(slug)}\\\\.md$`, \"u\");\n\n let entries;\n try {\n entries = await readdir(adrDirAbsolute, { withFileTypes: true });\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n throw new AdrSupersedeError(\"NOT_FOUND\", `No accepted ADR found for \"${slug}\".`);\n }\n throw error;\n }\n\n const match = entries.find((entry) => entry.isFile() && pattern.test(entry.name));\n if (match === undefined) {\n throw new AdrSupersedeError(\"NOT_FOUND\", `No accepted ADR found for \"${slug}\".`, [\n `Looked for an ADR-####-${slug}.md in the ADR directory.`,\n ]);\n }\n\n const content = await readFile(path.join(adrDirAbsolute, match.name), \"utf8\");\n if (!/(##\\s+Status\\r?\\n\\r?\\n)Accepted\\b/u.test(content)) {\n throw new AdrSupersedeError(\n \"NOT_ACCEPTED\",\n `ADR ${match.name} is not Accepted, so there is nothing to supersede.`,\n [\"Only an accepted decision can be superseded. Accept it first with `recall adr accept`.\"],\n );\n }\n\n return { fileName: match.name, content };\n}\n\nasync function write(\n options: AdrSupersedeOptions,\n relativePath: string,\n content: string,\n force: boolean | undefined,\n): Promise<WriteResult> {\n const plan = createWritePlan({\n rootDir: options.rootDir,\n files: [{ path: relativePath, content }],\n force,\n });\n\n if (plan.hasErrors) {\n throw new AdrSupersedeError(\n \"WRITE_PLAN_ERROR\",\n \"ADR supersede write plan contains errors.\",\n plan.entries\n .filter(\n (entry): entry is Extract<WritePlan[\"entries\"][number], { action: \"error\" }> =>\n entry.action === \"error\",\n )\n .map((entry) => `${entry.path}: ${entry.reason}`),\n );\n }\n\n return executeWritePlan(plan, { dryRun: options.dryRun });\n}\n\nexport function formatAdrSupersedeResult(result: AdrSupersedeResult): string {\n const lines = [\n result.dryRun\n ? \"Recall OS ADR supersede dry run complete.\"\n : \"Recall OS ADR supersede complete.\",\n `Superseded: ${result.oldPath} (now marked superseded by ${result.newRef})`,\n `New decision: ${result.newPath}`,\n ];\n\n appendWriteSummary(lines, { dryRun: result.dryRun, writeResult: result.writeResult });\n\n if (!result.dryRun) {\n appendNextSteps(lines, [\n `Fill ${result.newPath}: Context (what changed), Decision, Alternatives, Consequences.`,\n `${result.oldRef} stays in history as superseded; update any memory that still relies on it.`,\n \"Run `recall doctor` — it flags memory that still references the superseded decision.\",\n ]);\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction createSlug(name: string, field: \"oldName\" | \"newTitle\"): string {\n const withoutPrefix = name.replace(/^ADR-(?:PROPOSED-|\\d{4,}-)/iu, \"\");\n try {\n return slugify(withoutPrefix);\n } catch (error) {\n if (error instanceof SlugifyError) {\n throw new AdrSupersedeError(\"INVALID_ADR_NAME\", `Invalid ${field}: ${error.message}`);\n }\n throw error;\n }\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/gu, \"\\\\$&\");\n}\n\nasync function loadRequiredConfig(rootDir: string) {\n try {\n return await loadConfig(rootDir);\n } catch (error) {\n if (error instanceof ConfigLoadError || error instanceof ConfigValidationError) {\n throw new AdrSupersedeError(\n \"CONFIG_REQUIRED\",\n \"Recall OS config not found or invalid. Run `recall init` first.\",\n [error.message],\n );\n }\n throw error;\n }\n}\n","import path from \"node:path\";\n\nimport type { WriteFileInput } from \"../filesystem/write-plan.js\";\nimport { slugify } from \"../naming/slugify.js\";\nimport { createTemplateContext } from \"./template-context.js\";\nimport { renderTemplate } from \"./render-template.js\";\n\nexport type GenerateFeatureFilesOptions = {\n featuresDir: string;\n featureId: string;\n featureName: string;\n};\n\ntype FeatureTemplate = {\n fileName: string;\n content: string;\n};\n\nconst featureTemplates: FeatureTemplate[] = [\n {\n fileName: \"PRD.md\",\n content: `# PRD: {{title}}\n\n## Purpose\n\nDescribe why this feature exists and what user or business problem it solves.\n\n## In Scope\n\n- TBD\n\n## Non-Goals\n\n- TBD\n`,\n },\n {\n fileName: \"ACCEPTANCE.md\",\n content: `# Acceptance Criteria: {{title}}\n\n## Criteria\n\n- TBD\n\n## Out Of Scope\n\n- TBD\n`,\n },\n {\n fileName: \"ARCHITECTURE_IMPACT.md\",\n content: `# Architecture Impact: {{title}}\n\n## Affected Modules\n\n- TBD\n\n## ADR Impact\n\nState whether this feature needs a new or updated ADR.\n\n## Security Impact\n\nState whether auth, secrets, storage, networking, telemetry, file writes, or dependencies change.\n`,\n },\n {\n fileName: \"CHANGE_REQUESTS.md\",\n content: `# Change Requests: {{title}}\n\nRecord accepted changes to the feature requirements here.\n`,\n },\n {\n fileName: \"PLAN.md\",\n content: `# Plan: {{title}}\n\n## Approach\n\nTBD\n\n## Boundaries\n\nTBD\n`,\n },\n {\n fileName: \"TASKS.md\",\n content: `# Tasks: {{title}}\n\n## T1: Define Scope\n\nStatus: Todo\n\nScope:\n\n- TBD\n\nAcceptance:\n\n- TBD\n\nTests:\n\n- TBD\n\nDo Not:\n\n- Start implementation before PRD, acceptance, architecture impact, and test plan are clear.\n`,\n },\n {\n fileName: \"TEST_PLAN.md\",\n content: `# Test Plan: {{title}}\n\n## Unit Tests\n\n- TBD\n\n## Integration Tests\n\n- TBD\n\n## Security Tests\n\n- TBD\n`,\n },\n {\n fileName: \"REVIEW.md\",\n content: `# Review: {{title}}\n\n## Status\n\nPending review.\n\n## Findings\n\n- TBD\n`,\n },\n {\n fileName: \"COMPLETION_REPORT.md\",\n content: `# Completion Report: {{title}}\n\n## Status\n\nPending.\n\n## Files Changed\n\n- TBD\n\n## Tests Run\n\n- TBD\n\n## Results\n\n- TBD\n\n## Remaining Risks\n\n- TBD\n`,\n },\n];\n\nexport function generateFeatureFiles(options: GenerateFeatureFilesOptions): WriteFileInput[] {\n const slug = slugify(options.featureName);\n const featureDir = path.posix.join(options.featuresDir, `${options.featureId}-${slug}`);\n const title = titleizeFeatureName(options.featureName);\n const context = createTemplateContext({\n featureId: options.featureId,\n slug,\n title,\n });\n\n return featureTemplates.map((template) => ({\n path: path.posix.join(featureDir, template.fileName),\n content: renderTemplate(template.content, context),\n }));\n}\n\nfunction titleizeFeatureName(featureName: string): string {\n return featureName\n .trim()\n .replace(/[-_]+/gu, \" \")\n .replace(/\\s+/gu, \" \")\n .replace(/\\b\\w/gu, (character) => character.toUpperCase());\n}\n","import { readdir } from \"node:fs/promises\";\n\nconst FEATURE_FOLDER_PATTERN = /^F-(\\d{3,})-([a-z0-9]+(?:-[a-z0-9]+)*)$/u;\n\nexport type FeatureNumber = {\n number: number;\n id: string;\n};\n\nexport type FeatureFolder = FeatureNumber & {\n slug: string;\n folderName: string;\n};\n\nexport async function getNextFeatureNumber(\n featuresDirAbsolutePath: string,\n): Promise<FeatureNumber> {\n const existingFolders = await readExistingFeatureFolders(featuresDirAbsolutePath);\n return getNextFeatureNumberFromFolders(existingFolders);\n}\n\nexport async function getFeatureFolderForSlug(\n featuresDirAbsolutePath: string,\n slug: string,\n): Promise<FeatureFolder> {\n const existingFolders = await readExistingFeatureFolders(featuresDirAbsolutePath);\n const existingFolder = existingFolders\n .filter((folder) => folder.slug === slug)\n .sort((left, right) => left.number - right.number)[0];\n\n if (existingFolder !== undefined) {\n return existingFolder;\n }\n\n const nextFeatureNumber = getNextFeatureNumberFromFolders(existingFolders);\n\n return {\n ...nextFeatureNumber,\n slug,\n folderName: `${nextFeatureNumber.id}-${slug}`,\n };\n}\n\nfunction getNextFeatureNumberFromFolders(existingFolders: FeatureFolder[]): FeatureNumber {\n const existingNumbers = existingFolders.map((folder) => folder.number);\n const highestNumber = existingNumbers.length === 0 ? 0 : Math.max(...existingNumbers);\n const nextNumber = highestNumber + 1;\n\n return {\n number: nextNumber,\n id: formatFeatureNumber(nextNumber),\n };\n}\n\nexport function formatFeatureNumber(featureNumber: number): string {\n if (!Number.isInteger(featureNumber) || featureNumber < 1) {\n throw new Error(\"Feature number must be a positive integer.\");\n }\n\n return `F-${String(featureNumber).padStart(3, \"0\")}`;\n}\n\nexport function parseFeatureNumber(folderName: string): number | null {\n const match = FEATURE_FOLDER_PATTERN.exec(folderName);\n\n if (match === null) {\n return null;\n }\n\n return Number.parseInt(match[1] ?? \"\", 10);\n}\n\nasync function readExistingFeatureFolders(\n featuresDirAbsolutePath: string,\n): Promise<FeatureFolder[]> {\n let entries;\n\n try {\n entries = await readdir(featuresDirAbsolutePath, { withFileTypes: true });\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return [];\n }\n\n throw error;\n }\n\n return entries\n .filter((entry) => entry.isDirectory())\n .map((entry) => parseFeatureFolder(entry.name))\n .filter((featureFolder): featureFolder is FeatureFolder => featureFolder !== null);\n}\n\nfunction parseFeatureFolder(folderName: string): FeatureFolder | null {\n const match = FEATURE_FOLDER_PATTERN.exec(folderName);\n\n if (match === null) {\n return null;\n }\n\n const number = Number.parseInt(match[1] ?? \"\", 10);\n const id = formatFeatureNumber(number);\n const slug = match[2] ?? \"\";\n\n return {\n number,\n id,\n slug,\n folderName,\n };\n}\n","import { ConfigValidationError } from \"../../core/config/config-schema.js\";\nimport { loadConfig, ConfigLoadError } from \"../../core/config/load-config.js\";\nimport { resolveSafePath } from \"../../core/filesystem/safe-path.js\";\nimport { createWritePlan, type WritePlan } from \"../../core/filesystem/write-plan.js\";\nimport { executeWritePlan, type WriteResult } from \"../../core/filesystem/write-file-safe.js\";\nimport { generateFeatureFiles } from \"../../core/generator/generate-feature.js\";\nimport { getFeatureFolderForSlug } from \"../../core/naming/feature-number.js\";\nimport { SlugifyError, slugify } from \"../../core/naming/slugify.js\";\nimport { appendNextSteps, appendWriteSummary } from \"../write-summary.js\";\n\nexport type FeatureCreateOptions = {\n rootDir: string;\n name: string;\n dryRun?: boolean;\n force?: boolean;\n};\n\nexport type FeatureCreateResult = {\n featureId: string;\n slug: string;\n featurePath: string;\n dryRun: boolean;\n plan: WritePlan;\n writeResult: WriteResult;\n};\n\nexport type FeatureCreateErrorCode =\n | \"CONFIG_REQUIRED\"\n | \"INVALID_FEATURE_NAME\"\n | \"WRITE_PLAN_ERROR\";\n\nexport class FeatureCreateError extends Error {\n readonly code: FeatureCreateErrorCode;\n readonly details: string[];\n\n constructor(code: FeatureCreateErrorCode, message: string, details: string[] = []) {\n super(message);\n this.name = \"FeatureCreateError\";\n this.code = code;\n this.details = details;\n }\n}\n\nexport async function createFeature(options: FeatureCreateOptions): Promise<FeatureCreateResult> {\n const slug = createFeatureSlug(options.name);\n const config = await loadRequiredConfig(options.rootDir);\n const featuresDirPath = resolveSafePath(options.rootDir, config.featuresDir);\n const featureFolder = await getFeatureFolderForSlug(featuresDirPath.absolutePath, slug);\n const files = generateFeatureFiles({\n featuresDir: config.featuresDir,\n featureId: featureFolder.id,\n featureName: options.name,\n });\n const plan = createWritePlan({\n rootDir: options.rootDir,\n files,\n force: options.force,\n });\n\n if (plan.hasErrors) {\n throw new FeatureCreateError(\n \"WRITE_PLAN_ERROR\",\n \"Feature create write plan contains errors.\",\n plan.entries\n .filter((entry) => entry.action === \"error\")\n .map((entry) => `${entry.path}: ${entry.reason}`),\n );\n }\n\n const writeResult = await executeWritePlan(plan, { dryRun: options.dryRun });\n\n return {\n featureId: featureFolder.id,\n slug,\n featurePath: `${config.featuresDir}/${featureFolder.folderName}`,\n dryRun: options.dryRun ?? false,\n plan,\n writeResult,\n };\n}\n\nexport function formatFeatureCreateResult(result: FeatureCreateResult): string {\n const lines = [\n result.dryRun\n ? \"Recall OS feature create dry run complete.\"\n : \"Recall OS feature create complete.\",\n `Feature: ${result.featurePath}`,\n ];\n\n appendWriteSummary(lines, {\n dryRun: result.dryRun,\n writeResult: result.writeResult,\n });\n\n if (!result.dryRun) {\n appendNextSteps(lines, [\n `Start in ${result.featurePath}: write PRD.md (why) and ACCEPTANCE.md (how you will know it works).`,\n \"Then PLAN.md, TASKS.md, and TEST_PLAN.md before you implement.\",\n \"Run `recall doctor` to check the memory is complete.\",\n ]);\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction createFeatureSlug(name: string): string {\n try {\n return slugify(name);\n } catch (error) {\n if (error instanceof SlugifyError) {\n throw new FeatureCreateError(\"INVALID_FEATURE_NAME\", error.message);\n }\n\n throw error;\n }\n}\n\nasync function loadRequiredConfig(rootDir: string) {\n try {\n return await loadConfig(rootDir);\n } catch (error) {\n if (error instanceof ConfigLoadError || error instanceof ConfigValidationError) {\n throw new FeatureCreateError(\n \"CONFIG_REQUIRED\",\n \"Recall OS config not found or invalid. Run `recall init` first.\",\n [error.message],\n );\n }\n\n throw error;\n }\n}\n","import { parseConfig, type RecallConfig } from \"./config-schema.js\";\n\nconst DEFAULT_CONFIG = {\n version: \"0.1.0\",\n templateVersion: \"0.1.0\",\n preset: null,\n memoryProfile: \"standard\",\n mode: \"standard\",\n aiTools: [\"claude\", \"codex\"],\n docsDir: \"docs\",\n featuresDir: \"docs/40-features\",\n modulesDir: \"docs/30-modules\",\n adrDir: \"docs/adrs\",\n writePolicy: \"skip-existing\",\n preCommitGates: [],\n} satisfies RecallConfig;\n\nexport function createDefaultConfig(overrides: Partial<RecallConfig> = {}): RecallConfig {\n return parseConfig({\n ...DEFAULT_CONFIG,\n aiTools: [...DEFAULT_CONFIG.aiTools],\n preCommitGates: [...DEFAULT_CONFIG.preCommitGates],\n ...overrides,\n });\n}\n","import { existsSync } from \"node:fs\";\nimport { readFile, readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\n\n/**\n * Read-only signals inferred from a repository's manifest and marker files.\n *\n * Inspection never executes repository code, makes network calls, or installs anything. Every signal\n * here is a candidate the user reviews; nothing is accepted by adoption.\n */\nexport type RepoSignals = {\n languages: string[];\n packageManager: string | null;\n /** The manifest file the package manager was inferred from (e.g. `go.mod`). */\n packageManagerSource: string | null;\n frameworks: string[];\n hasTests: boolean;\n /** Where tests were detected (e.g. a matched `*_test.go` path), so a reviewer can correct it. */\n testsEvidence: string | null;\n hasReadme: boolean;\n hasDocs: boolean;\n};\n\n/** Maps a detected framework to the manifest it was inferred from, for reviewable provenance. */\nconst FRAMEWORK_SOURCES: Record<string, string> = {\n \"Next.js\": \"package.json\",\n React: \"package.json\",\n NestJS: \"package.json\",\n Express: \"package.json\",\n FastAPI: \"pyproject.toml / requirements.txt\",\n Flask: \"pyproject.toml / requirements.txt\",\n Django: \"pyproject.toml / requirements.txt\",\n Gin: \"go.mod\",\n Echo: \"go.mod\",\n Fiber: \"go.mod\",\n Chi: \"go.mod\",\n \"Spring Boot\": \"pom.xml / build.gradle\",\n \"Actix Web\": \"Cargo.toml\",\n Axum: \"Cargo.toml\",\n Rocket: \"Cargo.toml\",\n Laravel: \"composer.json\",\n Symfony: \"composer.json\",\n \"Ruby on Rails\": \"Gemfile\",\n Flutter: \"pubspec.yaml\",\n};\n\nexport async function inspectRepo(rootDir: string): Promise<RepoSignals> {\n const has = (relativePath: string): boolean => existsSync(path.join(rootDir, relativePath));\n\n const languages = new Set<string>();\n const frameworks = new Set<string>();\n\n const pkg = has(\"package.json\") ? await readJson(rootDir, \"package.json\") : null;\n if (pkg !== null) {\n languages.add(has(\"tsconfig.json\") ? \"TypeScript\" : \"JavaScript\");\n }\n\n let pythonText = \"\";\n if (has(\"pyproject.toml\")) {\n languages.add(\"Python\");\n pythonText += await readText(rootDir, \"pyproject.toml\");\n }\n if (has(\"requirements.txt\")) {\n languages.add(\"Python\");\n pythonText += await readText(rootDir, \"requirements.txt\");\n }\n\n if (has(\"go.mod\")) {\n languages.add(\"Go\");\n }\n if (has(\"Cargo.toml\")) {\n languages.add(\"Rust\");\n }\n if (has(\"pom.xml\") || has(\"build.gradle\") || has(\"build.gradle.kts\")) {\n languages.add(\"JVM\");\n }\n if (has(\"Package.swift\")) {\n languages.add(\"Swift\");\n }\n if (has(\"pubspec.yaml\")) {\n languages.add(\"Dart\");\n frameworks.add(\"Flutter\");\n }\n\n if (has(\"composer.json\")) {\n languages.add(\"PHP\");\n const composer = (await readText(rootDir, \"composer.json\")).toLowerCase();\n if (composer.includes(\"laravel/framework\")) {\n frameworks.add(\"Laravel\");\n } else if (composer.includes(\"symfony/\")) {\n frameworks.add(\"Symfony\");\n }\n }\n\n if (has(\"Gemfile\")) {\n languages.add(\"Ruby\");\n const gemfile = (await readText(rootDir, \"Gemfile\")).toLowerCase();\n if (gemfile.includes(\"rails\")) {\n frameworks.add(\"Ruby on Rails\");\n }\n }\n\n const deps = collectDependencies(pkg);\n if (\"next\" in deps) {\n frameworks.add(\"Next.js\");\n } else if (\"react\" in deps) {\n frameworks.add(\"React\");\n }\n if (\"@nestjs/core\" in deps) {\n frameworks.add(\"NestJS\");\n } else if (\"express\" in deps) {\n frameworks.add(\"Express\");\n }\n\n const python = pythonText.toLowerCase();\n if (python.includes(\"fastapi\")) {\n frameworks.add(\"FastAPI\");\n } else if (python.includes(\"flask\")) {\n frameworks.add(\"Flask\");\n } else if (python.includes(\"django\")) {\n frameworks.add(\"Django\");\n }\n\n if (has(\"go.mod\")) {\n const goModules = `${await readText(rootDir, \"go.mod\")}${await readText(rootDir, \"go.sum\")}`;\n if (goModules.includes(\"gin-gonic/gin\")) {\n frameworks.add(\"Gin\");\n } else if (goModules.includes(\"labstack/echo\")) {\n frameworks.add(\"Echo\");\n } else if (goModules.includes(\"gofiber/fiber\")) {\n frameworks.add(\"Fiber\");\n } else if (goModules.includes(\"go-chi/chi\")) {\n frameworks.add(\"Chi\");\n }\n }\n\n const jvmManifest =\n `${await readText(rootDir, \"pom.xml\")}${await readText(rootDir, \"build.gradle\")}${await readText(rootDir, \"build.gradle.kts\")}`.toLowerCase();\n if (jvmManifest.includes(\"spring-boot\") || jvmManifest.includes(\"springframework\")) {\n frameworks.add(\"Spring Boot\");\n }\n\n if (has(\"Cargo.toml\")) {\n const cargo = (await readText(rootDir, \"Cargo.toml\")).toLowerCase();\n if (cargo.includes(\"actix-web\")) {\n frameworks.add(\"Actix Web\");\n } else if (cargo.includes(\"axum\")) {\n frameworks.add(\"Axum\");\n } else if (cargo.includes(\"rocket\")) {\n frameworks.add(\"Rocket\");\n }\n }\n\n const [packageManager, packageManagerSource] = detectPackageManager(has);\n\n const scripts = pkg !== null && isRecord(pkg.scripts) ? pkg.scripts : {};\n const testsEvidence = await detectTestsEvidence(rootDir, has, \"test\" in scripts, python);\n\n return {\n languages: [...languages],\n packageManager,\n packageManagerSource,\n frameworks: [...frameworks],\n hasTests: testsEvidence !== null,\n testsEvidence,\n hasReadme: has(\"README.md\") || has(\"README\"),\n hasDocs: has(\"docs\"),\n };\n}\n\n/**\n * Human-readable summary of the inferred signals, with the source each was read from so a reviewer\n * can confirm or correct it. Shared by `recall adopt` (which persists it) and `recall init` (which\n * surfaces it). Every line is proposed, never accepted.\n */\nexport function summarizeSignals(signals: RepoSignals): string[] {\n const lines: string[] = [];\n\n lines.push(`- Languages: ${formatList(signals.languages)}`);\n\n lines.push(\n signals.packageManager === null\n ? \"- Package manager: none detected\"\n : `- Package manager: ${signals.packageManager}${\n signals.packageManagerSource === null ? \"\" : ` (from \\`${signals.packageManagerSource}\\`)`\n }`,\n );\n\n if (signals.frameworks.length === 0) {\n lines.push(\"- Frameworks: none detected\");\n } else {\n const withSource = signals.frameworks.map((framework) => {\n const source = FRAMEWORK_SOURCES[framework];\n return source === undefined ? framework : `${framework} (from \\`${source}\\`)`;\n });\n lines.push(`- Frameworks: ${withSource.join(\", \")}`);\n }\n\n lines.push(\n signals.testsEvidence === null\n ? \"- Tests: none detected — if tests exist, point Recall at them by correcting this report\"\n : `- Tests: detected via ${signals.testsEvidence}`,\n );\n\n lines.push(`- README present: ${signals.hasReadme ? \"yes\" : \"no\"}`);\n lines.push(`- Docs folder present: ${signals.hasDocs ? \"yes\" : \"no\"}`);\n\n return lines;\n}\n\nfunction formatList(values: string[]): string {\n return values.length === 0 ? \"none detected\" : values.join(\", \");\n}\n\n/**\n * Choose the repository's primary package manager. A backend manifest (Go, Rust, JVM, PHP, Ruby,\n * Python, Swift, Dart) wins over a JavaScript one, because a lone `package.json` in such a repo is\n * usually tooling (linters, git hooks) rather than the project's real package manager.\n */\nfunction detectPackageManager(\n has: (relativePath: string) => boolean,\n): [string | null, string | null] {\n const candidates: Array<[boolean, string, string]> = [\n [has(\"go.mod\"), \"Go modules\", \"go.mod\"],\n [has(\"Cargo.toml\"), \"Cargo\", \"Cargo.toml\"],\n [has(\"pom.xml\"), \"Maven\", \"pom.xml\"],\n [has(\"build.gradle\"), \"Gradle\", \"build.gradle\"],\n [has(\"build.gradle.kts\"), \"Gradle\", \"build.gradle.kts\"],\n [has(\"composer.json\"), \"Composer\", \"composer.json\"],\n [has(\"Gemfile\"), \"Bundler\", \"Gemfile\"],\n [has(\"Package.swift\"), \"Swift Package Manager\", \"Package.swift\"],\n [has(\"pubspec.yaml\"), \"pub\", \"pubspec.yaml\"],\n [has(\"uv.lock\"), \"uv\", \"uv.lock\"],\n [has(\"poetry.lock\"), \"Poetry\", \"poetry.lock\"],\n [has(\"requirements.txt\"), \"pip\", \"requirements.txt\"],\n [has(\"pyproject.toml\"), \"pip\", \"pyproject.toml\"],\n [has(\"pnpm-lock.yaml\"), \"pnpm\", \"pnpm-lock.yaml\"],\n [has(\"yarn.lock\"), \"yarn\", \"yarn.lock\"],\n [has(\"package-lock.json\"), \"npm\", \"package-lock.json\"],\n [has(\"package.json\"), \"npm\", \"package.json\"],\n ];\n\n for (const [present, name, source] of candidates) {\n if (present) {\n return [name, source];\n }\n }\n\n return [null, null];\n}\n\nasync function detectTestsEvidence(\n rootDir: string,\n has: (relativePath: string) => boolean,\n hasTestScript: boolean,\n pythonText: string,\n): Promise<string | null> {\n if (has(\"tests\")) {\n return \"`tests/` directory\";\n }\n if (has(\"test\")) {\n return \"`test/` directory\";\n }\n if (has(\"__tests__\")) {\n return \"`__tests__/` directory\";\n }\n if (has(\"pytest.ini\") || pythonText.includes(\"pytest\")) {\n return \"pytest configuration\";\n }\n if (has(\"phpunit.xml\") || has(\"phpunit.xml.dist\")) {\n return \"PHPUnit configuration\";\n }\n if (hasTestScript) {\n return '`\"test\"` script in package.json';\n }\n\n const testFile = await findTestFile(rootDir);\n if (testFile !== null) {\n return `\\`${testFile}\\``;\n }\n\n return null;\n}\n\nconst TEST_FILE_PATTERNS = [\n /_test\\.go$/u,\n /\\.(test|spec)\\.[cm]?[jt]sx?$/u,\n /^test_.+\\.py$/u,\n /_test\\.py$/u,\n /.+Tests?\\.(java|kt)$/u,\n /.+Test\\.php$/u,\n /_spec\\.rb$/u,\n /_test\\.rb$/u,\n];\n\nconst TEST_WALK_SKIP_DIRS = new Set([\n \"node_modules\",\n \"vendor\",\n \"dist\",\n \"build\",\n \"target\",\n \"coverage\",\n \"Pods\",\n \"__pycache__\",\n]);\n\n/**\n * Bounded, read-only walk that detects test files across ecosystems (Go `*_test.go`, JS/TS\n * `*.test.*`/`*.spec.*`, Python `test_*.py`, JVM `*Test.(java|kt)`, PHP `*Test.php`, Ruby `*_spec.rb`).\n * Capped at a fixed entry budget and skips heavy/vendored directories so it stays fast on large repos.\n */\nasync function findTestFile(rootDir: string): Promise<string | null> {\n let budget = 4000;\n const stack = [rootDir];\n\n while (stack.length > 0 && budget > 0) {\n const dir = stack.pop();\n if (dir === undefined) {\n break;\n }\n\n let entries;\n try {\n entries = await readdir(dir, { withFileTypes: true });\n } catch {\n continue;\n }\n\n for (const entry of entries) {\n budget -= 1;\n if (budget <= 0) {\n break;\n }\n\n if (entry.isDirectory()) {\n if (!TEST_WALK_SKIP_DIRS.has(entry.name) && !entry.name.startsWith(\".\")) {\n stack.push(path.join(dir, entry.name));\n }\n } else if (TEST_FILE_PATTERNS.some((pattern) => pattern.test(entry.name))) {\n return path.relative(rootDir, path.join(dir, entry.name));\n }\n }\n }\n\n return null;\n}\n\nfunction collectDependencies(pkg: Record<string, unknown> | null): Record<string, unknown> {\n if (pkg === null) {\n return {};\n }\n\n const dependencies = isRecord(pkg.dependencies) ? pkg.dependencies : {};\n const devDependencies = isRecord(pkg.devDependencies) ? pkg.devDependencies : {};\n\n return { ...dependencies, ...devDependencies };\n}\n\nasync function readJson(\n rootDir: string,\n relativePath: string,\n): Promise<Record<string, unknown> | null> {\n try {\n const parsed = JSON.parse(await readText(rootDir, relativePath)) as unknown;\n return isRecord(parsed) ? parsed : null;\n } catch {\n return null;\n }\n}\n\nasync function readText(rootDir: string, relativePath: string): Promise<string> {\n try {\n return await readFile(path.join(rootDir, relativePath), \"utf8\");\n } catch {\n return \"\";\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import type { WriteFileInput } from \"../filesystem/write-plan.js\";\nimport { summarizeSignals, type RepoSignals } from \"./inspect-repo.js\";\n\nexport const ADOPTION_REPORT_PATH = \"docs/adopt/ADOPTION_REPORT.md\";\n\nexport type GenerateAdoptionOptions = {\n adrDir: string;\n signals: RepoSignals;\n};\n\nexport function generateAdoptionFiles(options: GenerateAdoptionOptions): WriteFileInput[] {\n const files: WriteFileInput[] = [\n {\n path: ADOPTION_REPORT_PATH,\n content: renderReport(options.adrDir, options.signals),\n },\n ];\n\n for (const framework of options.signals.frameworks) {\n files.push({\n path: `${options.adrDir}/proposed/ADR-PROPOSED-adopt-${frameworkSlug(framework)}.md`,\n content: renderProposedAdr(framework),\n });\n }\n\n return files;\n}\n\nfunction renderReport(adrDir: string, signals: RepoSignals): string {\n return `# Adoption Report\n\n## Status\n\nProposed. Everything below is inferred from this repository and requires human review. Nothing here\nis accepted repository memory until you accept it.\n\n## Detected Signals\n\nEach signal notes the file it was inferred from. If one is wrong, correct the source or edit this\nreport — nothing here is accepted.\n\n${summarizeSignals(signals).join(\"\\n\")}\n\n## Proposed Decisions\n\n${renderProposedDecisions(adrDir, signals)}\n\n## Review Checklist\n\n- [ ] Confirm the detected languages and package manager (and the source each was read from).\n- [ ] Confirm where tests were detected, or point Recall at the right location if it is wrong.\n- [ ] Accept or reject each proposed framework ADR under \\`${adrDir}/proposed/\\`.\n- [ ] Run \\`recall init\\` to establish neutral repository memory if it does not exist yet.\n- [ ] Record any decision you accept with \\`recall adr create\\` or by accepting the proposed ADR.\n\n## Notes\n\nThis report was produced by \\`recall adopt\\` through read-only inspection of manifest and marker\nfiles. No repository code was executed and no decision was accepted automatically.\n`;\n}\n\nfunction renderProposedDecisions(adrDir: string, signals: RepoSignals): string {\n if (signals.frameworks.length === 0) {\n return \"- No framework decisions were inferred. Add decisions with `recall adr create` as needed.\";\n }\n\n return signals.frameworks\n .map(\n (framework) =>\n `- Proposed: record **${framework}** as an architecture decision (see ` +\n `\\`${adrDir}/proposed/ADR-PROPOSED-adopt-${frameworkSlug(framework)}.md\\`). Requires review.`,\n )\n .join(\"\\n\");\n}\n\nfunction renderProposedAdr(framework: string): string {\n return `# Proposed ADR: Use ${framework}\n\n## Status\n\nProposed\n\n## Context\n\n\\`recall adopt\\` detected ${framework} in this repository through read-only inspection.\n\n## Decision\n\nConsider recording ${framework} as an accepted architecture decision. This is proposed by adoption\nand is not accepted until a human reviews and accepts it.\n\n## Alternatives Considered\n\n- Record a different framework.\n- Leave the decision unrecorded for now.\n\n## Consequences\n\n- Captures a framework already in use as reviewable repository memory.\n- Requires explicit human acceptance before it becomes repository truth.\n\n## Related Documents\n\n- \\`docs/10-architecture/ARCHITECTURE.md\\` — record the accepted architecture here once promoted.\n- The adoption report generated alongside this proposal.\n`;\n}\n\nfunction frameworkSlug(framework: string): string {\n return framework\n .toLowerCase()\n .replace(/\\./gu, \"\")\n .replace(/[^a-z0-9]+/gu, \"-\")\n .replace(/^-+|-+$/gu, \"\");\n}\n","import { createDefaultConfig } from \"../core/config/default-config.js\";\nimport { ConfigValidationError } from \"../core/config/config-schema.js\";\nimport { loadConfig, ConfigLoadError } from \"../core/config/load-config.js\";\nimport { generateAdoptionFiles } from \"../core/adopt/generate-adoption.js\";\nimport { inspectRepo, type RepoSignals } from \"../core/adopt/inspect-repo.js\";\nimport { createWritePlan, type WritePlan } from \"../core/filesystem/write-plan.js\";\nimport { executeWritePlan, type WriteResult } from \"../core/filesystem/write-file-safe.js\";\nimport { appendNextSteps, appendWriteSummary } from \"./write-summary.js\";\n\nexport type AdoptOptions = {\n rootDir: string;\n dryRun?: boolean;\n force?: boolean;\n};\n\nexport type AdoptResult = {\n signals: RepoSignals;\n dryRun: boolean;\n plan: WritePlan;\n writeResult: WriteResult;\n};\n\nexport type AdoptErrorCode = \"WRITE_PLAN_ERROR\";\n\nexport class AdoptError extends Error {\n readonly code: AdoptErrorCode;\n readonly details: string[];\n\n constructor(code: AdoptErrorCode, message: string, details: string[] = []) {\n super(message);\n this.name = \"AdoptError\";\n this.code = code;\n this.details = details;\n }\n}\n\nexport async function adoptProject(options: AdoptOptions): Promise<AdoptResult> {\n const config = await loadConfigOrDefault(options.rootDir);\n const signals = await inspectRepo(options.rootDir);\n const files = generateAdoptionFiles({ adrDir: config.adrDir, signals });\n const plan = createWritePlan({\n rootDir: options.rootDir,\n files,\n force: options.force,\n });\n\n if (plan.hasErrors) {\n throw new AdoptError(\n \"WRITE_PLAN_ERROR\",\n \"Recall OS adopt write plan contains errors.\",\n plan.entries\n .filter((entry) => entry.action === \"error\")\n .map((entry) => `${entry.path}: ${entry.reason}`),\n );\n }\n\n const writeResult = await executeWritePlan(plan, { dryRun: options.dryRun });\n\n return {\n signals,\n dryRun: options.dryRun ?? false,\n plan,\n writeResult,\n };\n}\n\nexport function formatAdoptResult(result: AdoptResult): string {\n const lines = [\n result.dryRun ? \"Recall OS adopt dry run complete.\" : \"Recall OS adopt complete.\",\n \"Inferred signals are proposed and require human review.\",\n `Languages: ${formatList(result.signals.languages)}`,\n `Package manager: ${result.signals.packageManager ?? \"none detected\"}`,\n `Frameworks: ${formatList(result.signals.frameworks)}`,\n ];\n\n appendWriteSummary(lines, {\n dryRun: result.dryRun,\n writeResult: result.writeResult,\n });\n\n if (!result.dryRun) {\n appendNextSteps(lines, [\n \"Review docs/adopt/ADOPTION_REPORT.md — everything in it is proposed.\",\n \"Run `recall init` to establish neutral repository memory if it does not exist yet.\",\n \"Accept or reject each proposed ADR under docs/adrs/proposed/.\",\n ]);\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nasync function loadConfigOrDefault(rootDir: string) {\n try {\n return await loadConfig(rootDir);\n } catch (error) {\n if (error instanceof ConfigLoadError || error instanceof ConfigValidationError) {\n return createDefaultConfig();\n }\n\n throw error;\n }\n}\n\nfunction formatList(values: string[]): string {\n return values.length > 0 ? values.join(\", \") : \"none detected\";\n}\n","import { existsSync } from \"node:fs\";\nimport { readFile, readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport type { DoctorCheckContext, DoctorFinding } from \"../doctor-check.js\";\n\nconst featureFolderPattern = /^F-\\d{3,}-[a-z0-9]+(?:-[a-z0-9]+)*$/u;\n\n// Only the current-state docs are checked. Historical docs (completion reports, reviews) legitimately\n// reference paths as they were at the time and must not be flagged when code is later refactored.\nconst FEATURE_DOCS = [\"PRD.md\", \"ARCHITECTURE_IMPACT.md\"];\nconst MODULE_DOCS = [\"MODULE.md\", \"DECISIONS.md\"];\n\n// An inline-code token that looks like a concrete source path: under src/ or tests/, with a file\n// extension. Placeholder-bearing paths (`<id>`, globs, `...`) are skipped so illustrative paths do\n// not false-positive.\nconst codePathPattern = /`((?:src|tests)\\/[A-Za-z0-9._/-]+\\.[A-Za-z0-9]+)`/gu;\nconst placeholderMarkers = /[<>*]|\\.\\.\\./u;\n\n/**\n * Deterministic memory-to-code drift check.\n *\n * Flags current-state memory that cites a `src/` or `tests/` path which no longer exists, so stale\n * documentation that references renamed or deleted code is surfaced rather than silently trusted.\n */\nexport async function checkCodeReferences(context: DoctorCheckContext): Promise<DoctorFinding[]> {\n if (context.config === undefined) {\n return [];\n }\n\n const findings: DoctorFinding[] = [];\n\n const featureEntries = await readDirIfExists(context.rootDir, context.config.featuresDir);\n for (const folder of featureEntries) {\n if (!folder.isDirectory() || !featureFolderPattern.test(folder.name)) {\n continue;\n }\n for (const doc of FEATURE_DOCS) {\n const relativePath = path.posix.join(context.config.featuresDir, folder.name, doc);\n findings.push(...(await checkDoc(context.rootDir, relativePath)));\n }\n }\n\n const moduleEntries = await readDirIfExists(context.rootDir, context.config.modulesDir);\n for (const folder of moduleEntries) {\n if (!folder.isDirectory()) {\n continue;\n }\n for (const doc of MODULE_DOCS) {\n const relativePath = path.posix.join(context.config.modulesDir, folder.name, doc);\n findings.push(...(await checkDoc(context.rootDir, relativePath)));\n }\n }\n\n return findings;\n}\n\nasync function checkDoc(rootDir: string, relativePath: string): Promise<DoctorFinding[]> {\n const content = await readFileIfExists(rootDir, relativePath);\n if (content === undefined) {\n return [];\n }\n\n const findings: DoctorFinding[] = [];\n const seen = new Set<string>();\n\n for (const match of content.matchAll(codePathPattern)) {\n const reference = match[1];\n if (placeholderMarkers.test(reference) || seen.has(reference)) {\n continue;\n }\n seen.add(reference);\n\n if (!existsSync(path.join(rootDir, reference))) {\n findings.push({\n severity: \"warning\",\n check: \"drift-code-reference\",\n message: `Repository memory references ${reference}, which does not exist.`,\n path: relativePath,\n });\n }\n }\n\n return findings;\n}\n\nasync function readDirIfExists(rootDir: string, relativePath: string) {\n try {\n return await readdir(path.join(rootDir, relativePath), { withFileTypes: true });\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return [];\n }\n throw error;\n }\n}\n\nasync function readFileIfExists(\n rootDir: string,\n relativePath: string,\n): Promise<string | undefined> {\n try {\n return await readFile(path.join(rootDir, relativePath), \"utf8\");\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return undefined;\n }\n throw error;\n }\n}\n","import { readFile } from \"node:fs/promises\";\n\nimport {\n ConfigValidationError,\n parseConfig,\n type RecallConfig,\n} from \"../../config/config-schema.js\";\nimport { CONFIG_PATH } from \"../../config/load-config.js\";\nimport { resolveSafePath } from \"../../filesystem/safe-path.js\";\nimport type { DoctorFinding } from \"../doctor-check.js\";\n\nexport type ConfigCheckResult = {\n config?: RecallConfig;\n findings: DoctorFinding[];\n};\n\nexport async function checkConfig(rootDir: string): Promise<ConfigCheckResult> {\n const configPath = resolveSafePath(rootDir, CONFIG_PATH);\n\n let rawConfig: string;\n try {\n rawConfig = await readFile(configPath.absolutePath, \"utf8\");\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return {\n findings: [\n {\n severity: \"error\",\n check: \"config\",\n message: \"Missing .recall/config.json.\",\n path: CONFIG_PATH,\n },\n ],\n };\n }\n throw error;\n }\n\n let parsedJson: unknown;\n try {\n parsedJson = JSON.parse(rawConfig);\n } catch {\n return {\n findings: [\n {\n severity: \"error\",\n check: \"config\",\n message: \"Config file is not valid JSON.\",\n path: CONFIG_PATH,\n },\n ],\n };\n }\n\n try {\n const config = parseConfig(parsedJson);\n\n return {\n config,\n findings: [\n {\n severity: \"info\",\n check: \"config\",\n message: \"Recall OS config validates.\",\n path: CONFIG_PATH,\n },\n ],\n };\n } catch (error) {\n if (error instanceof ConfigValidationError) {\n return {\n findings: [\n {\n severity: \"error\",\n check: \"config\",\n message: error.message,\n path: CONFIG_PATH,\n },\n ],\n };\n }\n\n throw error;\n }\n}\n","import { readFile, readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport type { DoctorCheckContext, DoctorFinding } from \"../doctor-check.js\";\n\nconst featureFolderPattern = /^F-\\d{3,}-[a-z0-9]+(?:-[a-z0-9]+)*$/u;\nconst acceptedAdrPattern = /^ADR-\\d{4,}-[a-z0-9]+(?:-[a-z0-9]+)*\\.md$/u;\n\nconst SECURITY_MODEL_PATH = \"docs/20-security/SECURITY_MODEL.md\";\nconst THREAT_MODEL_PATH = \"docs/20-security/THREAT_MODEL.md\";\n\n/**\n * Content-completeness check.\n *\n * Flags feature PRDs and module memory whose required sections are still unedited template stubs, so\n * generated scaffolds become an enforced workflow rather than silent empty docs. Findings are\n * warnings: they surface gaps without hard-failing structurally healthy repositories.\n */\nexport async function checkContent(context: DoctorCheckContext): Promise<DoctorFinding[]> {\n if (context.config === undefined) {\n return [];\n }\n\n const findings: DoctorFinding[] = [];\n const entries = await readDirIfExists(context.rootDir, context.config.featuresDir);\n const featureFolders = entries.filter(\n (entry) => entry.isDirectory() && featureFolderPattern.test(entry.name),\n );\n\n for (const folder of featureFolders) {\n const prdPath = path.posix.join(context.config.featuresDir, folder.name, \"PRD.md\");\n const prd = await readFileIfExists(context.rootDir, prdPath);\n\n if (prd === undefined) {\n continue;\n }\n\n if (sectionIsUnfilled(prd, \"Purpose\")) {\n findings.push({\n severity: \"warning\",\n check: \"content-feature-prd\",\n message: \"Feature PRD purpose is still an unfilled template.\",\n path: prdPath,\n });\n }\n\n if (sectionIsUnfilled(prd, \"In Scope\")) {\n findings.push({\n severity: \"warning\",\n check: \"content-feature-prd\",\n message: \"Feature PRD in-scope section is still an unfilled template.\",\n path: prdPath,\n });\n }\n }\n\n const moduleEntries = await readDirIfExists(context.rootDir, context.config.modulesDir);\n const moduleFolders = moduleEntries.filter((entry) => entry.isDirectory());\n\n const adrEntries = await readDirIfExists(context.rootDir, context.config.adrDir);\n const acceptedAdrs = adrEntries.filter(\n (entry) => entry.isFile() && acceptedAdrPattern.test(entry.name),\n );\n\n // Force the foundational security docs to be filled, but only once the repository has real work.\n // A bare `recall init` stays green; a project with a feature, module, or accepted decision must\n // not leave its threat model and security model as untouched stubs.\n const hasWork = featureFolders.length > 0 || moduleFolders.length > 0 || acceptedAdrs.length > 0;\n\n if (hasWork) {\n findings.push(...(await checkSecurityDoc(context.rootDir)));\n }\n\n for (const folder of moduleFolders) {\n const modulePath = path.posix.join(context.config.modulesDir, folder.name, \"MODULE.md\");\n const moduleDoc = await readFileIfExists(context.rootDir, modulePath);\n\n if (moduleDoc === undefined) {\n continue;\n }\n\n if (sectionIsUnfilled(moduleDoc, \"Purpose\")) {\n findings.push({\n severity: \"warning\",\n check: \"content-module\",\n message: \"Module memory purpose is still an unfilled template.\",\n path: modulePath,\n });\n }\n\n if (sectionIsUnfilled(moduleDoc, \"Owns\")) {\n findings.push({\n severity: \"warning\",\n check: \"content-module\",\n message: \"Module memory owns section is still an unfilled template.\",\n path: modulePath,\n });\n }\n }\n\n return findings;\n}\n\nasync function checkSecurityDoc(rootDir: string): Promise<DoctorFinding[]> {\n const findings: DoctorFinding[] = [];\n\n const security = await readFileIfExists(rootDir, SECURITY_MODEL_PATH);\n if (security !== undefined && sectionIsUnfilled(security, \"Authentication And Authorization\")) {\n findings.push({\n severity: \"warning\",\n check: \"content-security\",\n message:\n \"Security model authentication and authorization section is still an unfilled template.\",\n path: SECURITY_MODEL_PATH,\n });\n }\n\n const threat = await readFileIfExists(rootDir, THREAT_MODEL_PATH);\n if (threat !== undefined && sectionIsUnfilled(threat, \"Assets\")) {\n findings.push({\n severity: \"warning\",\n check: \"content-threat-model\",\n message: \"Threat model assets section is still an unfilled template.\",\n path: THREAT_MODEL_PATH,\n });\n }\n\n return findings;\n}\n\nfunction sectionIsUnfilled(content: string, heading: string): boolean {\n const section = getSection(content, heading);\n return section !== undefined && isUnfilled(section);\n}\n\nfunction isUnfilled(value: string): boolean {\n const normalized = value\n .replace(/[`*_>#-]/gu, \" \")\n .replace(/\\s+/gu, \" \")\n .trim()\n .toLowerCase()\n .replace(/\\.$/u, \"\");\n\n if (normalized.length === 0) {\n return true;\n }\n\n if (\n normalized === \"tbd\" ||\n normalized === \"todo\" ||\n normalized === \"pending\" ||\n normalized === \"none\" ||\n normalized === \"n/a\"\n ) {\n return true;\n }\n\n return (\n normalized.includes(\"describe why this feature exists\") ||\n normalized.includes(\"describe what this module owns\") ||\n normalized.includes(\"describe how this repository authenticates\") ||\n normalized.includes(\"describe what this repository must protect\")\n );\n}\n\nfunction getSection(content: string, heading: string): string | undefined {\n const lines = content.split(/\\r?\\n/u);\n const normalizedHeading = `## ${heading.toLowerCase()}`;\n const startIndex = lines.findIndex((line) => line.trim().toLowerCase() === normalizedHeading);\n\n if (startIndex === -1) {\n return undefined;\n }\n\n const body: string[] = [];\n\n for (let index = startIndex + 1; index < lines.length; index += 1) {\n if (/^##\\s+/u.test(lines[index])) {\n break;\n }\n\n body.push(lines[index]);\n }\n\n return body.join(\"\\n\").trim();\n}\n\nasync function readDirIfExists(rootDir: string, relativePath: string) {\n try {\n return await readdir(path.join(rootDir, relativePath), { withFileTypes: true });\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return [];\n }\n throw error;\n }\n}\n\nasync function readFileIfExists(\n rootDir: string,\n relativePath: string,\n): Promise<string | undefined> {\n try {\n return await readFile(path.join(rootDir, relativePath), \"utf8\");\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return undefined;\n }\n throw error;\n }\n}\n","import { readFile, readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport type { DoctorCheckContext, DoctorFinding } from \"../doctor-check.js\";\n\nconst adrFilePattern = /^ADR-(\\d{4,})-[a-z0-9]+(?:-[a-z0-9]+)*\\.md$/iu;\nconst adrReferencePattern = /ADR-\\d{4,}/giu;\n\ntype KnownAdr = {\n id: string;\n accepted: boolean;\n};\n\n/**\n * Deterministic, local, read-only drift check.\n *\n * Detects repository memory that references ADR identifiers which either do not exist\n * (dangling decision references) or are not yet accepted (reliance on a proposed decision).\n */\nexport async function checkDrift(context: DoctorCheckContext): Promise<DoctorFinding[]> {\n if (context.config === undefined) {\n return [];\n }\n\n const knownAdrs = await loadKnownAdrs(context.rootDir, context.config.adrDir);\n\n const findings: DoctorFinding[] = [];\n findings.push(...(await checkReferences(context.rootDir, context.config.featuresDir, knownAdrs)));\n findings.push(...(await checkReferences(context.rootDir, context.config.modulesDir, knownAdrs)));\n\n return findings;\n}\n\nasync function loadKnownAdrs(rootDir: string, adrDir: string): Promise<Map<string, KnownAdr>> {\n const known = new Map<string, KnownAdr>();\n const files = await readMarkdownFiles(rootDir, adrDir);\n\n for (const file of files) {\n const match = adrFilePattern.exec(path.basename(file));\n if (match === null) {\n continue;\n }\n\n const id = `ADR-${match[1]}`;\n const content = await readFile(path.join(rootDir, file), \"utf8\");\n const accepted = sectionContains(content, \"Status\", /\\baccepted\\b/iu);\n\n // First accepted declaration wins; otherwise keep the existing record.\n const existing = known.get(id);\n if (existing === undefined || (!existing.accepted && accepted)) {\n known.set(id, { id, accepted });\n }\n }\n\n return known;\n}\n\nasync function checkReferences(\n rootDir: string,\n referenceDir: string,\n knownAdrs: Map<string, KnownAdr>,\n): Promise<DoctorFinding[]> {\n const findings: DoctorFinding[] = [];\n const files = await readMarkdownFiles(rootDir, referenceDir);\n\n for (const file of files) {\n const content = await readFile(path.join(rootDir, file), \"utf8\");\n const referenced = new Set<string>();\n\n // Ignore ADR identifiers inside fenced code blocks and inline code so illustrative\n // examples are not treated as real references.\n for (const match of stripCode(content).matchAll(adrReferencePattern)) {\n referenced.add(match[0].toUpperCase());\n }\n\n for (const id of referenced) {\n const known = knownAdrs.get(id);\n\n if (known === undefined) {\n findings.push({\n severity: \"error\",\n check: \"drift-adr-reference\",\n message: `Repository memory references ${id} but no matching ADR exists.`,\n path: file,\n });\n continue;\n }\n\n if (!known.accepted) {\n findings.push({\n severity: \"warning\",\n check: \"drift-proposed-reference\",\n message: `Repository memory references ${id} which is not accepted.`,\n path: file,\n });\n }\n }\n }\n\n return findings;\n}\n\nfunction stripCode(content: string): string {\n return content\n .replace(/```[\\s\\S]*?```/gu, \" \")\n .replace(/~~~[\\s\\S]*?~~~/gu, \" \")\n .replace(/`[^`]*`/gu, \" \");\n}\n\nasync function readMarkdownFiles(rootDir: string, relativeDir: string): Promise<string[]> {\n const entries = await readDirIfExists(rootDir, relativeDir);\n const files: string[] = [];\n\n for (const entry of entries) {\n const childRelative = path.posix.join(relativeDir, entry.name);\n\n if (entry.isDirectory()) {\n files.push(...(await readMarkdownFiles(rootDir, childRelative)));\n continue;\n }\n\n if (entry.isFile() && entry.name.toLowerCase().endsWith(\".md\")) {\n files.push(childRelative);\n }\n }\n\n return files;\n}\n\nfunction sectionContains(content: string, heading: string, pattern: RegExp): boolean {\n const section = getSection(content, heading);\n return section !== undefined && pattern.test(section);\n}\n\nfunction getSection(content: string, heading: string): string | undefined {\n const lines = content.split(/\\r?\\n/u);\n const normalizedHeading = `## ${heading.toLowerCase()}`;\n const startIndex = lines.findIndex((line) => line.trim().toLowerCase() === normalizedHeading);\n\n if (startIndex === -1) {\n return undefined;\n }\n\n const body: string[] = [];\n\n for (let index = startIndex + 1; index < lines.length; index += 1) {\n if (/^##\\s+/u.test(lines[index])) {\n break;\n }\n\n body.push(lines[index]);\n }\n\n return body.join(\"\\n\").trim();\n}\n\nasync function readDirIfExists(rootDir: string, relativePath: string) {\n try {\n return await readdir(path.join(rootDir, relativePath), { withFileTypes: true });\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return [];\n }\n throw error;\n }\n}\n","import { lstat, readFile, readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { REQUIRED_ADR_SECTIONS } from \"../../adr/adr-sections.js\";\nimport type { DoctorCheckContext, DoctorFinding } from \"../doctor-check.js\";\n\nconst featureFolderPattern = /^F-\\d{3,}-[a-z0-9]+(?:-[a-z0-9]+)*$/u;\nconst adrFilePattern = /^ADR-\\d{4,}-[a-z0-9]+(?:-[a-z0-9]+)*\\.md$/u;\n\nconst requiredFeatureDocs = [\n \"PRD.md\",\n \"ACCEPTANCE.md\",\n \"ARCHITECTURE_IMPACT.md\",\n \"CHANGE_REQUESTS.md\",\n \"PLAN.md\",\n \"TASKS.md\",\n \"TEST_PLAN.md\",\n \"REVIEW.md\",\n \"COMPLETION_REPORT.md\",\n];\n\nconst requiredModuleDocs = [\"MODULE.md\", \"TASKS.md\", \"TEST_PLAN.md\", \"DECISIONS.md\"];\n\nconst requiredAdrSections = REQUIRED_ADR_SECTIONS;\n\nexport async function checkMemoryIntegrity(context: DoctorCheckContext): Promise<DoctorFinding[]> {\n if (context.config === undefined) {\n return [];\n }\n\n const findings: DoctorFinding[] = [];\n\n findings.push(...(await checkFeatureFolders(context.rootDir, context.config.featuresDir)));\n findings.push(...(await checkModuleFolders(context.rootDir, context.config.modulesDir)));\n findings.push(...(await checkAdrFiles(context.rootDir, context.config.adrDir)));\n\n return findings;\n}\n\nasync function checkFeatureFolders(rootDir: string, featuresDir: string): Promise<DoctorFinding[]> {\n const findings: DoctorFinding[] = [];\n const entries = await readDirIfExists(rootDir, featuresDir);\n const featureFolders = entries.filter(\n (entry) => entry.isDirectory() && featureFolderPattern.test(entry.name),\n );\n\n for (const featureFolder of featureFolders) {\n for (const requiredDoc of requiredFeatureDocs) {\n const filePath = path.posix.join(featuresDir, featureFolder.name, requiredDoc);\n if (!(await isFile(rootDir, filePath))) {\n findings.push({\n severity: \"error\",\n check: \"feature-memory\",\n message: \"Feature folder is missing a required doc.\",\n path: filePath,\n });\n }\n }\n }\n\n findings.push({\n severity: \"info\",\n check: \"feature-memory\",\n message: `${featureFolders.length} feature folders detected.`,\n });\n\n return findings;\n}\n\nasync function checkModuleFolders(rootDir: string, modulesDir: string): Promise<DoctorFinding[]> {\n const findings: DoctorFinding[] = [];\n const entries = await readDirIfExists(rootDir, modulesDir);\n const moduleFolders = entries.filter((entry) => entry.isDirectory());\n\n for (const moduleFolder of moduleFolders) {\n for (const requiredDoc of requiredModuleDocs) {\n const filePath = path.posix.join(modulesDir, moduleFolder.name, requiredDoc);\n if (!(await isFile(rootDir, filePath))) {\n findings.push({\n severity: \"error\",\n check: \"module-memory\",\n message: \"Module folder is missing a required doc.\",\n path: filePath,\n });\n }\n }\n }\n\n findings.push({\n severity: \"info\",\n check: \"module-memory\",\n message: `${moduleFolders.length} module folders detected.`,\n });\n\n return findings;\n}\n\nasync function checkAdrFiles(rootDir: string, adrDir: string): Promise<DoctorFinding[]> {\n const findings: DoctorFinding[] = [];\n const entries = await readDirIfExists(rootDir, adrDir);\n const adrFiles = entries.filter((entry) => entry.isFile() && adrFilePattern.test(entry.name));\n\n for (const adrFile of adrFiles) {\n const filePath = path.posix.join(adrDir, adrFile.name);\n const content = await readFile(path.join(rootDir, filePath), \"utf8\");\n\n for (const requiredSection of requiredAdrSections) {\n if (!content.includes(requiredSection)) {\n findings.push({\n severity: \"error\",\n check: \"adr-memory\",\n message: `ADR file is missing required section ${requiredSection}.`,\n path: filePath,\n });\n }\n }\n }\n\n findings.push({\n severity: \"info\",\n check: \"adr-memory\",\n message: `${adrFiles.length} ADRs detected.`,\n });\n\n return findings;\n}\n\nasync function readDirIfExists(rootDir: string, relativePath: string) {\n try {\n return await readdir(path.join(rootDir, relativePath), { withFileTypes: true });\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return [];\n }\n throw error;\n }\n}\n\nasync function isFile(rootDir: string, relativePath: string): Promise<boolean> {\n try {\n return (await lstat(path.join(rootDir, relativePath))).isFile();\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return false;\n }\n throw error;\n }\n}\n","/**\n * The section headings every accepted ADR must contain. This is the single source of truth:\n * `recall doctor` validates against it, and every generator that emits a proposed ADR\n * (presets, `recall mcp add`, `recall adopt`) normalizes its body to include all of them — so a\n * proposed ADR stays healthy once a human promotes it with `recall adr accept`.\n */\nexport const REQUIRED_ADR_SECTIONS = [\n \"## Status\",\n \"## Context\",\n \"## Decision\",\n \"## Alternatives Considered\",\n \"## Consequences\",\n \"## Related Documents\",\n] as const;\n\nconst SECTION_PLACEHOLDERS: Record<string, string> = {\n \"## Related Documents\":\n \"- None yet. Link related ADRs, features, or modules as they are accepted.\",\n};\n\n/**\n * Append any required ADR section missing from `body`, using a neutral proposed-stage placeholder.\n * Idempotent: a body that already contains every required section is returned unchanged (aside from\n * a single trailing newline). Generated proposed ADRs historically stopped at `## Consequences`,\n * which made them fail Doctor's `## Related Documents` check the moment they were accepted.\n */\nexport function ensureRequiredAdrSections(body: string): string {\n let result = body.replace(/\\s+$/u, \"\");\n\n for (const section of REQUIRED_ADR_SECTIONS) {\n if (!result.includes(section)) {\n const placeholder = SECTION_PLACEHOLDERS[section] ?? \"To be documented.\";\n result += `\\n\\n${section}\\n\\n${placeholder}`;\n }\n }\n\n return `${result}\\n`;\n}\n","import { lstat } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport type { DoctorCheckContext, DoctorFinding } from \"../doctor-check.js\";\n\nconst rootFiles = [\"AGENTS.md\", \"CLAUDE.md\"];\n\nconst requiredDocs = [\n \"00-product/PRD.md\",\n \"00-product/BRD.md\",\n \"10-architecture/ARCHITECTURE.md\",\n \"10-architecture/MEMORY_ENGINE.md\",\n \"10-architecture/FILE_WRITE_POLICY.md\",\n \"20-security/SECURITY_MODEL.md\",\n \"20-security/THREAT_MODEL.md\",\n \"50-quality/TESTING_STRATEGY.md\",\n \"50-quality/QUALITY_GATES.md\",\n \"60-engineering/ENGINEERING_STANDARDS.md\",\n \"60-engineering/AI_AGENT_RULES.md\",\n \"ai/AI_AGENTS_SKILLS_MCP_STRATEGY.md\",\n \"ai/MCP_STRATEGY.md\",\n \"ai/RECALL_COMMANDS.md\",\n];\n\nexport async function checkRequiredFiles(context: DoctorCheckContext): Promise<DoctorFinding[]> {\n const findings: DoctorFinding[] = [];\n const docsDir = context.config?.docsDir ?? \"docs\";\n\n for (const filePath of rootFiles) {\n if (!(await isFile(context.rootDir, filePath))) {\n findings.push(missingFile(filePath, \"required-files\"));\n }\n }\n\n for (const relativeDocPath of requiredDocs) {\n const filePath = path.posix.join(docsDir, relativeDocPath);\n if (!(await isFile(context.rootDir, filePath))) {\n findings.push(missingFile(filePath, \"required-docs\"));\n }\n }\n\n const adrIndexPath = path.posix.join(context.config?.adrDir ?? \"docs/adrs\", \"README.md\");\n if (!(await isFile(context.rootDir, adrIndexPath))) {\n findings.push(missingFile(adrIndexPath, \"required-docs\"));\n }\n\n if (context.config !== undefined) {\n const requiredDirectories = [\n context.config.docsDir,\n context.config.featuresDir,\n context.config.modulesDir,\n context.config.adrDir,\n ];\n\n for (const directoryPath of requiredDirectories) {\n if (!(await isDirectory(context.rootDir, directoryPath))) {\n findings.push({\n severity: \"error\",\n check: \"configured-directories\",\n message: \"Configured directory is missing.\",\n path: directoryPath,\n });\n }\n }\n }\n\n return findings;\n}\n\nasync function isFile(rootDir: string, relativePath: string): Promise<boolean> {\n try {\n return (await lstat(path.join(rootDir, relativePath))).isFile();\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return false;\n }\n throw error;\n }\n}\n\nasync function isDirectory(rootDir: string, relativePath: string): Promise<boolean> {\n try {\n return (await lstat(path.join(rootDir, relativePath))).isDirectory();\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return false;\n }\n throw error;\n }\n}\n\nfunction missingFile(pathValue: string, check: string): DoctorFinding {\n return {\n severity: \"error\",\n check,\n message: \"Required file is missing.\",\n path: pathValue,\n };\n}\n","import { lstat, readFile, readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport type { DoctorCheckContext, DoctorFinding } from \"../doctor-check.js\";\n\nconst featureFolderPattern = /^F-\\d{3,}-[a-z0-9]+(?:-[a-z0-9]+)*$/u;\nconst adrFilePattern = /^ADR-\\d{4,}-[a-z0-9]+(?:-[a-z0-9]+)*\\.md$/u;\n\nconst securitySensitivePattern =\n /\\b(auth|authentication|authorization|secrets?|storage|networking?|telemetry|file writes?|write policy|dependencies?|mcp|ai api|cloud|runtime)\\b/iu;\n\nexport async function checkStandards(context: DoctorCheckContext): Promise<DoctorFinding[]> {\n if (context.config === undefined) {\n return [];\n }\n\n const findings: DoctorFinding[] = [];\n\n findings.push(...(await checkFeatureStandards(context.rootDir, context.config.featuresDir)));\n findings.push(...(await checkAdrStandards(context.rootDir, context.config.adrDir)));\n\n return findings;\n}\n\nasync function checkFeatureStandards(\n rootDir: string,\n featuresDir: string,\n): Promise<DoctorFinding[]> {\n const findings: DoctorFinding[] = [];\n const entries = await readDirIfExists(rootDir, featuresDir);\n const featureFolders = entries.filter(\n (entry) => entry.isDirectory() && featureFolderPattern.test(entry.name),\n );\n\n for (const featureFolder of featureFolders) {\n const featureDir = path.posix.join(featuresDir, featureFolder.name);\n const completionReportPath = path.posix.join(featureDir, \"COMPLETION_REPORT.md\");\n const reviewPath = path.posix.join(featureDir, \"REVIEW.md\");\n const architectureImpactPath = path.posix.join(featureDir, \"ARCHITECTURE_IMPACT.md\");\n\n const completionReport = await readFileIfExists(rootDir, completionReportPath);\n const review = await readFileIfExists(rootDir, reviewPath);\n const architectureImpact = await readFileIfExists(rootDir, architectureImpactPath);\n\n if (completionReport !== undefined) {\n const featureIsComplete = sectionContains(completionReport, \"Status\", /\\bcomplete\\b/iu);\n\n if (featureIsComplete) {\n if (review !== undefined && sectionContains(review, \"Status\", /\\bpending\\b/iu)) {\n findings.push({\n severity: \"error\",\n check: \"standards-feature-completion\",\n message: \"Feature is marked complete but review is still pending.\",\n path: reviewPath,\n });\n }\n\n if (!hasMeaningfulSection(completionReport, \"Tests Run\")) {\n findings.push({\n severity: \"error\",\n check: \"standards-feature-completion\",\n message: \"Feature is marked complete but completion report is missing test evidence.\",\n path: completionReportPath,\n });\n }\n\n if (!hasMeaningfulSection(completionReport, \"Results\")) {\n findings.push({\n severity: \"error\",\n check: \"standards-feature-completion\",\n message: \"Feature is marked complete but completion report is missing result evidence.\",\n path: completionReportPath,\n });\n }\n }\n\n if (architectureImpact !== undefined) {\n findings.push(\n ...checkSecurityImpactEvidence(\n architectureImpact,\n architectureImpactPath,\n featureIsComplete,\n ),\n );\n }\n }\n }\n\n return findings;\n}\n\nasync function checkAdrStandards(rootDir: string, adrDir: string): Promise<DoctorFinding[]> {\n const findings: DoctorFinding[] = [];\n const entries = await readDirIfExists(rootDir, adrDir);\n const adrFiles = entries.filter((entry) => entry.isFile() && adrFilePattern.test(entry.name));\n\n for (const adrFile of adrFiles) {\n const adrPath = path.posix.join(adrDir, adrFile.name);\n const content = await readFile(path.join(rootDir, adrPath), \"utf8\");\n const isAccepted = sectionContains(content, \"Status\", /\\baccepted\\b/iu);\n\n if (!hasMeaningfulSection(content, \"Consequences\")) {\n findings.push({\n severity: isAccepted ? \"error\" : \"warning\",\n check: \"standards-adr-consequences\",\n message: \"ADR consequence evidence is incomplete.\",\n path: adrPath,\n });\n }\n }\n\n return findings;\n}\n\nfunction checkSecurityImpactEvidence(\n architectureImpact: string,\n architectureImpactPath: string,\n featureIsComplete: boolean,\n): DoctorFinding[] {\n const contentWithoutSecuritySection = removeSection(architectureImpact, \"Security Impact\");\n\n if (!securitySensitivePattern.test(contentWithoutSecuritySection)) {\n return [];\n }\n\n if (hasMeaningfulSection(architectureImpact, \"Security Impact\")) {\n return [];\n }\n\n return [\n {\n severity: featureIsComplete ? \"error\" : \"warning\",\n check: \"standards-security-impact\",\n message: \"Security-sensitive feature planning is missing security impact evidence.\",\n path: architectureImpactPath,\n },\n ];\n}\n\nfunction sectionContains(content: string, heading: string, pattern: RegExp): boolean {\n const section = getSection(content, heading);\n return section !== undefined && pattern.test(section);\n}\n\nfunction hasMeaningfulSection(content: string, heading: string): boolean {\n const section = getSection(content, heading);\n return section !== undefined && !isPlaceholder(section);\n}\n\nfunction getSection(content: string, heading: string): string | undefined {\n const lines = content.split(/\\r?\\n/u);\n const startIndex = findSectionStart(lines, heading);\n\n if (startIndex === -1) {\n return undefined;\n }\n\n const body: string[] = [];\n\n for (let index = startIndex + 1; index < lines.length; index += 1) {\n if (/^##\\s+/u.test(lines[index])) {\n break;\n }\n\n body.push(lines[index]);\n }\n\n return body.join(\"\\n\").trim();\n}\n\nfunction removeSection(content: string, heading: string): string {\n const lines = content.split(/\\r?\\n/u);\n const startIndex = findSectionStart(lines, heading);\n\n if (startIndex === -1) {\n return content;\n }\n\n let endIndex = lines.length;\n for (let index = startIndex + 1; index < lines.length; index += 1) {\n if (/^##\\s+/u.test(lines[index])) {\n endIndex = index;\n break;\n }\n }\n\n return [...lines.slice(0, startIndex), ...lines.slice(endIndex)].join(\"\\n\");\n}\n\nfunction findSectionStart(lines: string[], heading: string): number {\n const normalizedHeading = `## ${heading.toLowerCase()}`;\n\n return lines.findIndex((line) => line.trim().toLowerCase() === normalizedHeading);\n}\n\nfunction isPlaceholder(value: string): boolean {\n const normalized = value\n .replace(/[`*_>#-]/gu, \" \")\n .replace(/\\s+/gu, \" \")\n .trim()\n .toLowerCase()\n .replace(/\\.$/u, \"\");\n\n if (normalized.length === 0) {\n return true;\n }\n\n if (\n normalized === \"tbd\" ||\n normalized === \"todo\" ||\n normalized === \"pending\" ||\n normalized === \"pending review\" ||\n normalized === \"draft\" ||\n normalized === \"none\" ||\n normalized === \"n/a\" ||\n normalized === \"not available yet\" ||\n normalized === \"not run yet\"\n ) {\n return true;\n }\n\n return (\n normalized.includes(\"implementation is in progress\") ||\n normalized.includes(\"will be completed after implementation\")\n );\n}\n\nasync function readDirIfExists(rootDir: string, relativePath: string) {\n try {\n return await readdir(path.join(rootDir, relativePath), { withFileTypes: true });\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return [];\n }\n throw error;\n }\n}\n\nasync function readFileIfExists(\n rootDir: string,\n relativePath: string,\n): Promise<string | undefined> {\n try {\n if (!(await isFile(rootDir, relativePath))) {\n return undefined;\n }\n\n return await readFile(path.join(rootDir, relativePath), \"utf8\");\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return undefined;\n }\n throw error;\n }\n}\n\nasync function isFile(rootDir: string, relativePath: string): Promise<boolean> {\n try {\n return (await lstat(path.join(rootDir, relativePath))).isFile();\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return false;\n }\n throw error;\n }\n}\n","import { readFile, readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport type { DoctorCheckContext, DoctorFinding } from \"../doctor-check.js\";\n\nconst adrFilePattern = /^ADR-(\\d{4,})-[a-z0-9]+(?:-[a-z0-9]+)*\\.md$/iu;\nconst adrReferencePattern = /ADR-\\d{4,}/giu;\n\n/**\n * Deterministic, local, read-only superseded-reference check.\n *\n * When a decision changes, `recall adr supersede` marks the old ADR \"Accepted — superseded by …\" and\n * records a new accepted ADR. This check flags feature or module memory that still cites the\n * superseded ADR as authority, so the reasoning trail gets updated instead of silently going stale.\n * It only fires when a superseded ADR exists and is still referenced — a repository with none stays\n * green. Semantic agreement between docs is left to the agent; this only follows the explicit\n * supersede trail.\n */\nexport async function checkSuperseded(context: DoctorCheckContext): Promise<DoctorFinding[]> {\n if (context.config === undefined) {\n return [];\n }\n\n const supersededIds = await loadSupersededAdrIds(context.rootDir, context.config.adrDir);\n if (supersededIds.size === 0) {\n return [];\n }\n\n const findings: DoctorFinding[] = [];\n findings.push(\n ...(await checkReferences(context.rootDir, context.config.featuresDir, supersededIds)),\n );\n findings.push(\n ...(await checkReferences(context.rootDir, context.config.modulesDir, supersededIds)),\n );\n\n return findings;\n}\n\nasync function loadSupersededAdrIds(rootDir: string, adrDir: string): Promise<Set<string>> {\n const superseded = new Set<string>();\n const files = await readMarkdownFiles(rootDir, adrDir);\n\n for (const file of files) {\n const match = adrFilePattern.exec(path.basename(file));\n if (match === null) {\n continue;\n }\n\n const content = await readFile(path.join(rootDir, file), \"utf8\");\n if (statusContains(content, /superseded\\s+by/iu)) {\n superseded.add(`ADR-${match[1]}`.toUpperCase());\n }\n }\n\n return superseded;\n}\n\nasync function checkReferences(\n rootDir: string,\n referenceDir: string,\n supersededIds: Set<string>,\n): Promise<DoctorFinding[]> {\n const findings: DoctorFinding[] = [];\n const files = await readMarkdownFiles(rootDir, referenceDir);\n\n for (const file of files) {\n const content = await readFile(path.join(rootDir, file), \"utf8\");\n const referenced = new Set<string>();\n\n // Ignore ADR identifiers inside fenced code blocks and inline code (illustrative examples).\n for (const match of stripCode(content).matchAll(adrReferencePattern)) {\n referenced.add(match[0].toUpperCase());\n }\n\n for (const id of referenced) {\n if (supersededIds.has(id)) {\n findings.push({\n severity: \"warning\",\n check: \"superseded-reference\",\n message: `Repository memory references ${id}, which has been superseded — update it to the current decision.`,\n path: file,\n });\n }\n }\n }\n\n return findings;\n}\n\nfunction statusContains(content: string, pattern: RegExp): boolean {\n const lines = content.split(/\\r?\\n/u);\n const startIndex = lines.findIndex((line) => line.trim().toLowerCase() === \"## status\");\n if (startIndex === -1) {\n return false;\n }\n\n const body: string[] = [];\n for (let index = startIndex + 1; index < lines.length; index += 1) {\n if (/^##\\s+/u.test(lines[index])) {\n break;\n }\n body.push(lines[index]);\n }\n\n return pattern.test(body.join(\"\\n\"));\n}\n\nfunction stripCode(content: string): string {\n return content\n .replace(/```[\\s\\S]*?```/gu, \" \")\n .replace(/~~~[\\s\\S]*?~~~/gu, \" \")\n .replace(/`[^`]*`/gu, \" \");\n}\n\nasync function readMarkdownFiles(rootDir: string, relativeDir: string): Promise<string[]> {\n const entries = await readDirIfExists(rootDir, relativeDir);\n const files: string[] = [];\n\n for (const entry of entries) {\n const childRelative = path.posix.join(relativeDir, entry.name);\n\n if (entry.isDirectory()) {\n files.push(...(await readMarkdownFiles(rootDir, childRelative)));\n continue;\n }\n\n if (entry.isFile() && entry.name.toLowerCase().endsWith(\".md\")) {\n files.push(childRelative);\n }\n }\n\n return files;\n}\n\nasync function readDirIfExists(rootDir: string, relativePath: string) {\n try {\n return await readdir(path.join(rootDir, relativePath), { withFileTypes: true });\n } catch (error) {\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n return [];\n }\n throw error;\n }\n}\n","import { checkCodeReferences } from \"./checks/code-reference-check.js\";\nimport { checkConfig } from \"./checks/config-check.js\";\nimport { checkContent } from \"./checks/content-check.js\";\nimport { checkDrift } from \"./checks/drift-check.js\";\nimport { checkMemoryIntegrity } from \"./checks/memory-integrity-check.js\";\nimport { checkRequiredFiles } from \"./checks/required-files-check.js\";\nimport { checkStandards } from \"./checks/standards-check.js\";\nimport { checkSuperseded } from \"./checks/superseded-check.js\";\n\nexport type DoctorSeverity = \"error\" | \"warning\" | \"info\";\n\nexport type DoctorFinding = {\n severity: DoctorSeverity;\n check: string;\n message: string;\n path?: string;\n};\n\nexport type DoctorReport = {\n findings: DoctorFinding[];\n summary: {\n errors: number;\n warnings: number;\n info: number;\n };\n};\n\nexport type DoctorCheckContext = {\n rootDir: string;\n config?: {\n docsDir: string;\n featuresDir: string;\n modulesDir: string;\n adrDir: string;\n };\n};\n\nexport type DoctorCheck = (\n context: DoctorCheckContext,\n) => Promise<DoctorFinding[]> | DoctorFinding[];\n\nexport async function runDoctor(rootDir: string): Promise<DoctorReport> {\n const findings: DoctorFinding[] = [];\n const configResult = await checkConfig(rootDir);\n\n findings.push(...configResult.findings);\n\n const context: DoctorCheckContext = {\n rootDir,\n config: configResult.config,\n };\n\n findings.push(...(await checkRequiredFiles(context)));\n\n if (configResult.config !== undefined) {\n findings.push(...(await checkMemoryIntegrity(context)));\n findings.push(...(await checkStandards(context)));\n findings.push(...(await checkDrift(context)));\n findings.push(...(await checkContent(context)));\n findings.push(...(await checkCodeReferences(context)));\n findings.push(...(await checkSuperseded(context)));\n }\n\n return createDoctorReport(findings);\n}\n\nexport function createDoctorReport(findings: DoctorFinding[]): DoctorReport {\n return {\n findings,\n summary: {\n errors: findings.filter((finding) => finding.severity === \"error\").length,\n warnings: findings.filter((finding) => finding.severity === \"warning\").length,\n info: findings.filter((finding) => finding.severity === \"info\").length,\n },\n };\n}\n","import type { DoctorFinding, DoctorReport } from \"./doctor-check.js\";\n\nconst severityOrder = [\"error\", \"warning\", \"info\"] as const;\n\nexport function getDoctorExitCode(report: DoctorReport): 0 | 1 | 2 {\n if (report.summary.errors > 0) {\n return 2;\n }\n\n if (report.summary.warnings > 0) {\n return 1;\n }\n\n return 0;\n}\n\nexport function formatDoctorReport(report: DoctorReport): string {\n const lines = [\"Doctor Report\", \"\"];\n\n for (const severity of severityOrder) {\n const findings = report.findings.filter((finding) => finding.severity === severity);\n\n if (findings.length === 0) {\n continue;\n }\n\n lines.push(severity.toUpperCase());\n for (const finding of findings) {\n lines.push(`- ${formatFinding(finding)}`);\n }\n lines.push(\"\");\n }\n\n if (report.findings.length === 0) {\n lines.push(\"INFO\");\n lines.push(\"- No findings.\");\n lines.push(\"\");\n }\n\n lines.push(`Result: ${formatResult(report)}`);\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction formatFinding(finding: DoctorFinding): string {\n if (finding.path === undefined) {\n return finding.message;\n }\n\n return `${finding.message} (${finding.path})`;\n}\n\nfunction formatResult(report: DoctorReport): string {\n if (report.summary.errors > 0) {\n return \"FAILED\";\n }\n\n if (report.summary.warnings > 0) {\n return \"WARNINGS\";\n }\n\n return \"PASSED\";\n}\n","import { runDoctor, type DoctorReport } from \"../core/doctor/doctor-check.js\";\nimport { formatDoctorReport, getDoctorExitCode } from \"../core/doctor/doctor-report.js\";\n\nexport type DoctorOptions = {\n rootDir: string;\n};\n\nexport type DoctorResult = {\n report: DoctorReport;\n exitCode: 0 | 1 | 2;\n};\n\nexport async function doctorProject(options: DoctorOptions): Promise<DoctorResult> {\n const report = await runDoctor(options.rootDir);\n\n return {\n report,\n exitCode: getDoctorExitCode(report),\n };\n}\n\nexport function formatDoctorResult(result: DoctorResult): string {\n return formatDoctorReport(result.report);\n}\n","import { existsSync } from \"node:fs\";\nimport path from \"node:path\";\n\nimport { createDefaultConfig } from \"../core/config/default-config.js\";\nimport { CONFIG_PATH } from \"../core/config/load-config.js\";\nimport {\n createWritePlan,\n type WritePlan,\n type WriteFileInput,\n} from \"../core/filesystem/write-plan.js\";\nimport { executeWritePlan, type WriteResult } from \"../core/filesystem/write-file-safe.js\";\nimport { inspectRepo, summarizeSignals, type RepoSignals } from \"../core/adopt/inspect-repo.js\";\nimport { generateInitFiles } from \"../core/generator/generate-init.js\";\nimport { detectPreCommitGates } from \"../core/hooks/detect-gates.js\";\nimport {\n CLAUDE_SETTINGS_PATH,\n HOOKS_PATH_ACTIVATION_COMMAND,\n PRE_COMMIT_HOOK_PATH,\n SESSION_START_HOOK_PATH,\n renderClaudeSettings,\n renderPreCommitHook,\n renderSessionStartHook,\n} from \"../core/hooks/generate-hook.js\";\nimport { getPreset } from \"../core/presets/preset-registry.js\";\nimport type { Preset } from \"../core/presets/preset-schema.js\";\nimport { generateSkillFiles } from \"../core/skills/generate-skill.js\";\nimport { listCatalogSkillNames } from \"../core/skills/skill-catalog.js\";\nimport { appendNextSteps, appendWriteSummary } from \"./write-summary.js\";\n\nexport type InitOptions = {\n rootDir: string;\n preset?: string;\n dryRun?: boolean;\n force?: boolean;\n reinit?: boolean;\n};\n\nexport type InitResult = {\n preset: string | null;\n dryRun: boolean;\n plan: WritePlan;\n writeResult: WriteResult;\n detected: RepoSignals;\n};\n\nexport type InitErrorCode = \"UNKNOWN_PRESET\" | \"WRITE_PLAN_ERROR\" | \"EXISTING_INSTALLATION\";\n\nexport class InitError extends Error {\n readonly code: InitErrorCode;\n readonly details: string[];\n\n constructor(code: InitErrorCode, message: string, details: string[] = []) {\n super(message);\n this.name = \"InitError\";\n this.code = code;\n this.details = details;\n }\n}\n\nexport async function initProject(options: InitOptions): Promise<InitResult> {\n if (\n options.force === true &&\n options.reinit !== true &&\n existsSync(path.join(options.rootDir, CONFIG_PATH))\n ) {\n throw new InitError(\n \"EXISTING_INSTALLATION\",\n \"Refusing to re-initialize an existing Recall OS installation.\",\n [\n \"An existing .recall/config.json was found in this directory.\",\n \"Running init --force here would overwrite existing repository memory.\",\n \"Pass --reinit together with --force to overwrite an existing installation.\",\n ],\n );\n }\n\n const preset = resolvePreset(options.preset);\n // Read-only inspection of the existing repository so init can surface the detected stack (proposed,\n // never accepted) — run before writes so it reflects the user's repo, not our generated scaffold.\n const detected = await inspectRepo(options.rootDir);\n const preCommitGates = await detectPreCommitGates(options.rootDir);\n const config = createDefaultConfig({ preset: preset?.id ?? null, preCommitGates });\n const files = createInitWriteFiles(options.rootDir, config, preset);\n const plan = createWritePlan({\n rootDir: options.rootDir,\n files,\n force: options.force,\n });\n\n if (plan.hasErrors) {\n throw new InitError(\n \"WRITE_PLAN_ERROR\",\n \"Recall OS init write plan contains errors.\",\n plan.entries\n .filter((entry) => entry.action === \"error\")\n .map((entry) => `${entry.path}: ${entry.reason}`),\n );\n }\n\n const writeResult = await executeWritePlan(plan, { dryRun: options.dryRun });\n\n return {\n preset: preset?.id ?? null,\n dryRun: options.dryRun ?? false,\n plan,\n writeResult,\n detected,\n };\n}\n\nexport function formatInitResult(result: InitResult): string {\n const lines = [\n result.dryRun ? \"Recall OS init dry run complete.\" : \"Recall OS init complete.\",\n `Preset: ${result.preset ?? \"none\"}`,\n ];\n\n if (!result.dryRun) {\n lines.push(\n `Generated repository memory, ${listCatalogSkillNames().length} agent skills, a pre-commit hook, a CI workflow, a Claude SessionStart hook, and a Cursor rule that load memory automatically.`,\n );\n }\n\n appendWriteSummary(lines, {\n dryRun: result.dryRun,\n writeResult: result.writeResult,\n });\n\n appendDetectedStack(lines, result.detected);\n\n const hookWritten =\n result.writeResult.created.includes(PRE_COMMIT_HOOK_PATH) ||\n result.writeResult.overwritten.includes(PRE_COMMIT_HOOK_PATH);\n\n if (hookWritten) {\n lines.push(\"\");\n lines.push(\n result.dryRun\n ? \"Pre-commit hook will be written to .recall/hooks/pre-commit.\"\n : \"Pre-commit hook written to .recall/hooks/pre-commit.\",\n );\n lines.push(`Enable it once per clone: ${HOOKS_PATH_ACTIVATION_COMMAND}`);\n }\n\n if (!result.dryRun) {\n appendNextSteps(lines, [\n \"Read CLAUDE.md and AGENTS.md, then the docs/ memory they point to.\",\n \"AI agent skills are in .claude/skills/ and .agents/skills/ — restart your AI tool to load them.\",\n \"Memory loads automatically per tool: a Claude SessionStart hook (.claude/hooks/session-start.sh), a Cursor rule (.cursor/rules/recall-memory.mdc), and AGENTS.md for Codex.\",\n \"CI is wired in .github/workflows/recall.yml; the pre-commit hook is in .recall/hooks/.\",\n \"Plan your first feature: `recall feature create <name>`.\",\n \"Record a decision: `recall adr create <title>`, then accept it with `recall adr accept`.\",\n \"Check repository memory health anytime: `recall doctor`.\",\n ]);\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction appendDetectedStack(lines: string[], detected: RepoSignals): void {\n const hasSignal =\n detected.languages.length > 0 ||\n detected.frameworks.length > 0 ||\n detected.packageManager !== null ||\n detected.testsEvidence !== null;\n\n if (!hasSignal) {\n return;\n }\n\n // Stack-relevant lines only; README/docs presence is noise right after init writes docs/.\n const stack = summarizeSignals(detected).filter(\n (line) => !line.startsWith(\"- README\") && !line.startsWith(\"- Docs\"),\n );\n\n lines.push(\"\");\n lines.push(\"Detected in this repository (proposed — review, nothing was accepted):\");\n lines.push(...stack);\n lines.push(\n \"If any signal is wrong, correct the source file noted. Run `recall adopt` to record this as proposed memory.\",\n );\n}\n\nfunction resolvePreset(presetId: string | undefined): Preset | null {\n if (presetId === undefined) {\n return null;\n }\n\n const preset = getPreset(presetId);\n\n if (preset === undefined) {\n throw new InitError(\"UNKNOWN_PRESET\", `Unknown preset \"${presetId}\".`);\n }\n\n return preset;\n}\n\nfunction createInitWriteFiles(\n rootDir: string,\n config: ReturnType<typeof createDefaultConfig>,\n preset: Preset | null,\n): WriteFileInput[] {\n return [\n {\n path: CONFIG_PATH,\n content: `${JSON.stringify(config, null, 2)}\\n`,\n },\n ...generateInitFiles({ rootDir, preset }),\n {\n path: PRE_COMMIT_HOOK_PATH,\n content: renderPreCommitHook(config.preCommitGates),\n executable: true,\n },\n // A Claude Code SessionStart hook that injects a memory map every session, so a fresh agent\n // reliably loads durable memory, plus the settings that wire it (skipped if settings exist).\n {\n path: SESSION_START_HOOK_PATH,\n content: renderSessionStartHook(),\n executable: true,\n },\n {\n path: CLAUDE_SETTINGS_PATH,\n content: renderClaudeSettings(),\n },\n // Generate the agent skill set so a fresh repo has the workflows that guide AI agents,\n // not just the docs. Written to both the Claude and portable Agent Skills targets.\n ...listCatalogSkillNames().flatMap((name) => generateSkillFiles(name).files),\n ];\n}\n","import path from \"node:path\";\n\nimport { ensureRequiredAdrSections } from \"../adr/adr-sections.js\";\nimport type { WriteFileInput } from \"../filesystem/write-plan.js\";\nimport type { Preset } from \"../presets/preset-schema.js\";\nimport { createTemplateContext } from \"./template-context.js\";\nimport { renderTemplate } from \"./render-template.js\";\n\nexport type GenerateInitFilesOptions = {\n rootDir: string;\n preset?: Preset | null;\n};\n\ntype InitTemplate = {\n path: string;\n content: string;\n};\n\nconst neutralTemplates: InitTemplate[] = [\n {\n path: \"AGENTS.md\",\n content: `# {{repositoryName}} Agent Instructions\n\nThis repository uses Recall OS repository memory.\n\nStart with durable source-of-truth docs under \\`docs/\\`.\n\nRequired reading:\n\n- \\`docs/00-product/PRD.md\\`\n- \\`docs/10-architecture/ARCHITECTURE.md\\`\n- \\`docs/20-security/SECURITY_MODEL.md\\`\n- \\`docs/50-quality/QUALITY_GATES.md\\`\n- \\`docs/60-engineering/ENGINEERING_STANDARDS.md\\`\n\nRepository rules override model preferences. If instructions conflict, stop and report the conflict.\n\n## Recall OS commands\n\nThis repository is maintained with the Recall OS CLI. Use these commands yourself as you work — do not\nask the human to run them, and do not search the web for them (this is a project-local tool):\n\n- \\`recall doctor\\` — validate repository memory; run it before claiming any work is complete.\n- \\`recall feature create <name>\\` — scaffold feature memory before non-trivial feature work.\n- \\`recall adr create <title>\\` — propose a decision; \\`recall adr accept <name>\\` accepts it.\n- \\`recall adr supersede <old> <new-title>\\` — record a changed decision (never overwrite an accepted ADR).\n- \\`recall module create <name>\\` — scaffold module memory for a new responsibility boundary.\n- \\`recall mcp add <server>\\` — capture an MCP tool's context into memory, offline.\n\nFull command reference: \\`docs/ai/RECALL_COMMANDS.md\\`.\n\n## Changing an accepted decision\n\nBefore changing anything an accepted ADR governs (framework, database, auth, API shape, and similar):\n\n1. Check \\`docs/adrs/\\` for an accepted ADR that covers it.\n2. If your change contradicts one, stop and confirm with a human first — do not silently change the\n code and leave the ADR saying the opposite.\n3. Record the change as a new decision with \\`recall adr supersede <old> <new-title>\\`. That supersedes\n the old ADR instead of overwriting history, so the reasoning stays auditable.\n\nRepository memory is only trustworthy if decisions change through this trail, not silently.\n`,\n },\n {\n path: \"CLAUDE.md\",\n content: `# {{repositoryName}} Claude Instructions\n\nThis file is loaded automatically every Claude session. The durable project memory lives in \\`docs/\\`;\ndo not rely on chat history as source of truth, and repository rules override model preference.\n\n@AGENTS.md\n\nRead the docs that \\`AGENTS.md\\` routes to before changing code or repository memory. A SessionStart\nhook (\\`.claude/hooks/session-start.sh\\`) also injects a memory map at the start of each session.\n`,\n },\n {\n // Cursor auto-applies rules under .cursor/rules. alwaysApply makes this the portable equivalent\n // of the Claude Code SessionStart hook: Cursor injects it into every request so the agent loads\n // repository memory even though it cannot run the Claude-specific hook.\n path: \".cursor/rules/recall-memory.mdc\",\n content: `---\ndescription: {{repositoryName}} repository memory and rules (Recall OS). Read before non-trivial work.\nglobs:\nalwaysApply: true\n---\n\n# {{repositoryName}} repository memory\n\nThis repository uses Recall OS. Durable memory lives in \\`docs/\\` and is the source of truth over chat\nhistory. Do not treat chat history as truth, and repository rules override model preference.\n\nBefore non-trivial work:\n\n- Read \\`AGENTS.md\\` and the docs it routes to.\n- Accepted decisions live in \\`docs/adrs/\\`; module memory lives in \\`docs/30-modules/\\`.\n- If an instruction conflicts with accepted repository memory, stop and report the conflict.\n- Before changing what an accepted ADR governs, confirm with a human and record it with\n \\`recall adr supersede <old> <new-title>\\` — never silently contradict an accepted decision.\n\nSource-of-truth order: accepted ADRs and repository decisions, then architecture docs, engineering\nstandards, the current PRD, security and testing docs, module docs, feature plans, then chat history.\n\nRecall OS commands — use these yourself (do not web-search this project-local CLI): \\`recall doctor\\`,\n\\`recall feature create <name>\\`, \\`recall adr create <title>\\` then \\`recall adr accept <name>\\`,\n\\`recall adr supersede <old> <new-title>\\`, \\`recall module create <name>\\`, \\`recall mcp add <server>\\`.\nFull reference: \\`docs/ai/RECALL_COMMANDS.md\\`.\n\nBefore claiming work is complete, run \\`recall doctor\\` and fix reported errors.\n`,\n },\n {\n path: \"docs/00-product/PRD.md\",\n content: `# PRD: {{repositoryName}}\n\n## Purpose\n\nDescribe what this repository is building and why.\n\n## Current Status\n\nDraft.\n\n## Notes\n\nKeep product intent durable here. Do not rely on chat history as source of truth.\n`,\n },\n {\n path: \"docs/00-product/BRD.md\",\n content: `# BRD: {{repositoryName}}\n\n## Purpose\n\nDescribe the business goal, target users, and success criteria for this repository.\n\n## Current Status\n\nDraft.\n`,\n },\n {\n path: \"docs/10-architecture/ARCHITECTURE.md\",\n content: `# Architecture\n\n## Purpose\n\nDescribe the accepted architecture for this repository.\n\n## Current Status\n\nNo architecture decisions are accepted yet.\n\nUse ADRs to accept architecture choices.\n`,\n },\n {\n path: \"docs/10-architecture/MEMORY_ENGINE.md\",\n content: `# Repository Memory\n\nRepository memory is the durable source of truth for humans and AI agents.\n\nSource-of-truth order:\n\n1. Accepted ADRs and repository decisions\n2. Architecture docs\n3. Engineering standards\n4. Current PRD and accepted change requests\n5. Security and testing docs\n6. Module docs\n7. Feature plans\n8. Task files\n9. External context\n10. Chat history\n`,\n },\n {\n path: \"docs/10-architecture/FILE_WRITE_POLICY.md\",\n content: `# File Write Policy\n\nDefault behavior:\n\n- Skip existing files.\n- Use dry run before risky writes.\n- Require explicit force to overwrite.\n- Never write outside the repository root.\n`,\n },\n {\n path: \"docs/20-security/SECURITY_MODEL.md\",\n content: `# Security Model\n\n## Status\n\nDraft — fill the prompted sections below with this repository's real model as it grows. \\`recall doctor\\`\nflags these as warnings once the repository has real work (a feature, module, or accepted decision).\n\n## Baseline Rules\n\n- Never commit secrets or credentials, and never read or copy \\`.env\\` files into docs.\n- Validate and authorize untrusted input at every trust boundary.\n- Do not add network, telemetry, cloud, MCP runtime, or AI API behavior without explicit review.\n\n## Authentication And Authorization\n\nDescribe how this repository authenticates users or clients and how it authorizes actions, including\nwhere those checks live.\n\n## Secrets And Configuration\n\nDescribe where secrets live, how they are injected, and how configuration is kept out of version\ncontrol.\n\n## Sensitive Data\n\nDescribe the sensitive or personal data this repository handles, and how it is protected at rest and\nin transit.\n\n## Dependencies And Supply Chain\n\nDescribe how third-party dependencies are vetted, pinned, and updated.\n`,\n },\n {\n path: \"docs/20-security/THREAT_MODEL.md\",\n content: `# Threat Model\n\n## Status\n\nDraft — replace the prompts below with this repository's real analysis as it grows. \\`recall doctor\\`\nflags these as warnings once the repository has real work (a feature, module, or accepted decision).\n\n## Assets\n\nDescribe what this repository must protect: user data, credentials, money, availability, or\nreputation.\n\n## Entry Points\n\nDescribe where untrusted input enters: HTTP endpoints, webhooks, file uploads, queues, CLI input, or\nthird-party callbacks.\n\n## Trust Boundaries\n\nDescribe where trust changes: client to server, service to database, your code to third-party APIs.\n\n## Threats\n\nDescribe the concrete threats that apply to this repository, by category:\n\n- Spoofing — how identities are faked or sessions stolen.\n- Tampering — how requests, data, or builds are altered (injection, mass assignment).\n- Repudiation — actions that must remain auditable.\n- Information disclosure — how sensitive data or secrets could leak.\n- Denial of service — how the system can be overwhelmed or abused.\n- Elevation of privilege — how a user could gain access they should not have.\n\n## Mitigations\n\nDescribe the control in place or planned for each threat above.\n\n## Open Risks\n\nDescribe accepted or unresolved risks and who owns them.\n`,\n },\n {\n path: \"docs/50-quality/TESTING_STRATEGY.md\",\n content: `# Testing Strategy\n\nTests should derive from acceptance criteria, risk, security invariants, and module boundaries.\n\nDocument required unit, integration, security, and golden tests as the repository grows.\n`,\n },\n {\n path: \"docs/50-quality/QUALITY_GATES.md\",\n content: `# Quality Gates\n\nDo not claim completion without evidence.\n\nCompletion evidence should include:\n\n- Files changed.\n- Tests run.\n- Results.\n- Skipped checks.\n- Remaining risks.\n`,\n },\n {\n path: \"docs/60-engineering/ENGINEERING_STANDARDS.md\",\n content: `# Engineering Standards\n\nRepository rules override model preferences.\n\nBaseline rules:\n\n- Never commit secrets.\n- Keep changes scoped.\n- Update docs when behavior or architecture changes.\n- Add tests or document why tests were skipped.\n- Do not claim completion without evidence.\n`,\n },\n {\n path: \"docs/60-engineering/AI_AGENT_RULES.md\",\n content: `# AI Agent Rules\n\nAI agents must follow repository memory over model preference.\n\nIf a request conflicts with accepted repository memory or engineering standards, stop and report the conflict.\n\n## Changing an accepted decision\n\nWhen work would change something an accepted ADR governs:\n\n1. Find the accepted ADR in \\`docs/adrs/\\` that covers it.\n2. If the change contradicts it, stop and confirm with a human before changing the code.\n3. Record the new decision with \\`recall adr supersede <old> <new-title>\\` so the old ADR is marked\n superseded and the reasoning is preserved, instead of silently editing or contradicting it.\n`,\n },\n {\n path: \"docs/ai/AI_AGENTS_SKILLS_MCP_STRATEGY.md\",\n content: `# AI Agents, Skills, And MCP Strategy\n\nRoot agent files are entry points, not guarantees.\n\nDurable memory lives in \\`docs/\\`.\n\nMCP is optional external context and does not override accepted repository memory.\n`,\n },\n {\n path: \"docs/ai/MCP_STRATEGY.md\",\n content: `# MCP Strategy\n\nMCP is not required for this repository.\n\nIf MCP is introduced later, document trusted servers, data accessed, permissions, risks, and source-of-truth rules.\n`,\n },\n {\n path: \"docs/ai/RECALL_COMMANDS.md\",\n content: `# Recall OS Commands\n\nThis document records the Recall OS commands available to humans and AI agents.\n\n## Completion Gate\n\nBefore claiming implementation work is complete, run:\n\n\\`\\`\\`txt\npnpm test:run\npnpm typecheck\nrecall doctor\n\\`\\`\\`\n\nIf \\`recall doctor\\` reports errors, fix them or report why they cannot be fixed. If it reports\nwarnings, address them or record why they are acceptable.\n\nPackage binary behavior is covered by binary integration tests.\n\n## Commands\n\n### \\`recall init\\`\n\nInitialize neutral repository memory.\n\nOptions:\n\n- \\`--preset <id>\\`: apply optional preset guidance and proposed decisions.\n- \\`--dry-run\\`: show planned writes without writing files.\n- \\`--force\\`: overwrite existing files explicitly.\n- \\`--reinit\\`: required with \\`--force\\` to overwrite an existing Recall OS installation\n (a directory that already has \\`.recall/config.json\\`). Without it, \\`--force\\` refuses, protecting\n existing repository memory.\n\nInit also generates a tracked pre-commit hook at \\`.recall/hooks/pre-commit\\` that runs \\`recall doctor\\`\nplus any \\`preCommitGates\\` in \\`.recall/config.json\\`. Init proposes, but does not run, the activation\ncommand \\`git config core.hooksPath .recall/hooks\\`.\n\n### \\`recall adopt\\`\n\nInspect an existing repository through read-only manifest and marker files, then write a proposed\nadoption report and proposed framework ADRs for human review. Adopt never executes repository code\nand never produces accepted memory.\n\nOptions:\n\n- \\`--dry-run\\`: show planned writes without writing files.\n- \\`--force\\`: overwrite existing files explicitly.\n\n### \\`recall skill create <name>\\`\n\nGenerate a portable AI agent skill as \\`SKILL.md\\` for both Claude Code (\\`.claude/skills/\\`) and the\nportable Agent Skills target (\\`.agents/skills/\\`). Known names use the built-in catalog; unknown names\nproduce a valid skeleton. Generated skills contain no scripts.\n\nOptions:\n\n- \\`--dry-run\\`: show planned writes without writing files.\n- \\`--force\\`: overwrite existing files explicitly.\n\n### \\`recall skill list\\`\n\nList the built-in catalog skills.\n\n### \\`recall mcp add <server>\\`\n\nGenerate offline, proposed memory for an MCP server (for example \\`figma\\`) as \\`docs/ai/mcp/<server>.md\\`\nplus a proposed adoption ADR. Recall OS never connects to the MCP server or makes network calls; the\nagent records durable MCP-derived context into the generated memory for human review. It also\ninstalls a \\`capture-mcp-context\\` agent skill that prompts the agent to record that context.\n\nOptions:\n\n- \\`--dry-run\\`: show planned writes without writing files.\n- \\`--force\\`: overwrite existing files explicitly.\n\n### \\`recall preset list\\`\n\nList built-in presets.\n\n### \\`recall feature create <name>\\`\n\nCreate feature memory docs under the configured features directory.\n\nOptions:\n\n- \\`--dry-run\\`: show planned writes without writing files.\n- \\`--force\\`: overwrite existing files explicitly.\n\n### \\`recall adr create <title>\\`\n\nCreate a proposed ADR under the configured ADR directory.\n\nOptions:\n\n- \\`--dry-run\\`: show planned writes without writing files.\n- \\`--force\\`: overwrite existing files explicitly.\n\n### \\`recall adr accept <name>\\`\n\nPromote a proposed ADR to accepted repository memory. A proposal under\n\\`docs/adrs/proposed/ADR-PROPOSED-<slug>.md\\` becomes a numbered, accepted \\`ADR-####-<slug>.md\\` and the\nproposal is removed; an existing numbered Proposed ADR is accepted in place.\n\nOptions:\n\n- \\`--dry-run\\`: show planned writes without writing files.\n- \\`--force\\`: overwrite existing files explicitly.\n\n### \\`recall adr supersede <old> <new-title>\\`\n\nRecord a changed decision. Marks an accepted ADR as \\`Accepted — superseded by ADR-####\\` and creates a\nnew accepted ADR that declares what it supersedes, so the reasoning trail stays auditable instead of\nbeing overwritten. Doctor then warns about any memory still referencing the superseded decision.\n\nOptions:\n\n- \\`--dry-run\\`: show planned writes without writing files.\n- \\`--force\\`: overwrite existing files explicitly.\n\n### \\`recall module create <name>\\`\n\nCreate module memory docs under the configured modules directory.\n\nOptions:\n\n- \\`--dry-run\\`: show planned writes without writing files.\n- \\`--force\\`: overwrite existing files explicitly.\n\n### \\`recall doctor\\`\n\nCheck whether repository memory is structurally healthy enough for AI-assisted work, whether basic\nengineering evidence is present, and whether memory references decisions that exist and are accepted.\n\nDoctor also runs deterministic drift checks: feature or module memory that references a missing ADR\nis an error, memory that references a not-yet-accepted ADR is a warning, and memory that still\nreferences a superseded decision is a warning.\n\nExit codes:\n\n- \\`0\\`: healthy\n- \\`1\\`: warnings only\n- \\`2\\`: errors\n`,\n },\n {\n path: \"docs/30-modules/README.md\",\n content: `# Module Memory\n\nModule memory records what each important module owns, how it should be tested, and which decisions affect it.\n\nFuture module folders should use:\n\n\\`\\`\\`txt\ndocs/30-modules/<module>/\n MODULE.md\n TASKS.md\n TEST_PLAN.md\n DECISIONS.md\n\\`\\`\\`\n\nAgents should update module memory when implementation changes responsibilities, boundaries, tests, risks, or decisions.\n`,\n },\n {\n path: \"docs/40-features/README.md\",\n content: `# Feature Memory\n\nFeature memory records requirements, acceptance criteria, plans, tests, reviews, and completion evidence.\n\nFuture feature folders should use:\n\n\\`\\`\\`txt\ndocs/40-features/F-###-<feature>/\n PRD.md\n ACCEPTANCE.md\n ARCHITECTURE_IMPACT.md\n CHANGE_REQUESTS.md\n PLAN.md\n TASKS.md\n TEST_PLAN.md\n REVIEW.md\n COMPLETION_REPORT.md\n\\`\\`\\`\n\nAgents should not implement meaningful feature work without a feature plan or clear source-of-truth reference.\n`,\n },\n {\n path: \"docs/adrs/README.md\",\n content: `# Architecture Decision Records\n\nAccepted ADRs live in this directory as \\`ADR-####-<slug>.md\\` with \\`## Status\\` set to \\`Accepted\\`.\nProposed ADRs live under \\`docs/adrs/proposed/\\`.\n\nThere is no \\`accepted/\\` subdirectory: accepted ADRs sit at the top level of \\`docs/adrs/\\`.\n\nPresets and AI agents may propose decisions; humans accept them with \\`recall adr accept <name>\\`,\nwhich promotes a proposal into an accepted ADR here.\n`,\n },\n {\n path: \".github/workflows/recall.yml\",\n content: `name: Recall OS\n\non:\n push:\n pull_request:\n\njobs:\n doctor:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n - uses: actions/setup-node@v4\n with:\n node-version: 20\n - name: Validate repository memory\n run: npx --yes recall-os@latest doctor\n`,\n },\n];\n\nexport function generateInitFiles(options: GenerateInitFilesOptions): WriteFileInput[] {\n const repositoryName = path.basename(path.resolve(options.rootDir)) || \"repository\";\n const context = createTemplateContext({ repositoryName });\n const files = neutralTemplates.map((template) => ({\n path: template.path,\n content: renderTemplate(template.content, context),\n }));\n\n if (options.preset !== undefined && options.preset !== null) {\n files.push(...generatePresetFiles(options.preset));\n }\n\n return files;\n}\n\nfunction generatePresetFiles(preset: Preset): WriteFileInput[] {\n return [\n ...preset.templates.map((template) => ({\n path: template.destination,\n content: template.content,\n })),\n ...preset.proposedDecisions.map((decision) => ({\n path: decision.destination,\n // Normalize every preset's proposed ADR so it stays Doctor-healthy once accepted.\n content: ensureRequiredAdrSections(decision.body),\n })),\n ];\n}\n","import { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\n/**\n * Scripts that are reasonable to run as pre-commit gates when a target repository defines them.\n * Detection only proposes these as editable config values; it never encodes them as core truth.\n */\nconst KNOWN_SCRIPTS = [\"test\", \"typecheck\", \"lint\"] as const;\n\n/**\n * Neutrally detect proposed pre-commit gates for a target repository.\n *\n * Reads `package.json` scripts and the lockfile to suggest `<pm> run <script>` commands. Returns an\n * empty list when no JavaScript toolchain is detected. The result is a proposal the user reviews in\n * `.recall/config.json`; it is not an accepted decision.\n */\nexport async function detectPreCommitGates(rootDir: string): Promise<string[]> {\n const packageJsonPath = path.join(rootDir, \"package.json\");\n\n if (!existsSync(packageJsonPath)) {\n return [];\n }\n\n let scripts: Record<string, unknown>;\n try {\n const raw = await readFile(packageJsonPath, \"utf8\");\n const parsed = JSON.parse(raw) as { scripts?: Record<string, unknown> };\n scripts = parsed.scripts ?? {};\n } catch {\n return [];\n }\n\n if (typeof scripts !== \"object\" || scripts === null) {\n return [];\n }\n\n const packageManager = detectPackageManager(rootDir);\n\n return KNOWN_SCRIPTS.filter((script) => typeof scripts[script] === \"string\").map(\n (script) => `${packageManager} run ${script}`,\n );\n}\n\nfunction detectPackageManager(rootDir: string): string {\n if (existsSync(path.join(rootDir, \"pnpm-lock.yaml\"))) {\n return \"pnpm\";\n }\n\n if (existsSync(path.join(rootDir, \"yarn.lock\"))) {\n return \"yarn\";\n }\n\n return \"npm\";\n}\n","export const HOOKS_DIR = \".recall/hooks\";\nexport const PRE_COMMIT_HOOK_PATH = \".recall/hooks/pre-commit\";\nexport const HOOKS_PATH_ACTIVATION_COMMAND = \"git config core.hooksPath .recall/hooks\";\n\nexport const SESSION_START_HOOK_PATH = \".claude/hooks/session-start.sh\";\nexport const CLAUDE_SETTINGS_PATH = \".claude/settings.json\";\n\n/**\n * Render a deterministic POSIX `sh` Claude Code SessionStart hook.\n *\n * Claude Code runs this before the first prompt of every session and injects its stdout\n * `additionalContext` into the model. It lists the repository's accepted ADRs and modules so a fresh\n * agent reliably knows the durable memory exists and where to read it. It is strictly read-only:\n * it only lists files and never modifies anything, makes no network calls, and runs no AI.\n */\nexport function renderSessionStartHook(): string {\n return `#!/bin/sh\n# Recall OS Claude Code SessionStart hook.\n# Generated by \\`recall init\\`. Injects a repository-memory map into every Claude Code session so a\n# fresh agent reliably loads durable memory. Wired in .claude/settings.json. Read-only.\n\nadrs=$(ls docs/adrs/ADR-*.md 2>/dev/null | sed 's|.*/||;s|\\\\.md$||' | tr '\\\\n' ' ')\nmodules=$(ls -d docs/30-modules/*/ 2>/dev/null | sed 's|docs/30-modules/||;s|/$||' | tr '\\\\n' ' ')\n\ncontext=\"Recall OS repository memory is the source of truth over chat history. Before non-trivial work, read AGENTS.md and the docs it routes to; repository rules override model preference. Accepted ADRs (docs/adrs/): \\${adrs:-none yet}. Modules (docs/30-modules/): \\${modules:-none yet}. Use the Recall OS CLI commands listed in AGENTS.md (recall feature/adr/module create, recall adr accept and supersede, recall doctor) yourself; do not web-search them. Run 'recall doctor' before claiming work complete.\"\n\nprintf '{\"hookSpecificOutput\":{\"hookEventName\":\"SessionStart\",\"additionalContext\":\"%s\"}}\\\\n' \"$context\"\n`;\n}\n\n/**\n * Claude Code settings that wire the SessionStart hook. Generated only when no settings file exists,\n * since the safe write policy never overwrites a user's existing settings.\n */\nexport function renderClaudeSettings(): string {\n return `${JSON.stringify(\n {\n hooks: {\n SessionStart: [\n {\n matcher: \"startup\",\n hooks: [{ type: \"command\", command: `./${SESSION_START_HOOK_PATH}` }],\n },\n ],\n },\n },\n null,\n 2,\n )}\\n`;\n}\n\n/**\n * Render a deterministic POSIX `sh` pre-commit hook.\n *\n * The hook runs `recall doctor` first, then each configured gate in order. Gates come from\n * `.recall/config.json` (`preCommitGates`), so the toolchain choice stays in user config rather than\n * in core. The hook does not modify git configuration; activation is a deliberate human step.\n */\nexport function renderPreCommitHook(gates: string[]): string {\n const lines = [\n \"#!/bin/sh\",\n \"# Recall OS pre-commit hook.\",\n \"# Generated by `recall init`. Edit gates in .recall/config.json (preCommitGates),\",\n \"# then re-run `recall init --force` to regenerate this hook.\",\n \"# Enable once per clone with:\",\n `# ${HOOKS_PATH_ACTIVATION_COMMAND}`,\n \"set -e\",\n \"\",\n \"recall doctor\",\n ];\n\n for (const gate of gates) {\n lines.push(gate);\n }\n\n lines.push(\"\");\n\n return lines.join(\"\\n\");\n}\n","import type { Preset } from \"../../core/presets/preset-schema.js\";\n\nexport const flutterPreset: Preset = {\n id: \"flutter\",\n name: \"Flutter\",\n description: \"Minimal Flutter-aware opinion pack guidance with proposed decisions only.\",\n templates: [\n {\n destination: \"docs/ai/presets/flutter-guidance.md\",\n description: \"Flutter guidance that remains non-authoritative until accepted.\",\n content:\n \"# Flutter Preset Guidance\\n\\nTreat Flutter package, state management, navigation, and platform choices as proposed guidance until accepted.\\n\",\n },\n ],\n guidance: [\n {\n title: \"Do not silently choose state management\",\n body: \"Flutter state management, navigation, persistence, and backend choices must remain optional guidance or proposed ADRs.\",\n },\n ],\n proposedDecisions: [\n {\n id: \"flutter-platform\",\n title: \"Use Flutter\",\n status: \"proposed\",\n destination: \"docs/adrs/proposed/ADR-PROPOSED-flutter-platform.md\",\n body: \"# Proposed ADR: Use Flutter\\n\\n## Status\\n\\nProposed\\n\\n## Decision\\n\\nConsider Flutter as the application platform. This is not accepted until a human reviews and accepts it.\\n\",\n },\n ],\n};\n","import type { Preset } from \"../../core/presets/preset-schema.js\";\n\nexport const genericPreset: Preset = {\n id: \"generic\",\n name: \"Generic\",\n description: \"Neutral repository memory with no framework or architecture opinions.\",\n templates: [\n {\n destination: \"docs/ai/presets/generic-guidance.md\",\n description: \"Neutral guidance for repository memory initialization.\",\n content:\n \"# Generic Preset Guidance\\n\\nUse neutral repository memory first. Record architecture choices only after a human accepts them.\\n\",\n },\n ],\n guidance: [\n {\n title: \"Neutral memory first\",\n body: \"Use this preset when the repository should start with memory structure only and no stack-specific recommendations.\",\n },\n ],\n proposedDecisions: [],\n};\n","import type { Preset } from \"../../core/presets/preset-schema.js\";\n\nconst guidance = `# iOS Swift Preset Guidance\n\nThis is proposed guidance, not accepted. Convert any choice you adopt into an accepted ADR in\nrepository memory. Until then, treat everything here as a recommendation awaiting human review.\n\n## Decision forks this stack forces\n\n- UI framework: SwiftUI vs UIKit.\n- Concurrency: Swift async/await with the Observation framework vs Combine.\n- Persistence: SwiftData vs Core Data.\n- Presentation pattern: MVVM vs The Composable Architecture (TCA).\n- Testing: XCTest vs the Swift Testing framework.\n\n## Recommended structure (proposed)\n\n- Feature folders with view, model, and view-model separation.\n- A dependency layer abstracted behind protocols for testability.\n- Swift Package Manager for modular code.\n\n## Testing (proposed)\n\n- Unit tests with XCTest or Swift Testing.\n- View-model tests independent of the UI.\n- Snapshot or UI tests for critical flows.\n\n## Security considerations (proposed)\n\n- Store credentials and tokens in the Keychain, never in source or UserDefaults.\n- Enable App Transport Security and consider certificate pinning.\n- Avoid logging sensitive data.\n`;\n\nfunction proposedAdr(topic: string, title: string, body: string) {\n return {\n id: `ios-swift-${topic}`,\n title,\n status: \"proposed\" as const,\n destination: `docs/adrs/proposed/ADR-PROPOSED-ios-swift-${topic}.md`,\n body,\n };\n}\n\nexport const iosSwiftPreset: Preset = {\n id: \"ios-swift\",\n name: \"iOS Swift\",\n description: \"Opinionated iOS Swift opinion pack with proposed decisions only.\",\n templates: [\n {\n destination: \"docs/ai/presets/ios-swift-guidance.md\",\n description: \"iOS Swift guidance that remains proposed until accepted.\",\n content: guidance,\n },\n ],\n guidance: [\n {\n title: \"Separate platform guidance from decisions\",\n body: \"SwiftUI vs UIKit, concurrency, persistence, presentation pattern, and testing choices must be documented as proposed before acceptance.\",\n },\n {\n title: \"Abstract dependencies behind protocols\",\n body: \"Hide platform services behind protocols for testability, but record this as a proposed decision before treating it as accepted.\",\n },\n ],\n proposedDecisions: [\n proposedAdr(\n \"platform\",\n \"Use iOS Swift\",\n `# Proposed ADR: Use iOS Swift\n\n## Status\n\nProposed\n\n## Context\n\nThe team needs a primary platform and language for the iOS application.\n\n## Decision\n\nConsider iOS Swift as the platform direction. This is not accepted until a human reviews and accepts\nit.\n\n## Alternatives Considered\n\n- Objective-C.\n- A cross-platform stack such as Flutter or React Native.\n\n## Consequences\n\n- Native performance and first-class Apple APIs.\n- Requires Swift and Apple toolchain proficiency.\n`,\n ),\n proposedAdr(\n \"ui-swiftui\",\n \"Use SwiftUI for UI\",\n `# Proposed ADR: Use SwiftUI\n\n## Status\n\nProposed\n\n## Context\n\nThe app needs a UI framework. SwiftUI and UIKit are the main options.\n\n## Decision\n\nConsider SwiftUI as the UI framework, awaiting human acceptance.\n\n## Alternatives Considered\n\n- UIKit.\n- A hybrid of SwiftUI and UIKit during migration.\n\n## Consequences\n\n- Declarative UI and less boilerplate.\n- Some advanced cases still require UIKit interop.\n`,\n ),\n proposedAdr(\n \"concurrency-async\",\n \"Use async/await and Observation\",\n `# Proposed ADR: Use async/await and Observation\n\n## Status\n\nProposed\n\n## Context\n\nThe app needs a concurrency and state-observation approach.\n\n## Decision\n\nConsider Swift async/await with the Observation framework, awaiting human acceptance.\n\n## Alternatives Considered\n\n- Combine.\n- Completion handlers and delegates.\n\n## Consequences\n\n- Structured concurrency and simpler state flow.\n- Requires a recent deployment target.\n`,\n ),\n proposedAdr(\n \"persistence-swiftdata\",\n \"Use SwiftData for persistence\",\n `# Proposed ADR: Use SwiftData\n\n## Status\n\nProposed\n\n## Context\n\nThe app needs local persistence.\n\n## Decision\n\nConsider SwiftData for local persistence, awaiting human acceptance.\n\n## Alternatives Considered\n\n- Core Data directly.\n- A lightweight store such as GRDB.\n\n## Consequences\n\n- Swift-native modeling and SwiftUI integration.\n- Requires a recent deployment target and migration care.\n`,\n ),\n proposedAdr(\n \"architecture-mvvm\",\n \"Use MVVM presentation pattern\",\n `# Proposed ADR: Use MVVM\n\n## Status\n\nProposed\n\n## Context\n\nThe app needs a presentation architecture.\n\n## Decision\n\nConsider MVVM with observable view models, awaiting human acceptance.\n\n## Alternatives Considered\n\n- The Composable Architecture (TCA).\n- Plain views with embedded logic.\n\n## Consequences\n\n- Clear separation of UI and state.\n- Teams must agree on view-model conventions.\n`,\n ),\n ],\n};\n","import type { Preset } from \"../../core/presets/preset-schema.js\";\n\nconst guidance = `# Kotlin Android Preset Guidance\n\nThis guidance is proposed, not accepted. Convert any choice you adopt into an accepted ADR in\nrepository memory. Until then, treat everything here as a recommendation awaiting human review.\n\n## Decision forks this stack forces\n\n- UI toolkit: Jetpack Compose vs Android Views/XML.\n- Asynchrony: Kotlin Coroutines and Flow vs RxJava/callbacks.\n- Dependency injection: Hilt vs Koin vs manual.\n- Local persistence: Room vs SQLDelight vs DataStore.\n- Presentation pattern: MVVM vs MVI.\n\n## Recommended structure (proposed)\n\n- Feature-based modules or packages (\\`feature/\\`, \\`core/\\`, \\`data/\\`, \\`ui/\\`).\n- A repository layer between ViewModels and data sources.\n- Immutable UI state exposed as \\`StateFlow\\` from ViewModels.\n\n## Testing (proposed)\n\n- Unit tests with JUnit5 and coroutine test dispatchers.\n- Flow assertions with Turbine.\n- UI tests with Compose UI testing or Espresso.\n\n## Security considerations (proposed)\n\n- Store secrets with the Android Keystore, never in source or version control.\n- Use EncryptedSharedPreferences or DataStore with encryption for sensitive local data.\n- Enforce network security config and certificate pinning where appropriate.\n`;\n\nfunction proposedAdr(topic: string, title: string, body: string) {\n return {\n id: `kotlin-android-${topic}`,\n title,\n status: \"proposed\" as const,\n destination: `docs/adrs/proposed/ADR-PROPOSED-kotlin-android-${topic}.md`,\n body,\n };\n}\n\nexport const kotlinAndroidPreset: Preset = {\n id: \"kotlin-android\",\n name: \"Kotlin Android\",\n description: \"Opinionated Kotlin Android opinion pack with proposed decisions only.\",\n templates: [\n {\n destination: \"docs/ai/presets/kotlin-android-guidance.md\",\n description: \"Kotlin Android guidance that remains proposed until accepted.\",\n content: guidance,\n },\n ],\n guidance: [\n {\n title: \"Keep stack choices proposed\",\n body: \"Compose vs Views, Coroutines/Flow vs RxJava, DI framework, persistence, and presentation pattern must remain proposed until accepted in repository memory.\",\n },\n {\n title: \"Prefer unidirectional state\",\n body: \"Expose immutable UI state from ViewModels and keep side effects explicit, but record this as a proposed decision before treating it as accepted.\",\n },\n ],\n proposedDecisions: [\n proposedAdr(\n \"platform\",\n \"Use Kotlin for Android\",\n `# Proposed ADR: Use Kotlin for Android\n\n## Status\n\nProposed\n\n## Context\n\nThe team needs a primary language and platform for the Android application.\n\n## Decision\n\nConsider Kotlin as the Android application language. This is not accepted until a human reviews and\naccepts it.\n\n## Alternatives Considered\n\n- Java for Android.\n- A cross-platform stack such as Flutter or React Native.\n\n## Consequences\n\n- Idiomatic Android APIs and coroutines support.\n- Requires Kotlin proficiency across the team.\n`,\n ),\n proposedAdr(\n \"ui-compose\",\n \"Use Jetpack Compose for UI\",\n `# Proposed ADR: Use Jetpack Compose\n\n## Status\n\nProposed\n\n## Context\n\nThe app needs a UI toolkit. Compose and the legacy View/XML system are the main options.\n\n## Decision\n\nConsider Jetpack Compose as the UI toolkit, awaiting human acceptance.\n\n## Alternatives Considered\n\n- Android Views with XML layouts.\n- A hybrid of Compose and Views during migration.\n\n## Consequences\n\n- Declarative UI and less boilerplate.\n- Requires Compose tooling and team ramp-up.\n`,\n ),\n proposedAdr(\n \"async-coroutines\",\n \"Use Coroutines and Flow for async\",\n `# Proposed ADR: Use Coroutines and Flow\n\n## Status\n\nProposed\n\n## Context\n\nThe app needs a concurrency and reactive streams approach.\n\n## Decision\n\nConsider Kotlin Coroutines with Flow for asynchronous work and streams, awaiting human acceptance.\n\n## Alternatives Considered\n\n- RxJava/RxKotlin.\n- Callbacks and \\`LiveData\\` only.\n\n## Consequences\n\n- Structured concurrency and cancellation.\n- Requires discipline around dispatchers and scope.\n`,\n ),\n proposedAdr(\n \"di-hilt\",\n \"Use Hilt for dependency injection\",\n `# Proposed ADR: Use Hilt\n\n## Status\n\nProposed\n\n## Context\n\nThe app needs a dependency injection approach for testability and lifecycle scoping.\n\n## Decision\n\nConsider Hilt for dependency injection, awaiting human acceptance.\n\n## Alternatives Considered\n\n- Koin.\n- Manual constructor injection.\n\n## Consequences\n\n- Compile-time validation and Android lifecycle scopes.\n- Adds annotation processing to the build.\n`,\n ),\n proposedAdr(\n \"persistence-room\",\n \"Use Room for local persistence\",\n `# Proposed ADR: Use Room\n\n## Status\n\nProposed\n\n## Context\n\nThe app needs structured local persistence.\n\n## Decision\n\nConsider Room for local relational persistence, awaiting human acceptance.\n\n## Alternatives Considered\n\n- SQLDelight.\n- DataStore for simple key-value needs.\n\n## Consequences\n\n- Compile-time verified SQL and Flow integration.\n- Schema migrations must be maintained.\n`,\n ),\n proposedAdr(\n \"architecture-mvvm\",\n \"Use MVVM presentation pattern\",\n `# Proposed ADR: Use MVVM\n\n## Status\n\nProposed\n\n## Context\n\nThe app needs a presentation architecture for separating UI from logic.\n\n## Decision\n\nConsider MVVM with unidirectional state from ViewModels, awaiting human acceptance.\n\n## Alternatives Considered\n\n- MVI with explicit intents and reducers.\n- Plain ViewModels without a strict pattern.\n\n## Consequences\n\n- Clear separation of UI and state.\n- Teams must agree on state and event conventions.\n`,\n ),\n ],\n};\n","import type { PresetGuidance, PresetProposedDecision } from \"../../core/presets/preset-schema.js\";\n\n/**\n * Shared building blocks for the Laravel opinion packs. Three presets compose these: `laravel-react`\n * and `laravel-vue` (Inertia SPAs) and `laravel-api` (API/SPA backend). Every decision is *proposed*\n * — a human accepts it with `recall adr accept`. Nothing here is accepted truth.\n */\nexport type LaravelVariant = \"react\" | \"vue\" | \"api\";\n\ntype VariantProfile = {\n id: string;\n label: string;\n description: string;\n frontendLine: string;\n deliveryLine: string;\n};\n\nconst VARIANTS: Record<LaravelVariant, VariantProfile> = {\n react: {\n id: \"laravel-react\",\n label: \"React via Inertia\",\n description:\n \"Opinionated Laravel + Inertia + React opinion pack (proposed decisions only). Matches the official Laravel React starter kit.\",\n frontendLine:\n \"Frontend: Inertia 2 + React 19 + TypeScript + Tailwind, built with Vite (the official React starter kit, with shadcn/ui for components).\",\n deliveryLine:\n \"The app is a server-driven SPA: Laravel controllers return Inertia responses with typed props; there is no separate REST client for first-party screens.\",\n },\n vue: {\n id: \"laravel-vue\",\n label: \"Vue via Inertia\",\n description:\n \"Opinionated Laravel + Inertia + Vue opinion pack (proposed decisions only). Matches the official Laravel Vue starter kit.\",\n frontendLine:\n \"Frontend: Inertia 2 + Vue 3 (script setup) + TypeScript + Tailwind, built with Vite (the official Vue starter kit).\",\n deliveryLine:\n \"The app is a server-driven SPA: Laravel controllers return Inertia responses with typed props; there is no separate REST client for first-party screens.\",\n },\n api: {\n id: \"laravel-api\",\n label: \"API / SPA backend\",\n description:\n \"Opinionated Laravel API-only opinion pack (proposed decisions only) for a decoupled SPA or mobile client.\",\n frontendLine:\n \"No server-rendered frontend: Laravel is an HTTP JSON API consumed by a separate SPA or mobile app.\",\n deliveryLine:\n \"Controllers return JSON via API Resources; first-party SPAs authenticate with Sanctum cookies, mobile clients with Sanctum tokens.\",\n },\n};\n\nfunction adr(presetId: string, topic: string, title: string, body: string): PresetProposedDecision {\n return {\n id: `${presetId}-${topic}`,\n title,\n status: \"proposed\",\n destination: `docs/adrs/proposed/ADR-PROPOSED-${presetId}-${topic}.md`,\n body,\n };\n}\n\nfunction related(presetId: string, ...extra: string[]): string {\n return [\n `## Related Documents`,\n ``,\n `- \\`docs/ai/presets/${presetId}-guidance.md\\` — the proposed Laravel stack guidance.`,\n `- \\`docs/10-architecture/ARCHITECTURE.md\\` — record the accepted architecture here once promoted.`,\n ...extra.map((line) => `- ${line}`),\n ``,\n ].join(\"\\n\");\n}\n\nexport function laravelGuidance(variant: LaravelVariant): string {\n const profile = VARIANTS[variant];\n\n return `# Laravel Preset Guidance (${profile.label})\n\nThis is proposed guidance, not accepted. Convert any architecture choice into a proposed ADR, then an\naccepted ADR, before treating it as repository truth. Repository rules override model preference.\n\n## The stack (proposed)\n\n- Laravel 12 on PHP 8.3+, using the official conventions and directory layout.\n- ${profile.frontendLine}\n- Database: PostgreSQL (MySQL is the alternative) through Eloquent and migrations.\n- Auth: Laravel Sanctum for first-party SPA and mobile clients (Passport only if you need third-party OAuth2).\n- Background work: queues, with Redis and Laravel Horizon when throughput grows.\n- Tests: Pest, with database factories and feature tests over real routes.\n\n${profile.deliveryLine}\n\n## Decision forks this stack forces\n\n- Frontend delivery: Inertia (server-driven SPA) vs a decoupled API + separate SPA vs Blade + Livewire.\n- Auth: Sanctum (first-party SPA and mobile) vs Passport (third-party OAuth2) vs a managed identity provider.\n- Database: PostgreSQL vs MySQL, and where read scaling and queues live (Redis vs database driver).\n- Authorization: Policies and Gates vs ad-hoc checks; validation via Form Requests vs inline.\n- Business logic: thin controllers with Action/Service classes vs fat controllers and models.\n- Testing: Pest vs PHPUnit.\n\n## Recommended structure (proposed)\n\n- Keep controllers thin: they validate, authorize, delegate, and return a response — nothing more.\n- Put request validation **and** authorization in Form Requests (\\`authorize()\\` + \\`rules()\\`).\n- Put per-model and per-action permission logic in Policies and Gates, not in controllers.\n- Put business logic in single-purpose Action or Service classes, not in controllers or models.\n- Shape every outbound payload with API Resources (or typed Inertia props), never raw models.\n- Declare \\`$fillable\\` (or \\`$guarded\\`) explicitly on every Eloquent model to stop mass assignment.\n\n## Data and performance (proposed)\n\n- Eager-load relationships (\\`with(...)\\`) to avoid N+1 queries; enable \\`Model::preventLazyLoading()\\` in local and CI.\n- Wrap multi-write operations in database transactions.\n- Paginate list endpoints; never return unbounded collections.\n- Move email, exports, third-party calls, and other slow work into queued jobs.\n- Cache expensive reads deliberately, with explicit invalidation.\n\n## Testing (proposed)\n\n- Write Pest feature tests that exercise real routes end to end, using \\`RefreshDatabase\\`.\n- Build state with model factories, not hand-rolled fixtures.\n- Test authorization explicitly: a forbidden action must assert a 403, not just a happy path.\n- Cover validation failures, not only the success case.\n\n## Security considerations (proposed)\n\n- Validate every inbound request through Form Requests; persist only validated data.\n- Authorize every state-changing action through a Policy or Gate.\n- Keep secrets in \\`.env\\`; never commit \\`.env\\` or hardcode credentials.\n- Apply rate limiting to auth and write endpoints.\n- Keep mass assignment locked down and never trust client-supplied IDs without an ownership check.\n${\n variant === \"api\"\n ? \"- Scope Sanctum tokens to least privilege; SPA clients use the cookie guard with CSRF protection.\\n\"\n : \"- Inertia uses Laravel's session and CSRF protection; keep auth and authorization on the server, never the client.\\n\"\n}`;\n}\n\nexport function laravelGuidanceItems(): PresetGuidance[] {\n return [\n {\n title: \"Keep stack choices proposed\",\n body: \"Framework, frontend delivery, database, auth, and testing choices stay proposed until accepted in repository memory.\",\n },\n {\n title: \"Thin controllers, explicit authorization\",\n body: \"Validate and authorize in Form Requests and Policies, keep business logic in Action or Service classes, and shape output with Resources — propose these as decisions before treating them as truth.\",\n },\n ];\n}\n\nexport function laravelProposedDecisions(variant: LaravelVariant): PresetProposedDecision[] {\n const presetId = VARIANTS[variant].id;\n\n const base: PresetProposedDecision[] = [\n adr(\n presetId,\n \"framework\",\n \"Use Laravel\",\n `# Proposed ADR: Use Laravel\n\n## Status\n\nProposed\n\n## Context\n\nThe team needs a productive, batteries-included PHP framework for a production web application.\n\n## Decision\n\nConsider Laravel 12 on PHP 8.3+ as the application framework, following its standard conventions and\ndirectory structure. This is not accepted until a human reviews and accepts it.\n\n## Alternatives Considered\n\n- Symfony for a more component-assembled approach.\n- A different language or framework entirely.\n\n## Consequences\n\n- A mature ecosystem (Eloquent, queues, Sanctum, Horizon) and strong conventions.\n- Couples the application to Laravel's conventions and release cadence.\n\n${related(presetId)}`,\n ),\n adr(\n presetId,\n \"database-eloquent\",\n \"Use Eloquent and migrations on PostgreSQL\",\n `# Proposed ADR: Use Eloquent and migrations on PostgreSQL\n\n## Status\n\nProposed\n\n## Context\n\nThe application needs a relational database and a schema workflow.\n\n## Decision\n\nConsider PostgreSQL (MySQL as the alternative) accessed through Eloquent and versioned migrations,\nawaiting human acceptance.\n\n## Alternatives Considered\n\n- MySQL or MariaDB.\n- The query builder or raw SQL without Eloquent.\n\n## Consequences\n\n- Expressive models, relationships, and reproducible schema migrations.\n- Requires discipline against N+1 queries and unbounded result sets.\n\n${related(presetId, \"`docs/50-quality/TESTING_STRATEGY.md` — how database tests use factories and a disposable database.\")}`,\n ),\n adr(\n presetId,\n \"auth-sanctum\",\n \"Use Laravel Sanctum for authentication\",\n `# Proposed ADR: Use Laravel Sanctum for authentication\n\n## Status\n\nProposed\n\n## Context\n\nThe application needs authentication for first-party clients (${\n variant === \"api\"\n ? \"a separate SPA and mobile apps\"\n : \"an Inertia SPA, and possibly mobile apps\"\n }).\n\n## Decision\n\nConsider Laravel Sanctum: the cookie-based guard for first-party SPAs and API tokens for mobile or\nscripted clients. This is not accepted until a human reviews and accepts it.\n\n## Alternatives Considered\n\n- Laravel Passport for full OAuth2 (third-party delegated access).\n- A managed identity provider.\n\n## Consequences\n\n- Lightweight first-party auth without standing up a full OAuth2 server.\n- If third-party delegated access is ever required, revisit with Passport.\n\n${related(presetId, \"`docs/20-security/SECURITY_MODEL.md` — record the accepted auth and session model here.\")}`,\n ),\n adr(\n presetId,\n \"validation-authorization\",\n \"Validate with Form Requests and authorize with Policies\",\n `# Proposed ADR: Validate with Form Requests and authorize with Policies\n\n## Status\n\nProposed\n\n## Context\n\nInput validation and authorization must be consistent and centralized, not scattered across\ncontrollers.\n\n## Decision\n\nConsider Form Requests for validation (and request-level authorization) plus Policies and Gates for\nper-model and per-action permission checks, awaiting human acceptance.\n\n## Alternatives Considered\n\n- Inline validation and authorization in controllers.\n- A third-party permissions package layered on top.\n\n## Consequences\n\n- Controllers stay thin; validation and authorization are testable in isolation.\n- Every state-changing action must have an explicit authorization path.\n\n${related(presetId)}`,\n ),\n adr(\n presetId,\n \"application-structure\",\n \"Keep controllers thin with Action and Service classes\",\n `# Proposed ADR: Keep controllers thin with Action and Service classes\n\n## Status\n\nProposed\n\n## Context\n\nBusiness logic tends to accumulate in controllers and models, which makes it hard to test and reuse.\n\n## Decision\n\nConsider thin controllers that delegate to single-purpose Action or Service classes, with outbound\npayloads shaped by API Resources (or typed Inertia props). This is not accepted until a human accepts\nit.\n\n## Alternatives Considered\n\n- Fat controllers.\n- Fat models holding business logic.\n\n## Consequences\n\n- Reusable, unit-testable business logic and consistent response shapes.\n- More classes and a convention the team must follow.\n\n${related(presetId)}`,\n ),\n adr(\n presetId,\n \"queues-horizon\",\n \"Run slow work on queues\",\n `# Proposed ADR: Run slow work on queues\n\n## Status\n\nProposed\n\n## Context\n\nEmail, exports, and third-party calls slow down requests and can fail independently.\n\n## Decision\n\nConsider queued jobs for slow or failure-prone work, using the database driver early and Redis with\nLaravel Horizon as throughput grows. This is not accepted until a human reviews and accepts it.\n\n## Alternatives Considered\n\n- Doing the work synchronously in the request.\n- An external task queue or serverless functions.\n\n## Consequences\n\n- Faster responses and isolated, retryable background work.\n- Adds a worker process and queue infrastructure to operate and monitor.\n\n${related(presetId)}`,\n ),\n adr(\n presetId,\n \"testing-pest\",\n \"Use Pest for testing\",\n `# Proposed ADR: Use Pest for testing\n\n## Status\n\nProposed\n\n## Context\n\nThe application needs a fast, readable testing workflow.\n\n## Decision\n\nConsider Pest with model factories and feature tests that exercise real routes against a disposable\ndatabase, awaiting human acceptance.\n\n## Alternatives Considered\n\n- PHPUnit directly.\n- A thinner test suite focused only on unit tests.\n\n## Consequences\n\n- Concise, expressive tests that cover routes, validation, and authorization.\n- The team standardizes on Pest's syntax and plugins.\n\n${related(presetId, \"`docs/50-quality/TESTING_STRATEGY.md` — record the accepted testing approach here.\")}`,\n ),\n ];\n\n return [...base, frontendDecision(variant)];\n}\n\nfunction frontendDecision(variant: LaravelVariant): PresetProposedDecision {\n const presetId = VARIANTS[variant].id;\n\n if (variant === \"api\") {\n return adr(\n presetId,\n \"api-design-rest\",\n \"Expose a versioned REST API with API Resources\",\n `# Proposed ADR: Expose a versioned REST API with API Resources\n\n## Status\n\nProposed\n\n## Context\n\nA decoupled SPA or mobile client consumes Laravel over HTTP, so the API contract must be stable and\nexplicit.\n\n## Decision\n\nConsider a versioned REST API (for example \\`/api/v1\\`) whose responses are shaped by API Resources,\nauthenticated with Sanctum, and documented (OpenAPI). This is not accepted until a human accepts it.\n\n## Alternatives Considered\n\n- GraphQL.\n- Server-driven Inertia pages instead of a decoupled API.\n\n## Consequences\n\n- A stable, documented contract that multiple clients can rely on.\n- Versioning and serialization become an explicit, maintained concern.\n\n${related(presetId, \"`docs/20-security/SECURITY_MODEL.md` — record token scopes and the SPA cookie guard here.\")}`,\n );\n }\n\n const framework = variant === \"react\" ? \"React 19\" : \"Vue 3\";\n const components =\n variant === \"react\"\n ? \"shadcn/ui components on Tailwind\"\n : \"Tailwind with single-file components (script setup)\";\n\n return adr(\n presetId,\n `frontend-inertia-${variant}`,\n `Use Inertia with ${framework}`,\n `# Proposed ADR: Use Inertia with ${framework}\n\n## Status\n\nProposed\n\n## Context\n\nThe application needs a modern SPA experience without standing up and securing a separate API for\nfirst-party screens.\n\n## Decision\n\nConsider Inertia 2 with ${framework} and TypeScript, built with Vite, using ${components}. Controllers\nreturn Inertia responses with typed props. This is not accepted until a human reviews and accepts it.\n\n## Alternatives Considered\n\n- A decoupled REST or GraphQL API with a standalone SPA.\n- Blade with Livewire.\n\n## Consequences\n\n- Server-driven routing and auth with a reactive ${framework} frontend and no duplicate API layer.\n- Couples the frontend to Inertia's model and the ${framework} ecosystem.\n\n${related(presetId)}`,\n );\n}\n","import type { Preset } from \"../../core/presets/preset-schema.js\";\nimport {\n laravelGuidance,\n laravelGuidanceItems,\n laravelProposedDecisions,\n} from \"../laravel/shared.js\";\n\nexport const laravelApiPreset: Preset = {\n id: \"laravel-api\",\n name: \"Laravel API\",\n description: \"Opinionated Laravel API-only opinion pack with proposed decisions only.\",\n templates: [\n {\n destination: \"docs/ai/presets/laravel-api-guidance.md\",\n description: \"Laravel API-only guidance that remains proposed until accepted.\",\n content: laravelGuidance(\"api\"),\n },\n ],\n guidance: laravelGuidanceItems(),\n proposedDecisions: laravelProposedDecisions(\"api\"),\n};\n","import type { Preset } from \"../../core/presets/preset-schema.js\";\nimport {\n laravelGuidance,\n laravelGuidanceItems,\n laravelProposedDecisions,\n} from \"../laravel/shared.js\";\n\nexport const laravelReactPreset: Preset = {\n id: \"laravel-react\",\n name: \"Laravel + React\",\n description: \"Opinionated Laravel + Inertia + React opinion pack with proposed decisions only.\",\n templates: [\n {\n destination: \"docs/ai/presets/laravel-react-guidance.md\",\n description: \"Laravel + React (Inertia) guidance that remains proposed until accepted.\",\n content: laravelGuidance(\"react\"),\n },\n ],\n guidance: laravelGuidanceItems(),\n proposedDecisions: laravelProposedDecisions(\"react\"),\n};\n","import type { Preset } from \"../../core/presets/preset-schema.js\";\nimport {\n laravelGuidance,\n laravelGuidanceItems,\n laravelProposedDecisions,\n} from \"../laravel/shared.js\";\n\nexport const laravelVuePreset: Preset = {\n id: \"laravel-vue\",\n name: \"Laravel + Vue\",\n description: \"Opinionated Laravel + Inertia + Vue opinion pack with proposed decisions only.\",\n templates: [\n {\n destination: \"docs/ai/presets/laravel-vue-guidance.md\",\n description: \"Laravel + Vue (Inertia) guidance that remains proposed until accepted.\",\n content: laravelGuidance(\"vue\"),\n },\n ],\n guidance: laravelGuidanceItems(),\n proposedDecisions: laravelProposedDecisions(\"vue\"),\n};\n","import type { Preset } from \"../../core/presets/preset-schema.js\";\n\nconst guidance = `# Next.js Preset Guidance\n\nThis is proposed guidance, not accepted. Convert any architecture choice into a proposed ADR, then an\naccepted ADR, before treating it as repository truth.\n\n## Decision forks this stack forces\n\n- Routing: App Router vs Pages Router.\n- Rendering: Server Components and server actions vs client-heavy rendering.\n- Data layer: Drizzle or Prisma with PostgreSQL vs a hosted backend.\n- Styling: Tailwind CSS vs CSS Modules vs a component library.\n- Testing: Vitest with Testing Library and Playwright vs other runners.\n\n## Recommended structure (proposed)\n\n- The App Router with route groups and colocated server components.\n- A typed data layer isolated from UI components.\n- Shared UI primitives and a consistent styling system.\n\n## Testing (proposed)\n\n- Unit and component tests with Vitest and Testing Library.\n- End-to-end tests with Playwright for critical flows.\n- Type-safe data access tested against a disposable database.\n\n## Security considerations (proposed)\n\n- Keep secrets in server-only environment variables, never in client bundles.\n- Validate input on the server, including server actions and route handlers.\n- Scope authentication and authorization on the server, not the client.\n`;\n\nfunction proposedAdr(topic: string, title: string, body: string) {\n return {\n id: `nextjs-${topic}`,\n title,\n status: \"proposed\" as const,\n destination: `docs/adrs/proposed/ADR-PROPOSED-nextjs-${topic}.md`,\n body,\n };\n}\n\nexport const nextjsPreset: Preset = {\n id: \"nextjs\",\n name: \"Next.js\",\n description: \"Opinionated Next.js opinion pack with proposed decisions only.\",\n templates: [\n {\n destination: \"docs/ai/presets/nextjs-guidance.md\",\n description: \"Next.js guidance that remains proposed until accepted.\",\n content: guidance,\n },\n ],\n guidance: [\n {\n title: \"Keep framework choices proposed\",\n body: \"Routing, rendering, data layer, styling, and testing choices must remain proposed until accepted in repository memory.\",\n },\n {\n title: \"Keep secrets server-side\",\n body: \"Never expose secrets to the client bundle, and record the data and auth approach as proposed decisions before acceptance.\",\n },\n ],\n proposedDecisions: [\n proposedAdr(\n \"framework\",\n \"Use Next.js\",\n `# Proposed ADR: Use Next.js\n\n## Status\n\nProposed\n\n## Context\n\nThe team needs a React framework for a production web application.\n\n## Decision\n\nConsider Next.js as the application framework. This is not accepted until a human reviews and accepts\nit.\n\n## Alternatives Considered\n\n- A Vite single-page app with a separate API.\n- Remix or another framework.\n\n## Consequences\n\n- Server rendering, routing, and a large ecosystem.\n- Couples the app to Next.js conventions.\n`,\n ),\n proposedAdr(\n \"routing-app-router\",\n \"Use the App Router\",\n `# Proposed ADR: Use the App Router\n\n## Status\n\nProposed\n\n## Context\n\nNext.js offers the App Router and the legacy Pages Router.\n\n## Decision\n\nConsider the App Router with Server Components, awaiting human acceptance.\n\n## Alternatives Considered\n\n- The Pages Router.\n- A mix during migration.\n\n## Consequences\n\n- Server Components and nested layouts.\n- Requires understanding server and client boundaries.\n`,\n ),\n proposedAdr(\n \"data-layer\",\n \"Use a typed data layer with PostgreSQL\",\n `# Proposed ADR: Use a typed data layer with PostgreSQL\n\n## Status\n\nProposed\n\n## Context\n\nThe app needs a database and a typed access layer.\n\n## Decision\n\nConsider Drizzle or Prisma with PostgreSQL, awaiting human acceptance.\n\n## Alternatives Considered\n\n- A hosted backend or BaaS.\n- Raw SQL.\n\n## Consequences\n\n- Type-safe queries and migrations.\n- Adds an ORM and schema workflow.\n`,\n ),\n proposedAdr(\n \"styling-tailwind\",\n \"Use Tailwind CSS\",\n `# Proposed ADR: Use Tailwind CSS\n\n## Status\n\nProposed\n\n## Context\n\nThe app needs a styling approach.\n\n## Decision\n\nConsider Tailwind CSS for styling, awaiting human acceptance.\n\n## Alternatives Considered\n\n- CSS Modules.\n- A component library with its own styling.\n\n## Consequences\n\n- Fast, consistent utility-based styling.\n- Markup includes utility classes that teams must standardize.\n`,\n ),\n proposedAdr(\n \"testing\",\n \"Use Vitest and Playwright\",\n `# Proposed ADR: Use Vitest and Playwright\n\n## Status\n\nProposed\n\n## Context\n\nThe app needs unit, component, and end-to-end testing.\n\n## Decision\n\nConsider Vitest with Testing Library and Playwright, awaiting human acceptance.\n\n## Alternatives Considered\n\n- Jest.\n- Cypress for end-to-end tests.\n\n## Consequences\n\n- Fast unit and component tests plus reliable end-to-end coverage.\n- Teams maintain two test toolchains.\n`,\n ),\n ],\n};\n","import type { Preset } from \"../../core/presets/preset-schema.js\";\n\nconst guidance = `# Python FastAPI Preset Guidance\n\nThis guidance is proposed, not accepted. Convert any choice you adopt into an accepted ADR in\nrepository memory. Until then, treat everything here as a recommendation awaiting human review.\n\n## Decision forks this stack forces\n\n- Web framework: FastAPI vs Flask vs Django REST.\n- Database and access: PostgreSQL with SQLAlchemy and Alembic vs an async ORM vs raw SQL.\n- Validation and settings: Pydantic v2 models and settings.\n- Testing: pytest with httpx vs unittest.\n- Background work and caching: Redis, task queues, and async workers.\n\n## Recommended structure (proposed)\n\n- A layered layout: \\`api/\\` routers, \\`services/\\` logic, \\`repositories/\\` data access, \\`models/\\` schemas.\n- Dependency injection through FastAPI dependencies.\n- Configuration via Pydantic settings loaded from environment variables.\n\n## Testing (proposed)\n\n- pytest with the FastAPI test client or httpx \\`AsyncClient\\`.\n- A disposable test database and transactional fixtures.\n- Contract tests for request and response schemas.\n\n## Security considerations (proposed)\n\n- Load secrets from environment or a secret manager, never from source.\n- Validate and constrain all input with Pydantic models.\n- Scope authentication and authorization at the dependency layer.\n`;\n\nfunction proposedAdr(topic: string, title: string, body: string) {\n return {\n id: `python-fastapi-${topic}`,\n title,\n status: \"proposed\" as const,\n destination: `docs/adrs/proposed/ADR-PROPOSED-python-fastapi-${topic}.md`,\n body,\n };\n}\n\nexport const pythonFastapiPreset: Preset = {\n id: \"python-fastapi\",\n name: \"Python FastAPI\",\n description: \"Opinionated Python FastAPI opinion pack with proposed decisions only.\",\n templates: [\n {\n destination: \"docs/ai/presets/python-fastapi-guidance.md\",\n description: \"Python FastAPI guidance that remains proposed until accepted.\",\n content: guidance,\n },\n ],\n guidance: [\n {\n title: \"Keep framework and data choices proposed\",\n body: \"FastAPI, the database and ORM, validation, and testing choices must remain proposed until accepted in repository memory.\",\n },\n {\n title: \"Validate all input\",\n body: \"Use Pydantic models at the boundary, but record the validation approach as a proposed decision before treating it as accepted.\",\n },\n ],\n proposedDecisions: [\n proposedAdr(\n \"framework\",\n \"Use FastAPI\",\n `# Proposed ADR: Use FastAPI\n\n## Status\n\nProposed\n\n## Context\n\nThe service needs a Python web framework for an async API.\n\n## Decision\n\nConsider FastAPI as the web framework, awaiting human acceptance.\n\n## Alternatives Considered\n\n- Flask.\n- Django REST Framework.\n\n## Consequences\n\n- Async support and automatic OpenAPI docs.\n- Requires comfort with type hints and dependency injection.\n`,\n ),\n proposedAdr(\n \"database-postgres\",\n \"Use PostgreSQL with SQLAlchemy and Alembic\",\n `# Proposed ADR: Use PostgreSQL with SQLAlchemy\n\n## Status\n\nProposed\n\n## Context\n\nThe service needs a relational database and a migration strategy.\n\n## Decision\n\nConsider PostgreSQL with SQLAlchemy and Alembic migrations, awaiting human acceptance.\n\n## Alternatives Considered\n\n- An async ORM such as Tortoise or SQLModel only.\n- Raw SQL with a lightweight driver.\n\n## Consequences\n\n- Mature tooling and explicit migrations.\n- Requires session and connection management discipline.\n`,\n ),\n proposedAdr(\n \"validation-pydantic\",\n \"Use Pydantic for validation and settings\",\n `# Proposed ADR: Use Pydantic\n\n## Status\n\nProposed\n\n## Context\n\nThe service needs request validation and typed configuration.\n\n## Decision\n\nConsider Pydantic v2 models for validation and settings, awaiting human acceptance.\n\n## Alternatives Considered\n\n- Marshmallow.\n- Hand-written validation.\n\n## Consequences\n\n- Strong typing at the boundary and clear settings.\n- Adds Pydantic to the dependency surface.\n`,\n ),\n proposedAdr(\n \"testing-pytest\",\n \"Use pytest for testing\",\n `# Proposed ADR: Use pytest\n\n## Status\n\nProposed\n\n## Context\n\nThe service needs a test framework and HTTP testing approach.\n\n## Decision\n\nConsider pytest with httpx for API tests, awaiting human acceptance.\n\n## Alternatives Considered\n\n- unittest.\n- nose-style runners.\n\n## Consequences\n\n- Concise fixtures and rich plugins.\n- Teams must standardize fixture and database setup.\n`,\n ),\n proposedAdr(\n \"cache-redis\",\n \"Use Redis for caching and background work\",\n `# Proposed ADR: Use Redis\n\n## Status\n\nProposed\n\n## Context\n\nThe service may need caching, rate limiting, or a task queue backend.\n\n## Decision\n\nConsider Redis for caching and background work, awaiting human acceptance.\n\n## Alternatives Considered\n\n- In-process caching only.\n- A managed queue service.\n\n## Consequences\n\n- Fast shared cache and queue backend.\n- Adds an operational dependency to run and monitor.\n`,\n ),\n ],\n};\n","import { z } from \"zod\";\n\nimport { normalizeOutputPath } from \"../filesystem/safe-path.js\";\n\nconst PRESET_ID_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/u;\n\nconst safeDestinationSchema = z.string().transform((value, context) => {\n try {\n return normalizeOutputPath(value);\n } catch (error) {\n context.addIssue({\n code: \"custom\",\n message: error instanceof Error ? error.message : \"Destination is invalid.\",\n });\n return z.NEVER;\n }\n});\n\nexport class PresetValidationError extends Error {\n readonly issues: string[];\n\n constructor(issues: string[]) {\n super(`Invalid Recall OS preset: ${issues.join(\"; \")}`);\n this.name = \"PresetValidationError\";\n this.issues = issues;\n }\n}\n\nexport const presetTemplateSchema = z\n .object({\n destination: safeDestinationSchema,\n content: z.string().min(1, \"Template content cannot be empty.\"),\n description: z.string().min(1).optional(),\n })\n .strict();\n\nexport const presetGuidanceSchema = z\n .object({\n title: z.string().min(1, \"Guidance title cannot be empty.\"),\n body: z.string().min(1, \"Guidance body cannot be empty.\"),\n })\n .strict();\n\nexport const presetProposedDecisionSchema = z\n .object({\n id: z\n .string()\n .min(1, \"Decision id cannot be empty.\")\n .max(80, \"Decision id cannot exceed 80 characters.\")\n .regex(\n PRESET_ID_PATTERN,\n \"Decision id must use lowercase letters, numbers, and single hyphens.\",\n ),\n title: z.string().min(1, \"Decision title cannot be empty.\"),\n status: z.literal(\"proposed\"),\n destination: safeDestinationSchema,\n body: z.string().min(1, \"Decision body cannot be empty.\"),\n })\n .strict();\n\nexport const presetSchema = z\n .object({\n id: z\n .string()\n .min(1, \"Preset id cannot be empty.\")\n .max(80, \"Preset id cannot exceed 80 characters.\")\n .regex(\n PRESET_ID_PATTERN,\n \"Preset id must use lowercase letters, numbers, and single hyphens.\",\n ),\n name: z.string().min(1, \"Preset name cannot be empty.\"),\n description: z.string().min(1, \"Preset description cannot be empty.\"),\n templates: z.array(presetTemplateSchema).min(1, \"Preset must include a template.\"),\n guidance: z.array(presetGuidanceSchema).default([]),\n proposedDecisions: z.array(presetProposedDecisionSchema).default([]),\n })\n .strict()\n .superRefine((preset, context) => {\n const destinations = new Set<string>();\n\n for (const [index, template] of preset.templates.entries()) {\n if (destinations.has(template.destination)) {\n context.addIssue({\n code: \"custom\",\n path: [\"templates\", index, \"destination\"],\n message: `Duplicate destination \"${template.destination}\".`,\n });\n }\n\n destinations.add(template.destination);\n }\n\n for (const [index, decision] of preset.proposedDecisions.entries()) {\n if (destinations.has(decision.destination)) {\n context.addIssue({\n code: \"custom\",\n path: [\"proposedDecisions\", index, \"destination\"],\n message: `Duplicate destination \"${decision.destination}\".`,\n });\n }\n\n destinations.add(decision.destination);\n }\n });\n\nexport type PresetTemplate = z.infer<typeof presetTemplateSchema>;\nexport type PresetGuidance = z.infer<typeof presetGuidanceSchema>;\nexport type PresetProposedDecision = z.infer<typeof presetProposedDecisionSchema>;\nexport type Preset = z.infer<typeof presetSchema>;\n\nexport function parsePreset(value: unknown): Preset {\n const result = presetSchema.safeParse(value);\n\n if (!result.success) {\n throw new PresetValidationError(\n result.error.issues.map((issue) => {\n const path = issue.path.length > 0 ? `${issue.path.join(\".\")}: ` : \"\";\n return `${path}${issue.message}`;\n }),\n );\n }\n\n return result.data;\n}\n","import { parsePreset, PresetValidationError, type Preset } from \"./preset-schema.js\";\n\nexport function validatePreset(preset: Preset): Preset {\n return parsePreset(preset);\n}\n\nexport function validatePresetRegistry(presets: readonly Preset[]): Preset[] {\n const validatedPresets = presets.map((preset) => parsePreset(preset));\n const seenIds = new Set<string>();\n\n for (const preset of validatedPresets) {\n if (seenIds.has(preset.id)) {\n throw new PresetValidationError([`Duplicate preset id \"${preset.id}\".`]);\n }\n\n seenIds.add(preset.id);\n }\n\n return [...validatedPresets].sort((left, right) => left.id.localeCompare(right.id));\n}\n","import { flutterPreset } from \"../../presets/flutter/preset.js\";\nimport { genericPreset } from \"../../presets/generic/preset.js\";\nimport { iosSwiftPreset } from \"../../presets/ios-swift/preset.js\";\nimport { kotlinAndroidPreset } from \"../../presets/kotlin-android/preset.js\";\nimport { laravelApiPreset } from \"../../presets/laravel-api/preset.js\";\nimport { laravelReactPreset } from \"../../presets/laravel-react/preset.js\";\nimport { laravelVuePreset } from \"../../presets/laravel-vue/preset.js\";\nimport { nextjsPreset } from \"../../presets/nextjs/preset.js\";\nimport { pythonFastapiPreset } from \"../../presets/python-fastapi/preset.js\";\nimport { validatePresetRegistry } from \"./validate-preset.js\";\nimport type { Preset } from \"./preset-schema.js\";\n\nconst builtInPresets = validatePresetRegistry([\n flutterPreset,\n genericPreset,\n iosSwiftPreset,\n kotlinAndroidPreset,\n laravelApiPreset,\n laravelReactPreset,\n laravelVuePreset,\n nextjsPreset,\n pythonFastapiPreset,\n]);\n\nexport function listPresets(): Preset[] {\n return [...builtInPresets];\n}\n\nexport function getPreset(id: string): Preset | undefined {\n return builtInPresets.find((preset) => preset.id === id);\n}\n","import type { SkillDefinition } from \"./skill-catalog.js\";\n\n/**\n * Render a SkillDefinition into a valid Agent Skills SKILL.md.\n *\n * The output uses only the standard portable fields (`name`, `description`) and contains no scripts,\n * so the same file works in Claude Code and other Agent Skills-compatible tools.\n */\nexport function renderSkill(skill: SkillDefinition): string {\n const lines: string[] = [\n \"---\",\n `name: ${skill.name}`,\n // JSON-stringify yields a valid double-quoted YAML scalar, so descriptions with any punctuation\n // stay valid Agent Skills frontmatter.\n `description: ${JSON.stringify(skill.description)}`,\n \"---\",\n \"\",\n `# Skill: ${skill.title}`,\n \"\",\n \"## Purpose\",\n \"\",\n ...paragraphs(skill.purpose),\n \"\",\n \"## Inputs\",\n \"\",\n ...bullets(skill.inputs),\n \"\",\n \"## Required Reading\",\n \"\",\n ...bullets(skill.requiredReading),\n \"\",\n \"## Output Files\",\n \"\",\n ...bullets(skill.outputFiles),\n \"\",\n \"## Process\",\n \"\",\n ...numbered(skill.process),\n \"\",\n ];\n\n for (const section of skill.extraSections ?? []) {\n lines.push(`## ${section.heading}`, \"\", ...bullets(section.bullets), \"\");\n }\n\n lines.push(\n \"## Stop Conditions\",\n \"\",\n \"Stop and request human decision if:\",\n \"\",\n ...bullets(skill.stopConditions),\n \"\",\n \"## Quality Bar\",\n \"\",\n ...bullets(skill.qualityBar),\n );\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction paragraphs(values: string[]): string[] {\n const out: string[] = [];\n values.forEach((value, index) => {\n if (index > 0) {\n out.push(\"\");\n }\n out.push(value);\n });\n return out;\n}\n\nfunction bullets(values: string[]): string[] {\n return values.map((value) => `- ${value}`);\n}\n\nfunction numbered(values: string[]): string[] {\n return values.map((value, index) => `${index + 1}. ${value}`);\n}\n","export type SkillDefinition = {\n name: string;\n title: string;\n description: string;\n purpose: string[];\n inputs: string[];\n requiredReading: string[];\n outputFiles: string[];\n process: string[];\n extraSections?: { heading: string; bullets: string[] }[];\n stopConditions: string[];\n qualityBar: string[];\n};\n\n/**\n * Built-in catalog of Recall OS workflow skills.\n *\n * Each skill is portable (standard Agent Skills fields only) and contains no scripts, so the same\n * SKILL.md works across Claude Code and other Agent Skills-compatible tools. Descriptions include\n * \"Use when ...\" trigger language so agents invoke them at the right moment.\n */\nexport const SKILL_CATALOG: SkillDefinition[] = [\n {\n name: \"create-prd\",\n title: \"Create PRD\",\n description:\n \"Create or update a feature PRD with user intent, scope, acceptance criteria, non-goals, security notes, test expectations, and source-of-truth links. Use when starting a feature, drafting or updating a PRD, or defining acceptance criteria.\",\n purpose: [\n \"Create a useful feature PRD that helps humans and AI agents understand what should be built and why.\",\n ],\n inputs: [\n \"Feature name or problem statement.\",\n \"User goal or business reason.\",\n \"Any existing product notes, tickets, or change requests.\",\n ],\n requiredReading: [\n \"`docs/00-product/BRD.md`\",\n \"`docs/00-product/PRD.md`\",\n \"Relevant existing `docs/40-features/<feature>/`\",\n \"Relevant accepted ADRs in `docs/adrs/`\",\n ],\n outputFiles: [\n \"`docs/40-features/<feature>/PRD.md`\",\n \"`docs/40-features/<feature>/ACCEPTANCE.md`, when acceptance criteria are part of the request.\",\n \"`docs/40-features/<feature>/CHANGE_REQUESTS.md`, when changing existing requirements.\",\n ],\n process: [\n \"Identify the user, problem, desired outcome, and non-goals.\",\n \"Link the feature to product goals and existing source-of-truth docs.\",\n \"Define acceptance criteria that can be tested.\",\n \"Capture security, privacy, file write, dependency, and MCP implications.\",\n \"Identify architecture areas that require follow-up review.\",\n \"Keep the PRD concise and implementation-guiding.\",\n ],\n stopConditions: [\n \"Product intent is contradictory.\",\n \"A requested behavior conflicts with an accepted ADR.\",\n \"The feature adds network, telemetry, AI API, cloud, MCP runtime, auth, secrets, or file write behavior without explicit approval.\",\n \"Scope is too broad to define testable acceptance criteria.\",\n ],\n qualityBar: [\n \"The PRD states goals, non-goals, users, acceptance criteria, risks, and source links.\",\n \"Acceptance criteria are concrete enough to drive tests.\",\n \"Security and architecture implications are not generic filler.\",\n \"The PRD does not duplicate full architecture docs.\",\n ],\n },\n {\n name: \"plan-feature\",\n title: \"Plan Feature\",\n description:\n \"Plan a feature from approved requirements by producing implementation tasks, architecture impact, test plan, review expectations, and completion evidence. Use when turning an approved PRD into a plan, tasks, and a test plan.\",\n purpose: [\n \"Turn product intent into a scoped engineering plan that an implementation agent can follow safely.\",\n ],\n inputs: [\n \"Feature PRD.\",\n \"Acceptance criteria.\",\n \"Relevant module or architecture docs.\",\n \"Known constraints or release target.\",\n ],\n requiredReading: [\n \"`docs/10-architecture/ARCHITECTURE.md`\",\n \"`docs/10-architecture/FILE_WRITE_POLICY.md`\",\n \"`docs/20-security/SECURITY_MODEL.md`\",\n \"`docs/50-quality/QUALITY_GATES.md`\",\n \"`docs/60-engineering/ENGINEERING_STANDARDS.md`\",\n \"Relevant feature docs under `docs/40-features/`\",\n \"Relevant module docs under `docs/30-modules/`\",\n \"Relevant ADRs under `docs/adrs/`\",\n ],\n outputFiles: [\n \"`docs/40-features/<feature>/PLAN.md`\",\n \"`docs/40-features/<feature>/TASKS.md`\",\n \"`docs/40-features/<feature>/ARCHITECTURE_IMPACT.md`\",\n \"`docs/40-features/<feature>/TEST_PLAN.md`\",\n ],\n process: [\n \"Restate the feature objective and acceptance criteria.\",\n \"Identify modules, docs, templates, and tests affected.\",\n \"Document architecture impact and ADR needs.\",\n \"Break work into ordered tasks with clear completion evidence.\",\n \"Define tests from requirements, risk, security invariants, and regressions.\",\n \"For module requests, treat the module as a mini product and create feature delivery docs before implementation tasks.\",\n ],\n stopConditions: [\n \"Requirements are missing or contradictory.\",\n \"Architecture impact cannot be determined.\",\n \"The plan conflicts with engineering standards.\",\n \"A task requires changing accepted non-goals.\",\n \"A module request tries to start implementation before PRD, acceptance, architecture impact, test plan, and tasks exist.\",\n ],\n qualityBar: [\n \"Tasks are ordered and independently reviewable.\",\n \"Tests map to acceptance criteria and risks.\",\n \"Architecture impact is explicit.\",\n \"Engineering standards are accounted for in tasks and completion evidence.\",\n \"The plan does not include implementation code when only planning is requested.\",\n ],\n },\n {\n name: \"plan-module\",\n title: \"Plan Module\",\n description:\n \"Plan a module as a mini product by creating feature delivery docs, module memory, acceptance criteria, architecture impact, test plan, and ordered tasks before implementation. Use when asked to build, create, redesign, or materially change a module.\",\n purpose: [\n \"Turn a module request into a complete delivery workflow before implementation starts.\",\n ],\n inputs: [\n \"Module name or request.\",\n \"Product goal or user need.\",\n \"Existing architecture, feature, or module docs.\",\n \"Known constraints or priority stage.\",\n ],\n requiredReading: [\n \"`AGENTS.md`\",\n \"`docs/00-product/PRD.md`\",\n \"`docs/10-architecture/ARCHITECTURE.md`\",\n \"`docs/20-security/SECURITY_MODEL.md`\",\n \"`docs/50-quality/TESTING_STRATEGY.md`\",\n \"`docs/60-engineering/ENGINEERING_STANDARDS.md`\",\n \"`docs/ai/MODULE_DELIVERY_WORKFLOW.md`\",\n \"Relevant ADRs under `docs/adrs/`\",\n ],\n outputFiles: [\n \"`docs/40-features/F-###-<module>-module/` delivery docs (PRD, ACCEPTANCE, ARCHITECTURE_IMPACT, PLAN, TASKS, TEST_PLAN, REVIEW, COMPLETION_REPORT).\",\n \"`docs/30-modules/<module>/MODULE.md`\",\n \"`docs/30-modules/<module>/TASKS.md`\",\n \"`docs/30-modules/<module>/TEST_PLAN.md`\",\n \"`docs/30-modules/<module>/DECISIONS.md`\",\n ],\n process: [\n \"Create a module brief: ownership, non-ownership, public interfaces, users, and use cases.\",\n \"Define behavior and edge cases.\",\n \"Write testable acceptance criteria.\",\n \"Document architecture impact, dependency impact, config impact, template impact, and ADR needs.\",\n \"Write the test plan from acceptance criteria, security invariants, and regression risk.\",\n \"Break work into ordered tasks with status, scope, acceptance, tests, and do-not-do boundaries.\",\n \"Mark implementation as blocked until the first task is selected.\",\n ],\n stopConditions: [\n \"The module ownership or public interface is unclear.\",\n \"The module conflicts with accepted ADRs or architecture docs.\",\n \"The module conflicts with engineering standards.\",\n \"The module requires runtime network, telemetry, cloud, MCP, AI API, auth, secrets, storage, or file write behavior changes without ADR or security review.\",\n \"The user asks to implement before PRD, acceptance, architecture impact, test plan, and tasks exist.\",\n ],\n qualityBar: [\n \"The module is planned as a mini product, not a file list.\",\n \"PRD, acceptance, architecture impact, test plan, and tasks are all present.\",\n \"Tasks are small enough to execute one at a time.\",\n \"Module memory captures what future agents need to remember.\",\n \"No implementation code is written by this skill.\",\n ],\n },\n {\n name: \"create-adr\",\n title: \"Create ADR\",\n description:\n \"Create an Architecture Decision Record for a meaningful architecture, dependency, security, file-write, MCP, or workflow decision. Use when recording such a decision so future agents do not contradict it.\",\n purpose: [\n \"Record durable architecture decisions so future humans and agents do not rediscover or contradict them.\",\n ],\n inputs: [\n \"Decision topic.\",\n \"Context and constraints.\",\n \"Options considered.\",\n \"Recommended or selected decision.\",\n ],\n requiredReading: [\n \"`docs/10-architecture/ARCHITECTURE.md`\",\n \"`docs/10-architecture/FILE_WRITE_POLICY.md`\",\n \"`docs/20-security/SECURITY_MODEL.md`\",\n \"Relevant existing ADRs in `docs/adrs/`\",\n ],\n outputFiles: [\"`docs/adrs/ADR-####-<slug>.md`\"],\n process: [\n \"Determine whether the change needs an ADR.\",\n \"Find the next ADR number without reusing existing numbers.\",\n \"Write context, decision, alternatives, consequences, and related docs.\",\n \"Mark the status as `Proposed` unless the human has accepted the decision.\",\n \"Link to affected PRDs, architecture docs, feature docs, and security docs.\",\n ],\n stopConditions: [\n \"The decision changes security posture, network behavior, telemetry, file writes, auth, secrets, cloud, or runtime MCP.\",\n \"The requested decision conflicts with an accepted ADR.\",\n \"The decision is not actually made yet and should remain a proposal.\",\n ],\n qualityBar: [\n \"The ADR explains why the decision exists, not just what changed.\",\n \"Alternatives and consequences are honest.\",\n \"Status is clear.\",\n \"Related documents are linked.\",\n ],\n },\n {\n name: \"implement-task\",\n title: \"Implement Task\",\n description:\n \"Implement one scoped engineering task while preserving requirements, architecture boundaries, security posture, tests, docs, and completion evidence. Use when implementing a single task from an approved plan.\",\n purpose: [\"Implement a bounded task safely from approved requirements and plans.\"],\n inputs: [\n \"Task description.\",\n \"Feature plan or acceptance criteria.\",\n \"Relevant module and architecture docs.\",\n ],\n requiredReading: [\n \"`AGENTS.md`\",\n \"`docs/10-architecture/ARCHITECTURE.md`\",\n \"`docs/10-architecture/FILE_WRITE_POLICY.md`\",\n \"`docs/20-security/SECURITY_MODEL.md`\",\n \"`docs/60-engineering/ENGINEERING_STANDARDS.md`\",\n \"Relevant feature, module, and ADR docs.\",\n ],\n outputFiles: [\n \"Implementation files for the scoped task.\",\n \"Tests for changed behavior.\",\n \"Updated module, feature, or completion docs when behavior changes.\",\n ],\n process: [\n \"Confirm the task has clear acceptance criteria.\",\n \"Confirm the task comes after PRD, acceptance, architecture impact, and test plan.\",\n \"Identify affected modules and tests.\",\n \"Implement the smallest safe change.\",\n \"Add or update tests based on risk.\",\n \"Update docs when behavior, architecture, or module ownership changes.\",\n \"Prepare completion evidence with commands and results.\",\n ],\n stopConditions: [\n \"The task conflicts with source-of-truth docs.\",\n \"The task conflicts with engineering standards.\",\n \"The task requires adding runtime network, telemetry, cloud, MCP, AI API, or generated production app behavior without review.\",\n \"A dependency is needed without ADR consideration.\",\n \"Tests cannot be designed from the available requirements.\",\n ],\n qualityBar: [\n \"Scope stays narrow.\",\n \"Tests cover behavior and risk.\",\n \"File write and security rules are preserved.\",\n \"Engineering standards are followed.\",\n \"Completion evidence is concrete.\",\n \"One task is implemented at a time.\",\n ],\n },\n {\n name: \"write-tests\",\n title: \"Write Tests\",\n description:\n \"Write meaningful tests from acceptance criteria, risk, security invariants, module boundaries, and regression history. Use when adding or updating tests, writing a test plan, or covering a new feature or bug fix.\",\n purpose: [\"Create professional tests that prove important behavior, not random happy paths.\"],\n inputs: [\n \"Feature PRD or task.\",\n \"Acceptance criteria.\",\n \"Changed files or planned modules.\",\n \"Known risks.\",\n ],\n requiredReading: [\n \"`docs/50-quality/TESTING_STRATEGY.md`\",\n \"`docs/50-quality/QUALITY_GATES.md`\",\n \"`docs/20-security/SECURITY_MODEL.md`\",\n \"`docs/60-engineering/ENGINEERING_STANDARDS.md`\",\n \"Relevant feature `TEST_PLAN.md`\",\n \"Relevant module `TEST_PLAN.md`\",\n ],\n outputFiles: [\n \"Test files under the appropriate `tests/` area.\",\n \"Updated `TEST_PLAN.md` when test strategy changes.\",\n \"Completion evidence listing commands and results.\",\n ],\n process: [\n \"Map acceptance criteria to test cases.\",\n \"Add risk-based tests for unsafe paths, overwrites, symlinks, config validation, generated output, and CLI behavior as relevant.\",\n \"Prefer unit tests for pure logic and integration tests for command behavior.\",\n \"Add golden tests for generated docs and templates.\",\n \"Name tests by behavior.\",\n \"Document skipped tests and remaining risk.\",\n ],\n stopConditions: [\n \"Requirements are not testable.\",\n \"The requested test would require runtime network, telemetry, cloud, MCP, or AI API behavior without review.\",\n \"Security-sensitive behavior lacks a documented expected result.\",\n \"The test approach conflicts with engineering standards.\",\n ],\n qualityBar: [\n \"Tests derive from requirements and risk.\",\n \"Security invariants are covered.\",\n \"Test names describe behavior.\",\n \"Engineering standards for evidence and skipped checks are followed.\",\n \"The completion report includes commands and results.\",\n ],\n },\n {\n name: \"security-review\",\n title: \"Security Review\",\n description:\n \"Review a change for file write safety, path traversal, symlink risk, overwrite behavior, dependencies, secrets, telemetry, network, MCP, and supply chain risk. Use when reviewing a change for security before it is accepted.\",\n purpose: [\"Find security risks before a change is accepted.\"],\n inputs: [\n \"Change summary or diff.\",\n \"Feature docs.\",\n \"Architecture and security docs.\",\n \"Test results.\",\n ],\n requiredReading: [\n \"`docs/20-security/SECURITY_MODEL.md`\",\n \"`docs/20-security/THREAT_MODEL.md`\",\n \"`docs/10-architecture/FILE_WRITE_POLICY.md`\",\n \"`docs/60-engineering/ENGINEERING_STANDARDS.md`\",\n \"`docs/ai/MCP_STRATEGY.md`\",\n ],\n outputFiles: [\n \"Relevant feature `REVIEW.md`\",\n \"Relevant feature `COMPLETION_REPORT.md`\",\n \"Security docs, if the accepted behavior changes.\",\n ],\n process: [\n \"Identify changed trust boundaries.\",\n \"Check path validation, overwrite policy, symlink policy, and dry-run behavior.\",\n \"Check dependency, package, template, and preset risk.\",\n \"Check for network, telemetry, secrets, `.env`, cloud, AI API, or runtime MCP behavior.\",\n \"Check tests for security-sensitive behavior.\",\n \"Classify findings as blockers, risks, or documented acceptable tradeoffs.\",\n ],\n stopConditions: [\n \"Runtime network, telemetry, cloud, MCP, AI API, auth, secrets, storage, or file write behavior changes without ADR or security review.\",\n \"Existing files can be overwritten by default.\",\n \"Writes can escape the project root.\",\n \"Secrets could be read, logged, or generated into docs.\",\n \"Engineering standards are bypassed for secrets, dependencies, migrations, tests, or completion evidence.\",\n ],\n qualityBar: [\n \"Findings are specific and actionable.\",\n \"Security claims cite docs or test evidence.\",\n \"Remaining risks are explicit.\",\n ],\n },\n {\n name: \"architecture-drift-review\",\n title: \"Architecture Drift Review\",\n description:\n \"Review a change for undocumented architecture, dependency, module, security, testing, or documentation drift. Use when checking whether a change diverges from accepted repository memory.\",\n purpose: [\n \"Find changes that diverge from accepted repository memory.\",\n \"Drift is not difference from a Recall OS recommendation. Recall OS is architecture-neutral.\",\n ],\n inputs: [\"Change summary or diff.\", \"Feature docs.\", \"Module docs.\", \"ADRs.\", \"Test results.\"],\n requiredReading: [\n \"`docs/10-architecture/ARCHITECTURE.md`\",\n \"`docs/60-engineering/ENGINEERING_STANDARDS.md`\",\n \"`docs/20-security/SECURITY_MODEL.md`\",\n \"Relevant `docs/30-modules/<module>/MODULE.md`\",\n \"Relevant `docs/40-features/<feature>/PRD.md`\",\n \"Relevant `docs/adrs/*.md`\",\n ],\n outputFiles: [\n \"Relevant feature `REVIEW.md`\",\n \"Relevant feature `COMPLETION_REPORT.md`\",\n \"Updated docs only when the human accepts documented evolution.\",\n ],\n process: [\n \"Review the change and identify changed modules and generated outputs.\",\n \"Compare changes against accepted ADRs and repository decisions.\",\n \"Compare changes against module boundaries.\",\n \"Check for new dependencies and security-sensitive changes.\",\n \"Check whether tests and docs were updated.\",\n \"Classify findings.\",\n ],\n extraSections: [\n {\n heading: \"Finding Types\",\n bullets: [\n \"Architecture drift\",\n \"Dependency drift\",\n \"Module drift\",\n \"Security drift\",\n \"Testing drift\",\n \"Documentation drift\",\n \"Engineering standards drift\",\n \"Acceptable documented evolution\",\n ],\n },\n ],\n stopConditions: [\n \"An accepted ADR conflicts with the implementation.\",\n \"The implementation conflicts with engineering standards.\",\n \"A dependency was added without ADR consideration.\",\n \"Authentication, authorization, storage, networking, secrets, telemetry, cloud, runtime MCP, or file write behavior changed without security review.\",\n \"Feature behavior changed without a PRD or change request update.\",\n ],\n qualityBar: [\n \"Findings distinguish drift from documented evolution.\",\n \"Findings compare against accepted repository memory, not Recall OS preferences.\",\n \"Each blocker names the missing source-of-truth update.\",\n \"Review output is concrete enough to act on.\",\n ],\n },\n {\n name: \"update-module-memory\",\n title: \"Update Module Memory\",\n description:\n \"Update module memory docs after module behavior, ownership, boundaries, tests, risks, or decisions change. Use when a module's behavior, ownership, boundaries, tests, risks, or decisions change.\",\n purpose: [\n \"Keep module docs accurate so agents do not rediscover ownership, boundaries, tests, and decisions.\",\n ],\n inputs: [\n \"Changed module or feature.\",\n \"Implementation summary.\",\n \"Test results.\",\n \"Architecture or ADR changes.\",\n ],\n requiredReading: [\n \"`docs/60-engineering/ENGINEERING_STANDARDS.md`\",\n \"`docs/ai/MODULE_DELIVERY_WORKFLOW.md`\",\n \"Relevant `docs/30-modules/<module>/MODULE.md`\",\n \"Relevant `docs/30-modules/<module>/DECISIONS.md`\",\n \"Relevant feature docs and ADRs.\",\n ],\n outputFiles: [\n \"`docs/30-modules/<module>/MODULE.md`\",\n \"`docs/30-modules/<module>/TASKS.md`\",\n \"`docs/30-modules/<module>/TEST_PLAN.md`\",\n \"`docs/30-modules/<module>/DECISIONS.md`\",\n ],\n process: [\n \"Identify affected modules.\",\n \"Confirm module memory is linked to feature delivery docs when the module is new or materially changed.\",\n \"Update module purpose, responsibilities, non-responsibilities, public interfaces, and boundaries when behavior changes.\",\n \"Update task status only when supported by completion evidence.\",\n \"Update test expectations when risks or behavior change.\",\n \"Record decisions or link ADRs when architecture changes.\",\n \"Avoid copying full feature docs into module docs.\",\n ],\n stopConditions: [\n \"Module ownership is unclear.\",\n \"A change crosses module boundaries without architecture review.\",\n \"Module memory updates would conflict with engineering standards.\",\n \"A decision belongs in an ADR instead of a module note.\",\n \"Feature delivery docs are missing for new module work.\",\n ],\n qualityBar: [\n \"Module docs are concise and current.\",\n \"Boundaries are clear.\",\n \"Test expectations are actionable.\",\n \"Decisions link to ADRs where appropriate.\",\n \"Future agents can tell what the module owns and what it must not own.\",\n ],\n },\n {\n name: \"completion-report\",\n title: \"Completion Report\",\n description:\n \"Write a completion report with files changed, tests run, results, skipped checks, docs updated, remaining risks, and release readiness notes. Use when recording evidence that a task or feature is complete and ready for review.\",\n purpose: [\"Record evidence that a task is complete and safe to review.\"],\n inputs: [\n \"Task or feature summary.\",\n \"Files changed.\",\n \"Commands run.\",\n \"Test results.\",\n \"Docs updated.\",\n \"Known risks.\",\n ],\n requiredReading: [\n \"`docs/50-quality/QUALITY_GATES.md`\",\n \"`docs/60-engineering/ENGINEERING_STANDARDS.md`\",\n \"Relevant feature `TASKS.md`\",\n \"Relevant feature `TEST_PLAN.md`\",\n \"Relevant feature `REVIEW.md`\",\n ],\n outputFiles: [\n \"Relevant feature `COMPLETION_REPORT.md`\",\n \"Task or feature docs that need final status updates.\",\n ],\n process: [\n \"Summarize the completed scope.\",\n \"List files changed by category.\",\n \"List commands run and results.\",\n \"List skipped checks and why.\",\n \"List docs updated.\",\n \"State whether engineering standards were followed.\",\n \"List remaining risks and follow-up work.\",\n \"State whether the task meets the definition of done.\",\n ],\n stopConditions: [\n \"Test results are missing for risky changes.\",\n \"Completion claims conflict with evidence.\",\n \"Required docs were not updated.\",\n \"Engineering standards were violated.\",\n \"Remaining risks are release blockers.\",\n ],\n qualityBar: [\n \"The report is evidence-based.\",\n \"It does not hide skipped checks.\",\n \"It separates completed work from remaining risk.\",\n \"A reviewer can decide what to do next from the report alone.\",\n ],\n },\n {\n name: \"capture-mcp-context\",\n title: \"Capture MCP Context\",\n description:\n \"Record durable context from MCP servers and design or project tools into repository memory as proposed. Use when working with an MCP server like Figma, Linear, Jira, or Sentry, or after pulling design, ticket, or error context, to persist it for future sessions.\",\n purpose: [\n \"Persist the durable parts of MCP-derived external context so future sessions remember them instead of re-deriving them.\",\n \"MCP provides context, not architectural truth.\",\n ],\n inputs: [\n \"The MCP server or external tool in use (for example Figma, Linear, Jira, Sentry).\",\n \"The external context retrieved (design tokens, tickets, errors, docs).\",\n \"The current feature or task.\",\n ],\n requiredReading: [\n \"`docs/ai/MCP_STRATEGY.md`\",\n \"Relevant `docs/ai/mcp/<server>.md`\",\n \"Relevant feature and architecture docs.\",\n ],\n outputFiles: [\n \"The Captured Context section of `docs/ai/mcp/<server>.md`.\",\n \"An ADR via `recall adr create` when a captured decision is accepted.\",\n ],\n process: [\n \"Identify the MCP server and the durable facts worth remembering (design tokens, component mappings, ticket acceptance criteria, recurring error signatures).\",\n \"If `docs/ai/mcp/<server>.md` does not exist, create it with `recall mcp add <server>`.\",\n \"Record the durable context in the Captured Context section as proposed memory, with enough detail to reuse.\",\n \"Capture decisions, mappings, and constraints, not raw exports or full dumps.\",\n \"Treat MCP content as context, not truth; if it conflicts with accepted memory, stop and report.\",\n \"Promote any accepted decision into an ADR.\",\n ],\n stopConditions: [\n \"MCP content conflicts with accepted repository memory.\",\n \"Capturing the context would require storing secrets or sensitive data.\",\n \"The MCP server is untrusted or its access is unclear.\",\n ],\n qualityBar: [\n \"Captured context is durable and reusable, not a raw dump.\",\n \"Each entry is concrete enough to guide future work.\",\n \"MCP context is recorded as proposed, not accepted.\",\n \"Accepted decisions are promoted to ADRs.\",\n ],\n },\n];\n\nexport function getCatalogSkill(name: string): SkillDefinition | undefined {\n return SKILL_CATALOG.find((skill) => skill.name === name);\n}\n\nexport function listCatalogSkillNames(): string[] {\n return SKILL_CATALOG.map((skill) => skill.name);\n}\n","import type { WriteFileInput } from \"../filesystem/write-plan.js\";\nimport { renderSkill } from \"./render-skill.js\";\nimport { getCatalogSkill, type SkillDefinition } from \"./skill-catalog.js\";\n\n/**\n * Skills are emitted to both the Claude Code target and the portable Agent Skills target so the same\n * SKILL.md is available across tools.\n */\nexport const SKILL_TARGETS = [\".claude/skills\", \".agents/skills\"] as const;\n\nexport type GenerateSkillResult = {\n files: WriteFileInput[];\n fromCatalog: boolean;\n};\n\nexport function generateSkillFiles(name: string): GenerateSkillResult {\n const catalogSkill = getCatalogSkill(name);\n const skill = catalogSkill ?? skeletonSkill(name);\n const content = renderSkill(skill);\n\n return {\n files: SKILL_TARGETS.map((target) => ({\n path: `${target}/${name}/SKILL.md`,\n content,\n })),\n fromCatalog: catalogSkill !== undefined,\n };\n}\n\nfunction skeletonSkill(name: string): SkillDefinition {\n return {\n name,\n title: titleize(name),\n description: `Describe what the ${name} skill does and when to use it. Use when ... (replace this with concrete trigger keywords).`,\n purpose: [\"Describe the single job this skill performs.\"],\n inputs: [\"List the inputs this skill needs.\"],\n requiredReading: [\"List the source-of-truth docs this skill must read.\"],\n outputFiles: [\"List the files this skill produces or updates.\"],\n process: [\"Describe the steps, one job, routing to source-of-truth docs.\"],\n stopConditions: [\n \"A request conflicts with accepted repository memory or engineering standards.\",\n \"The work would add network, telemetry, MCP runtime, AI API, or other accepted non-goals.\",\n ],\n qualityBar: [\"State how to tell the skill did its job well.\"],\n };\n}\n\nfunction titleize(name: string): string {\n return name\n .split(\"-\")\n .filter((part) => part.length > 0)\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(\" \");\n}\n","export type KnownServer = {\n title: string;\n purpose: string;\n dataAccessed: string[];\n};\n\n/**\n * Purpose and data hints for well-known MCP servers, drawn from the MCP strategy guidance. Used to\n * pre-fill generated MCP memory. Recall OS never connects to these servers; this is static guidance.\n */\nconst KNOWN_SERVERS: Record<string, KnownServer> = {\n figma: {\n title: \"Figma\",\n purpose: \"Design variables, components, and layout metadata for building consistent UI.\",\n dataAccessed: [\n \"Design tokens and variables.\",\n \"Component and layout metadata.\",\n \"Frames and styles.\",\n ],\n },\n linear: {\n title: \"Linear\",\n purpose: \"Tickets, project status, and acceptance criteria.\",\n dataAccessed: [\n \"Issues and tickets.\",\n \"Project and cycle status.\",\n \"Acceptance criteria in issues.\",\n ],\n },\n jira: {\n title: \"Jira\",\n purpose: \"Tickets, sprints, and acceptance criteria for knocking out tasks.\",\n dataAccessed: [\n \"Issues and tickets.\",\n \"Sprint and board status.\",\n \"Acceptance criteria in issues.\",\n ],\n },\n github: {\n title: \"GitHub\",\n purpose: \"Pull requests, issues, and review comments.\",\n dataAccessed: [\"Pull requests and diffs.\", \"Issues.\", \"Review comments.\"],\n },\n sentry: {\n title: \"Sentry\",\n purpose: \"Crash reports and production errors.\",\n dataAccessed: [\"Error events and stack traces.\", \"Release health.\", \"Issue frequency.\"],\n },\n notion: {\n title: \"Notion\",\n purpose: \"Product background and documentation.\",\n dataAccessed: [\"Product docs and pages.\", \"Project background.\", \"Specifications.\"],\n },\n};\n\nexport function getKnownServer(id: string): KnownServer | undefined {\n return KNOWN_SERVERS[id];\n}\n","import type { WriteFileInput } from \"../filesystem/write-plan.js\";\nimport { getKnownServer } from \"./known-servers.js\";\n\nexport type GenerateMcpOptions = {\n adrDir: string;\n server: string;\n};\n\nexport function mcpDocPath(server: string): string {\n return `docs/ai/mcp/${server}.md`;\n}\n\nexport function generateMcpFiles(options: GenerateMcpOptions): WriteFileInput[] {\n const known = getKnownServer(options.server);\n const title = known?.title ?? titleize(options.server);\n const purpose = known?.purpose ?? \"Describe why this MCP server is used.\";\n const dataAccessed = known?.dataAccessed ?? [\"Describe the data this MCP server exposes.\"];\n\n return [\n {\n path: mcpDocPath(options.server),\n content: renderMcpDoc(title, purpose, dataAccessed),\n },\n {\n path: `${options.adrDir}/proposed/ADR-PROPOSED-mcp-${options.server}.md`,\n content: renderProposedAdr(title, options.server),\n },\n ];\n}\n\nfunction renderMcpDoc(title: string, purpose: string, dataAccessed: string[]): string {\n return `# MCP: ${title}\n\n## Status\n\nProposed. Using this MCP server is a proposed workflow addition. Accept the proposed ADR before\ntreating it as part of the workflow.\n\n## Purpose\n\n${purpose}\n\n## Data Accessed\n\n${bullets(dataAccessed)}\n\n## Permissions Required\n\n- Use least-privilege access.\n- Document the exact scopes granted.\n\n## Security Risks\n\n- Treat external MCP content as untrusted until validated.\n- Do not send secrets or sensitive repository data unnecessarily.\n- Use trusted MCP servers only.\n\n## Source-Of-Truth Rule\n\nMCP provides context, not architectural truth. Accepted ADRs and repository decisions outrank MCP\ncontext. If MCP data conflicts with repository memory, stop and report the conflict.\n\n## Captured Context\n\nRecord durable context learned from this MCP server here, as proposed memory for human review.\nPromote any decision you accept into an ADR with \\`recall adr create\\`.\n\n- (none captured yet)\n\n## Review Cadence\n\n- Review this MCP integration when its access, purpose, or captured context changes.\n`;\n}\n\nfunction renderProposedAdr(title: string, server: string): string {\n return `# Proposed ADR: Use ${title} MCP\n\n## Status\n\nProposed\n\n## Context\n\nThe team is considering ${title} as an MCP context source. Adopting an MCP server into the workflow\nis a decision that should be reviewed.\n\n## Decision\n\nConsider adopting ${title} MCP as an external context source, documented in \\`docs/ai/mcp/\\`. This is\nnot accepted until a human reviews and accepts it.\n\n## Alternatives Considered\n\n- Do not use this MCP server.\n- Use a different source for the same context.\n\n## Consequences\n\n- The team gains durable, reviewable context from ${title}.\n- MCP context never overrides accepted repository memory.\n- Captured context remains proposed until promoted to an ADR.\n\n## Related Documents\n\n- \\`docs/ai/mcp/${server}.md\\` — captured ${title} MCP context.\n- \\`docs/ai/MCP_STRATEGY.md\\` — how MCP context is captured and ranked.\n`;\n}\n\nfunction bullets(values: string[]): string {\n return values.map((value) => `- ${value}`).join(\"\\n\");\n}\n\nfunction titleize(value: string): string {\n return value\n .split(\"-\")\n .filter((part) => part.length > 0)\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(\" \");\n}\n","import { createDefaultConfig } from \"../../core/config/default-config.js\";\nimport { ConfigValidationError } from \"../../core/config/config-schema.js\";\nimport { loadConfig, ConfigLoadError } from \"../../core/config/load-config.js\";\nimport { generateMcpFiles, mcpDocPath } from \"../../core/mcp/generate-mcp.js\";\nimport { generateSkillFiles } from \"../../core/skills/generate-skill.js\";\nimport { createWritePlan, type WritePlan } from \"../../core/filesystem/write-plan.js\";\nimport { executeWritePlan, type WriteResult } from \"../../core/filesystem/write-file-safe.js\";\nimport { SlugifyError, slugify } from \"../../core/naming/slugify.js\";\nimport { appendNextSteps, appendWriteSummary } from \"../write-summary.js\";\n\nexport type McpAddOptions = {\n rootDir: string;\n server: string;\n dryRun?: boolean;\n force?: boolean;\n};\n\nexport type McpAddResult = {\n server: string;\n docPath: string;\n dryRun: boolean;\n plan: WritePlan;\n writeResult: WriteResult;\n};\n\nexport type McpAddErrorCode = \"INVALID_SERVER_NAME\" | \"WRITE_PLAN_ERROR\";\n\nexport class McpAddError extends Error {\n readonly code: McpAddErrorCode;\n readonly details: string[];\n\n constructor(code: McpAddErrorCode, message: string, details: string[] = []) {\n super(message);\n this.name = \"McpAddError\";\n this.code = code;\n this.details = details;\n }\n}\n\nexport async function mcpAdd(options: McpAddOptions): Promise<McpAddResult> {\n const server = createServerSlug(options.server);\n const config = await loadConfigOrDefault(options.rootDir);\n // The memory doc and adoption ADR, plus the capture skill that tells agents to record durable\n // MCP-derived context into that doc. The skill is shared across servers and skipped if it exists.\n const files = [\n ...generateMcpFiles({ adrDir: config.adrDir, server }),\n ...generateSkillFiles(\"capture-mcp-context\").files,\n ];\n const plan = createWritePlan({\n rootDir: options.rootDir,\n files,\n force: options.force,\n });\n\n if (plan.hasErrors) {\n throw new McpAddError(\n \"WRITE_PLAN_ERROR\",\n \"Recall OS mcp add write plan contains errors.\",\n plan.entries\n .filter((entry) => entry.action === \"error\")\n .map((entry) => `${entry.path}: ${entry.reason}`),\n );\n }\n\n const writeResult = await executeWritePlan(plan, { dryRun: options.dryRun });\n\n return {\n server,\n docPath: mcpDocPath(server),\n dryRun: options.dryRun ?? false,\n plan,\n writeResult,\n };\n}\n\nexport function formatMcpAddResult(result: McpAddResult): string {\n const lines = [\n result.dryRun ? \"Recall OS mcp add dry run complete.\" : \"Recall OS mcp add complete.\",\n `MCP memory: ${result.docPath} (proposed — review before adopting)`,\n \"Capture skill installed so agents record durable MCP context into this memory.\",\n ];\n\n appendWriteSummary(lines, {\n dryRun: result.dryRun,\n writeResult: result.writeResult,\n });\n\n if (!result.dryRun) {\n appendNextSteps(lines, [\n `Open ${result.docPath} and confirm purpose, data accessed, and permissions.`,\n \"Your agent records durable context into the Captured Context section via the capture-mcp-context skill.\",\n \"Accept the proposed ADR once you adopt the server.\",\n ]);\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction createServerSlug(server: string): string {\n try {\n return slugify(server);\n } catch (error) {\n if (error instanceof SlugifyError) {\n throw new McpAddError(\"INVALID_SERVER_NAME\", error.message);\n }\n\n throw error;\n }\n}\n\nasync function loadConfigOrDefault(rootDir: string) {\n try {\n return await loadConfig(rootDir);\n } catch (error) {\n if (error instanceof ConfigLoadError || error instanceof ConfigValidationError) {\n return createDefaultConfig();\n }\n\n throw error;\n }\n}\n","import path from \"node:path\";\n\nimport type { WriteFileInput } from \"../filesystem/write-plan.js\";\nimport { slugify } from \"../naming/slugify.js\";\nimport { createTemplateContext } from \"./template-context.js\";\nimport { renderTemplate } from \"./render-template.js\";\n\nexport type GenerateModuleFilesOptions = {\n modulesDir: string;\n moduleName: string;\n};\n\ntype ModuleTemplate = {\n fileName: string;\n content: string;\n};\n\nconst moduleTemplates: ModuleTemplate[] = [\n {\n fileName: \"MODULE.md\",\n content: `# Module: {{title}}\n\n## Purpose\n\nDescribe what this module owns and why it exists.\n\n## Owns\n\n- TBD\n\n## Does Not Own\n\n- TBD\n\n## Public Interfaces\n\n- TBD\n\n## Boundaries\n\nDescribe important dependencies, callers, and constraints.\n`,\n },\n {\n fileName: \"TASKS.md\",\n content: `# Module Tasks: {{title}}\n\n## Active Work\n\n- TBD\n\n## Tasks\n\n- Todo: Define module responsibilities.\n- Todo: Define tests.\n- Todo: Update decisions as behavior changes.\n`,\n },\n {\n fileName: \"TEST_PLAN.md\",\n content: `# Module Test Plan: {{title}}\n\n## Unit Tests\n\n- TBD\n\n## Integration Tests\n\n- TBD\n\n## Security Tests\n\n- TBD\n`,\n },\n {\n fileName: \"DECISIONS.md\",\n content: `# Module Decisions: {{title}}\n\nRecord durable module decisions here.\n\n## Current Decisions\n\n- TBD\n`,\n },\n];\n\nexport function generateModuleFiles(options: GenerateModuleFilesOptions): WriteFileInput[] {\n const slug = slugify(options.moduleName);\n const moduleDir = path.posix.join(options.modulesDir, slug);\n const title = titleizeModuleName(options.moduleName);\n const context = createTemplateContext({\n slug,\n title,\n });\n\n return moduleTemplates.map((template) => ({\n path: path.posix.join(moduleDir, template.fileName),\n content: renderTemplate(template.content, context),\n }));\n}\n\nfunction titleizeModuleName(moduleName: string): string {\n return moduleName\n .trim()\n .replace(/[-_]+/gu, \" \")\n .replace(/\\s+/gu, \" \")\n .replace(/\\b\\w/gu, (character) => character.toUpperCase());\n}\n","import { ConfigValidationError } from \"../../core/config/config-schema.js\";\nimport { loadConfig, ConfigLoadError } from \"../../core/config/load-config.js\";\nimport { createWritePlan, type WritePlan } from \"../../core/filesystem/write-plan.js\";\nimport { executeWritePlan, type WriteResult } from \"../../core/filesystem/write-file-safe.js\";\nimport { generateModuleFiles } from \"../../core/generator/generate-module.js\";\nimport { SlugifyError, slugify } from \"../../core/naming/slugify.js\";\nimport { appendNextSteps, appendWriteSummary } from \"../write-summary.js\";\n\nexport type ModuleCreateOptions = {\n rootDir: string;\n name: string;\n dryRun?: boolean;\n force?: boolean;\n};\n\nexport type ModuleCreateResult = {\n slug: string;\n modulePath: string;\n dryRun: boolean;\n plan: WritePlan;\n writeResult: WriteResult;\n};\n\nexport type ModuleCreateErrorCode = \"CONFIG_REQUIRED\" | \"INVALID_MODULE_NAME\" | \"WRITE_PLAN_ERROR\";\n\nexport class ModuleCreateError extends Error {\n readonly code: ModuleCreateErrorCode;\n readonly details: string[];\n\n constructor(code: ModuleCreateErrorCode, message: string, details: string[] = []) {\n super(message);\n this.name = \"ModuleCreateError\";\n this.code = code;\n this.details = details;\n }\n}\n\nexport async function createModule(options: ModuleCreateOptions): Promise<ModuleCreateResult> {\n const slug = createModuleSlug(options.name);\n const config = await loadRequiredConfig(options.rootDir);\n const files = generateModuleFiles({\n modulesDir: config.modulesDir,\n moduleName: options.name,\n });\n const plan = createWritePlan({\n rootDir: options.rootDir,\n files,\n force: options.force,\n });\n\n if (plan.hasErrors) {\n throw new ModuleCreateError(\n \"WRITE_PLAN_ERROR\",\n \"Module create write plan contains errors.\",\n plan.entries\n .filter((entry) => entry.action === \"error\")\n .map((entry) => `${entry.path}: ${entry.reason}`),\n );\n }\n\n const writeResult = await executeWritePlan(plan, { dryRun: options.dryRun });\n\n return {\n slug,\n modulePath: `${config.modulesDir}/${slug}`,\n dryRun: options.dryRun ?? false,\n plan,\n writeResult,\n };\n}\n\nexport function formatModuleCreateResult(result: ModuleCreateResult): string {\n const lines = [\n result.dryRun\n ? \"Recall OS module create dry run complete.\"\n : \"Recall OS module create complete.\",\n `Module: ${result.modulePath}`,\n ];\n\n appendWriteSummary(lines, {\n dryRun: result.dryRun,\n writeResult: result.writeResult,\n });\n\n if (!result.dryRun) {\n appendNextSteps(lines, [\n `Open ${result.modulePath}/MODULE.md and describe what this module owns and does not own.`,\n \"Record durable decisions in DECISIONS.md, or link an ADR.\",\n ]);\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction createModuleSlug(name: string): string {\n try {\n return slugify(name);\n } catch (error) {\n if (error instanceof SlugifyError) {\n throw new ModuleCreateError(\"INVALID_MODULE_NAME\", error.message);\n }\n\n throw error;\n }\n}\n\nasync function loadRequiredConfig(rootDir: string) {\n try {\n return await loadConfig(rootDir);\n } catch (error) {\n if (error instanceof ConfigLoadError || error instanceof ConfigValidationError) {\n throw new ModuleCreateError(\n \"CONFIG_REQUIRED\",\n \"Recall OS config not found or invalid. Run `recall init` first.\",\n [error.message],\n );\n }\n\n throw error;\n }\n}\n","import { listPresets } from \"../../core/presets/preset-registry.js\";\n\nexport type PresetListEntry = {\n id: string;\n name: string;\n description: string;\n};\n\nexport type PresetListResult = {\n presets: PresetListEntry[];\n};\n\nexport function listPresetEntries(): PresetListResult {\n return {\n presets: listPresets()\n .map((preset) => ({\n id: preset.id,\n name: preset.name,\n description: preset.description,\n }))\n .sort((left, right) => left.id.localeCompare(right.id)),\n };\n}\n\nexport function formatPresetListResult(result: PresetListResult): string {\n const lines = [\"Recall OS presets\", \"\"];\n\n for (const preset of result.presets) {\n lines.push(`- ${preset.id}: ${preset.name}`);\n lines.push(` ${preset.description}`);\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n","import { createWritePlan, type WritePlan } from \"../../core/filesystem/write-plan.js\";\nimport { executeWritePlan, type WriteResult } from \"../../core/filesystem/write-file-safe.js\";\nimport { generateSkillFiles } from \"../../core/skills/generate-skill.js\";\nimport { SlugifyError, slugify } from \"../../core/naming/slugify.js\";\nimport { appendNextSteps, appendWriteSummary } from \"../write-summary.js\";\n\nexport type SkillCreateOptions = {\n rootDir: string;\n name: string;\n dryRun?: boolean;\n force?: boolean;\n};\n\nexport type SkillCreateResult = {\n slug: string;\n fromCatalog: boolean;\n dryRun: boolean;\n plan: WritePlan;\n writeResult: WriteResult;\n};\n\nexport type SkillCreateErrorCode = \"INVALID_SKILL_NAME\" | \"WRITE_PLAN_ERROR\";\n\nexport class SkillCreateError extends Error {\n readonly code: SkillCreateErrorCode;\n readonly details: string[];\n\n constructor(code: SkillCreateErrorCode, message: string, details: string[] = []) {\n super(message);\n this.name = \"SkillCreateError\";\n this.code = code;\n this.details = details;\n }\n}\n\nexport async function createSkill(options: SkillCreateOptions): Promise<SkillCreateResult> {\n const slug = createSkillSlug(options.name);\n const { files, fromCatalog } = generateSkillFiles(slug);\n const plan = createWritePlan({\n rootDir: options.rootDir,\n files,\n force: options.force,\n });\n\n if (plan.hasErrors) {\n throw new SkillCreateError(\n \"WRITE_PLAN_ERROR\",\n \"Recall OS skill create write plan contains errors.\",\n plan.entries\n .filter((entry) => entry.action === \"error\")\n .map((entry) => `${entry.path}: ${entry.reason}`),\n );\n }\n\n const writeResult = await executeWritePlan(plan, { dryRun: options.dryRun });\n\n return {\n slug,\n fromCatalog,\n dryRun: options.dryRun ?? false,\n plan,\n writeResult,\n };\n}\n\nexport function formatSkillCreateResult(result: SkillCreateResult): string {\n const lines = [\n result.dryRun ? \"Recall OS skill create dry run complete.\" : \"Recall OS skill create complete.\",\n `Skill: ${result.slug}${result.fromCatalog ? \" (from catalog)\" : \" (skeleton — fill it in)\"}`,\n ];\n\n appendWriteSummary(lines, {\n dryRun: result.dryRun,\n writeResult: result.writeResult,\n });\n\n if (!result.dryRun) {\n appendNextSteps(\n lines,\n result.fromCatalog\n ? [\n `The skill is ready in .claude/skills/${result.slug}/ and .agents/skills/${result.slug}/.`,\n \"Restart your AI tool to load it; the agent triggers it from the description.\",\n ]\n : [\n `Open .claude/skills/${result.slug}/SKILL.md and fill the description, process, and quality bar.`,\n \"Keep the same content in .agents/skills/ for portability.\",\n ],\n );\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction createSkillSlug(name: string): string {\n try {\n return slugify(name);\n } catch (error) {\n if (error instanceof SlugifyError) {\n throw new SkillCreateError(\"INVALID_SKILL_NAME\", error.message);\n }\n\n throw error;\n }\n}\n","import { SKILL_CATALOG } from \"../../core/skills/skill-catalog.js\";\n\nexport function formatSkillListResult(): string {\n const lines = [\"Recall OS skill catalog\", \"\"];\n\n for (const skill of SKILL_CATALOG) {\n lines.push(`- ${skill.name}: ${skill.title}`);\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n"],"mappings":"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","names":["existsSync","readFile","readdir","path","path","path","CONTROL_CHARS","existsSync","numbered","readFile","readdir","path","path","TEMPLATE_KEY_PATTERN","RESERVED_TEMPLATE_KEYS","path","loadRequiredConfig","readFile","readdir","path","createSlug","loadRequiredConfig","write","escapeRegExp","readdir","readFile","path","path","path","readdir","readdir","loadRequiredConfig","existsSync","readFile","readdir","path","formatList","existsSync","readFile","readdir","path","readFile","readFile","readFile","readdir","path","featureFolderPattern","readDirIfExists","readFileIfExists","readFile","readdir","path","readDirIfExists","getSection","lstat","readFile","readdir","path","featureFolderPattern","adrFilePattern","readDirIfExists","path","readFile","readdir","lstat","lstat","path","isFile","lstat","readFile","readdir","path","featureFolderPattern","adrFilePattern","readDirIfExists","readFileIfExists","sectionContains","getSection","isFile","readFile","readdir","path","adrFilePattern","adrReferencePattern","checkReferences","readMarkdownFiles","stripCode","readDirIfExists","existsSync","path","path","path","existsSync","readFile","path","detectPackageManager","guidance","proposedAdr","guidance","proposedAdr","guidance","proposedAdr","z","PRESET_ID_PATTERN","z","presetSchema","path","existsSync","path","titleize","renderProposedAdr","bullets","loadConfigOrDefault","path","path","loadRequiredConfig"]}