@prover-coder-ai/context-doc 1.0.18 → 1.0.19

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sources":["../src/shell/services/crypto.ts","../src/shell/sync/types.ts","../src/shell/services/file-system.ts","../src/shell/services/runtime-env.ts","../src/shell/cli.ts","../src/shell/sync/shared.ts","../src/shell/sync/sources/claude.ts","../src/core/knowledge.ts","../src/shell/sync/sources/codex.ts","../src/shell/sync/sources/qwen.ts","../src/shell/sync/index.ts","../src/app/program.ts","../src/app/main.ts"],"sourcesContent":["import { Context, Effect, Layer, pipe } from \"effect\"\n\nexport class CryptoService extends Context.Tag(\"CryptoService\")<\n CryptoService,\n {\n readonly sha256: (value: string) => Effect.Effect<string, CryptoError>\n }\n>() {}\n\nexport interface CryptoError {\n readonly _tag: \"CryptoError\"\n readonly reason: string\n}\n\nconst cryptoError = (reason: string): CryptoError => ({\n _tag: \"CryptoError\",\n reason\n})\n\nconst toHex = (buffer: ArrayBuffer): string =>\n [...new Uint8Array(buffer)]\n .map((byte) => byte.toString(16).padStart(2, \"0\"))\n .join(\"\")\n\nconst digestSha256 = (value: string): Effect.Effect<string, CryptoError> =>\n pipe(\n Effect.tryPromise({\n try: () => {\n const crypto = globalThis.crypto\n const bytes = new TextEncoder().encode(value)\n return crypto.subtle.digest(\"SHA-256\", bytes)\n },\n catch: (error) => cryptoError(error instanceof Error ? error.message : \"Crypto digest failed\")\n }),\n Effect.map((buffer) => toHex(buffer))\n )\n\n// CHANGE: isolate hashing behind a service for deterministic testing\n// WHY: avoid direct crypto usage in shell logic\n// QUOTE(TZ): \"Внешние зависимости: только через типизированные интерфейсы\"\n// REF: user-2026-01-19-sync-rewrite\n// SOURCE: n/a\n// FORMAT THEOREM: forall s: sha256(s) -> hex(s)\n// PURITY: SHELL\n// EFFECT: Effect<CryptoService, never, never>\n// INVARIANT: sha256 output length = 64\n// COMPLEXITY: O(n)/O(1)\nexport const CryptoServiceLive = Layer.succeed(CryptoService, {\n sha256: (value) => digestSha256(value)\n})\n","import type * as Fx from \"effect\"\n\nexport interface SyncError {\n readonly _tag: \"SyncError\"\n readonly path: string\n readonly reason: string\n}\n\nexport interface SyncOptions {\n readonly cwd: string\n readonly projectRoot?: string\n readonly sourceDir?: string\n readonly destinationDir?: string\n readonly repositoryUrlOverride?: string\n readonly metaRoot?: string\n readonly qwenSourceDir?: string\n readonly claudeProjectsRoot?: string\n}\n\nexport type SyncEffect<A, R = never> = Fx.Effect.Effect<A, SyncError, R>\n\nexport interface SyncSource<R> {\n readonly name: string\n readonly destSubdir: \".codex\" | \".qwen\" | \".claude\"\n readonly resolveSource: (options: SyncOptions) => SyncEffect<string, R>\n readonly copy: (\n sourceDir: string,\n destinationDir: string,\n options: SyncOptions\n ) => SyncEffect<number, R>\n}\n\n// CHANGE: centralize sync-specific types to keep shell modules consistent\n// WHY: shared types and error model simplify composition and testing\n// QUOTE(TZ): \"Ошибки: типизированы в сигнатурах функций\"\n// REF: user-2026-01-19-sync-rewrite\n// SOURCE: n/a\n// FORMAT THEOREM: forall e: SyncError -> typed(e)\n// PURITY: SHELL\n// EFFECT: n/a\n// INVARIANT: SyncError contains path and reason for logging\n// COMPLEXITY: O(1)/O(1)\nexport const syncError = (pathValue: string, reason: string): SyncError => ({\n _tag: \"SyncError\",\n path: pathValue,\n reason\n})\n","import type { PlatformError as PlatformErrorType } from \"@effect/platform/Error\"\nimport * as FileSystem from \"@effect/platform/FileSystem\"\nimport * as Path from \"@effect/platform/Path\"\nimport { Context, Effect, Layer, pipe } from \"effect\"\n\nimport { type SyncError, syncError } from \"../sync/types.js\"\n\nexport type DirectoryEntryKind = \"file\" | \"directory\" | \"other\"\n\nexport interface DirectoryEntry {\n readonly name: string\n readonly path: string\n readonly kind: DirectoryEntryKind\n}\n\nexport class FileSystemService extends Context.Tag(\"FileSystemService\")<\n FileSystemService,\n {\n readonly readFileString: (pathValue: string) => Effect.Effect<string, SyncError>\n readonly readDirectory: (\n pathValue: string\n ) => Effect.Effect<ReadonlyArray<DirectoryEntry>, SyncError>\n readonly makeDirectory: (pathValue: string) => Effect.Effect<void, SyncError>\n readonly copyFile: (\n sourcePath: string,\n destinationPath: string\n ) => Effect.Effect<void, SyncError>\n readonly exists: (pathValue: string) => Effect.Effect<boolean, SyncError>\n }\n>() {}\n\nconst forEach = Effect.forEach\n\nconst resolveEntryPath = (\n path: Path.Path,\n root: string,\n entry: string\n): string => (path.isAbsolute(entry) ? entry : path.join(root, entry))\n\nconst entryKindFromInfo = (\n info: FileSystem.File.Info\n): DirectoryEntryKind => {\n if (info.type === \"Directory\") {\n return \"directory\"\n }\n if (info.type === \"File\") {\n return \"file\"\n }\n return \"other\"\n}\n\nconst toDirectoryEntry = (\n path: Path.Path,\n entryPath: string,\n info: FileSystem.File.Info\n): DirectoryEntry => ({\n name: path.basename(entryPath),\n path: entryPath,\n kind: entryKindFromInfo(info)\n})\n\nconst missingEntry = (\n path: Path.Path,\n entryPath: string\n): DirectoryEntry => ({\n name: path.basename(entryPath),\n path: entryPath,\n kind: \"other\"\n})\n\nconst isNotFoundError = (error: PlatformErrorType): boolean =>\n error._tag === \"SystemError\" && error.reason === \"NotFound\"\n\n// CHANGE: tolerate missing directory entries while traversing sources\n// WHY: broken symlinks should not abort sync traversal\n// QUOTE(TZ): n/a\n// REF: user-2026-01-21-broken-symlink\n// SOURCE: n/a\n// FORMAT THEOREM: forall e: notFound(e) -> ignored(e)\n// PURITY: SHELL\n// EFFECT: Effect<DirectoryEntry, SyncError, FileSystem>\n// INVARIANT: NotFound entries are classified as kind=\"other\"\n// COMPLEXITY: O(1)/O(1)\nconst readEntry = (\n fs: FileSystem.FileSystem,\n path: Path.Path,\n entryPath: string\n): Effect.Effect<DirectoryEntry, SyncError> =>\n pipe(\n fs.stat(entryPath),\n Effect.map((info) => toDirectoryEntry(path, entryPath, info)),\n Effect.catchIf(isNotFoundError, () => Effect.succeed(missingEntry(path, entryPath))),\n Effect.mapError(() => syncError(entryPath, \"Cannot read directory entry\"))\n )\n\nconst resolveEntry = (\n fs: FileSystem.FileSystem,\n path: Path.Path,\n root: string,\n entry: string\n): Effect.Effect<DirectoryEntry, SyncError> => {\n const entryPath = resolveEntryPath(path, root, entry)\n return readEntry(fs, path, entryPath)\n}\n\n// CHANGE: wrap filesystem access behind a service for typed errors and testing\n// WHY: enforce shell boundary and avoid raw fs usage in logic\n// QUOTE(TZ): \"Внешние зависимости: только через типизированные интерфейсы\"\n// REF: user-2026-01-19-sync-rewrite\n// SOURCE: n/a\n// FORMAT THEOREM: forall p: exists(p) -> readable(p)\n// PURITY: SHELL\n// EFFECT: Effect<FileSystemService, SyncError, never>\n// INVARIANT: readDirectory returns absolute entry paths\n// COMPLEXITY: O(n)/O(n)\nexport const FileSystemLive = Layer.effect(\n FileSystemService,\n Effect.gen(function*(_) {\n const fs = yield* _(FileSystem.FileSystem)\n const path = yield* _(Path.Path)\n\n const readFileString = (pathValue: string): Effect.Effect<string, SyncError> =>\n pipe(\n fs.readFileString(pathValue, \"utf8\"),\n Effect.mapError(() => syncError(pathValue, \"Cannot read file\"))\n )\n\n const readDirectory = (\n pathValue: string\n ): Effect.Effect<ReadonlyArray<DirectoryEntry>, SyncError> =>\n pipe(\n fs.readDirectory(pathValue),\n Effect.mapError(() => syncError(pathValue, \"Cannot read directory\")),\n Effect.flatMap((entries) => forEach(entries, (entry) => resolveEntry(fs, path, pathValue, entry)))\n )\n\n const makeDirectory = (pathValue: string): Effect.Effect<void, SyncError> =>\n pipe(\n fs.makeDirectory(pathValue, { recursive: true }),\n Effect.mapError(() => syncError(pathValue, \"Cannot create destination directory structure\"))\n )\n\n const copyFile = (\n sourcePath: string,\n destinationPath: string\n ): Effect.Effect<void, SyncError> =>\n pipe(\n fs.copyFile(sourcePath, destinationPath),\n Effect.mapError(() => syncError(sourcePath, \"Cannot copy file into destination\"))\n )\n\n const exists = (pathValue: string): Effect.Effect<boolean, SyncError> =>\n pipe(\n fs.exists(pathValue),\n Effect.mapError(() => syncError(pathValue, \"Cannot check path existence\"))\n )\n\n return {\n readFileString,\n readDirectory,\n makeDirectory,\n copyFile,\n exists\n }\n })\n)\n","import { Context, Effect, Layer, Option } from \"effect\"\n\nexport class RuntimeEnv extends Context.Tag(\"RuntimeEnv\")<\n RuntimeEnv,\n {\n readonly argv: Effect.Effect<ReadonlyArray<string>>\n readonly cwd: Effect.Effect<string>\n readonly homedir: Effect.Effect<string>\n readonly envVar: (key: string) => Effect.Effect<Option.Option<string>>\n }\n>() {}\n\nconst readProcess = (): NodeJS.Process | undefined => typeof process === \"undefined\" ? undefined : process\n\nconst readEnv = (): NodeJS.ProcessEnv => readProcess()?.env ?? {}\n\nconst resolveHomeDir = (env: NodeJS.ProcessEnv, cwdFallback: string): string => {\n const direct = env[\"HOME\"] ?? env[\"USERPROFILE\"]\n if (direct !== undefined) {\n return direct\n }\n\n const drive = env[\"HOMEDRIVE\"]\n const path = env[\"HOMEPATH\"]\n if (drive !== undefined && path !== undefined) {\n return `${drive}${path}`\n }\n\n return cwdFallback\n}\n\n// CHANGE: wrap process/os access behind a typed Effect service\n// WHY: keep shell dependencies injectable and testable\n// QUOTE(TZ): \"Внешние зависимости: только через типизированные интерфейсы\"\n// REF: user-2026-01-19-sync-rewrite\n// SOURCE: n/a\n// FORMAT THEOREM: forall k: env(k) -> Option<string>\n// PURITY: SHELL\n// EFFECT: Effect<RuntimeEnv, never, never>\n// INVARIANT: argv/cwd/homedir are read once per effect\n// COMPLEXITY: O(1)/O(1)\nexport const RuntimeEnvLive = Layer.succeed(RuntimeEnv, {\n argv: Effect.sync(() => {\n const proc = readProcess()\n return proc === undefined ? [] : [...proc.argv]\n }),\n cwd: Effect.sync(() => readProcess()?.cwd() ?? \".\"),\n homedir: Effect.sync(() => {\n const proc = readProcess()\n const cwdFallback = proc?.cwd() ?? \".\"\n return resolveHomeDir(readEnv(), cwdFallback)\n }),\n envVar: (key) => Effect.sync(() => Option.fromNullable(readEnv()[key]))\n})\n","import { Effect } from \"effect\"\n\nimport { RuntimeEnv } from \"./services/runtime-env.js\"\nimport type { SyncOptions } from \"./sync/types.js\"\n\ntype CliKey = Exclude<keyof SyncOptions, \"cwd\">\n\nconst flagMap = new Map<string, CliKey>([\n [\"--project-root\", \"projectRoot\"],\n [\"-r\", \"projectRoot\"],\n [\"--source\", \"sourceDir\"],\n [\"-s\", \"sourceDir\"],\n [\"--dest\", \"destinationDir\"],\n [\"-d\", \"destinationDir\"],\n [\"--project-url\", \"repositoryUrlOverride\"],\n [\"--project-name\", \"repositoryUrlOverride\"],\n [\"--meta-root\", \"metaRoot\"],\n [\"--qwen-source\", \"qwenSourceDir\"],\n [\"--claude-projects\", \"claudeProjectsRoot\"]\n])\n\nconst parseArgs = (args: ReadonlyArray<string>, cwd: string): SyncOptions => {\n let result: SyncOptions = { cwd }\n\n let index = 0\n while (index < args.length) {\n const arg = args[index]\n if (arg === undefined) {\n index += 1\n continue\n }\n const key = flagMap.get(arg)\n if (key === undefined) {\n index += 1\n continue\n }\n\n const value = args[index + 1]\n if (value !== undefined) {\n result = { ...result, [key]: value }\n index += 2\n continue\n }\n index += 1\n }\n\n return result\n}\n\n/**\n * Reads CLI arguments and builds SyncOptions.\n *\n * @returns Effect with resolved SyncOptions.\n *\n * @pure false - reads process argv/cwd via RuntimeEnv\n * @effect RuntimeEnv\n * @invariant options.cwd is always defined; projectRoot overrides cwd for matching\n * @complexity O(n) where n = |args|\n */\n// CHANGE: parse CLI flags with optional project root override\n// WHY: allow matching against repo root while running from subpackages\n// QUOTE(TZ): \"передай root-path на основную папку\"\n// REF: user-2026-01-19-project-root\n// SOURCE: n/a\n// FORMAT THEOREM: forall a: parse(a) -> SyncOptions\n// PURITY: SHELL\n// EFFECT: Effect<SyncOptions, never, RuntimeEnv>\n// INVARIANT: unknown flags are ignored\n// COMPLEXITY: O(n)/O(1)\nexport const readSyncOptions = Effect.gen(function*(_) {\n const env = yield* _(RuntimeEnv)\n const argv = yield* _(env.argv)\n const cwd = yield* _(env.cwd)\n return parseArgs(argv.slice(2), cwd)\n})\n","import * as Path from \"@effect/platform/Path\"\nimport { Console, Effect, Match, pipe } from \"effect\"\n\nimport { type DirectoryEntry, FileSystemService } from \"../services/file-system.js\"\nimport { type SyncError, syncError, type SyncOptions, type SyncSource } from \"./types.js\"\n\nconst forEach = Effect.forEach\n\ntype FilteredSourceEnv<R> = R | FileSystemService | Path.Path\n\nconst ensureDirectory = (\n directory: string\n): Effect.Effect<void, SyncError, FileSystemService> =>\n Effect.gen(function*(_) {\n const fs = yield* _(FileSystemService)\n yield* _(fs.makeDirectory(directory))\n })\n\n// CHANGE: expose recursive traversal for callers that filter by entry\n// WHY: reuse traversal logic across sources without duplicating Match logic\n// QUOTE(TZ): \"минимальный корректный diff\"\n// REF: user-2026-01-19-sync-rewrite\n// SOURCE: n/a\n// FORMAT THEOREM: forall f: collectFiles(root, p) -> p(f) => exists(f)\n// PURITY: SHELL\n// EFFECT: Effect<ReadonlyArray<string>, SyncError, FileSystemService>\n// INVARIANT: returned paths are absolute and exist in traversal\n// COMPLEXITY: O(n)/O(n)\nexport const collectFiles = (\n root: string,\n isRelevant: (entry: DirectoryEntry) => boolean\n): Effect.Effect<ReadonlyArray<string>, SyncError, FileSystemService> =>\n Effect.gen(function*(_) {\n const fs = yield* _(FileSystemService)\n const entries = yield* _(fs.readDirectory(root))\n const chunks = yield* _(\n forEach(entries, (entry) =>\n Match.value(entry.kind).pipe(\n Match.when(\"directory\", () => collectFiles(entry.path, isRelevant)),\n Match.when(\"file\", () => isRelevant(entry) ? Effect.succeed([entry.path]) : Effect.succeed([])),\n Match.when(\"other\", () => Effect.succeed([])),\n Match.exhaustive\n ))\n )\n return chunks.flat()\n })\n\n// CHANGE: share relative path copy for multiple sync sources\n// WHY: avoid repeating path math in each source\n// QUOTE(TZ): \"SHELL → CORE (but not наоборот)\"\n// REF: user-2026-01-19-sync-rewrite\n// SOURCE: n/a\n// FORMAT THEOREM: forall f: copy(f) -> relative(f) preserved\n// PURITY: SHELL\n// EFFECT: Effect<void, SyncError, FileSystemService | Path>\n// INVARIANT: destination preserves source-relative path\n// COMPLEXITY: O(1)/O(1)\nexport const copyFilePreservingRelativePath = (\n sourceRoot: string,\n destinationRoot: string,\n filePath: string\n): Effect.Effect<void, SyncError, FileSystemService | Path.Path> =>\n Effect.gen(function*(_) {\n const fs = yield* _(FileSystemService)\n const path = yield* _(Path.Path)\n const relative = path.relative(sourceRoot, filePath)\n const targetPath = path.join(destinationRoot, relative)\n yield* _(fs.makeDirectory(path.dirname(targetPath)))\n yield* _(fs.copyFile(filePath, targetPath))\n })\n\n// CHANGE: expose reusable first-match search with effectful predicate\n// WHY: remove duplicated recursive search logic across sources\n// QUOTE(TZ): \"минимальный корректный diff\"\n// REF: user-2026-01-19-sync-rewrite\n// SOURCE: n/a\n// FORMAT THEOREM: forall c: match(c) -> returns first c\n// PURITY: SHELL\n// EFFECT: Effect<string | undefined, SyncError, R>\n// INVARIANT: result is undefined iff no candidate matches\n// COMPLEXITY: O(n)/O(1)\nexport const findFirstMatching = <R>(\n candidates: ReadonlyArray<string>,\n matches: (candidate: string) => Effect.Effect<boolean, SyncError, R>\n): Effect.Effect<string | undefined, SyncError, R> => {\n const loop = (\n remaining: ReadonlyArray<string>\n ): Effect.Effect<string | undefined, SyncError, R> =>\n Effect.gen(function*(_) {\n const [candidate, ...rest] = remaining\n if (candidate === undefined) {\n return\n }\n const matched = yield* _(matches(candidate))\n if (!matched) {\n return yield* _(loop(rest))\n }\n return candidate\n })\n\n return loop(candidates)\n}\n\n// CHANGE: ensure destination directory is created through Effect-typed fs\n// WHY: keep IO effects inside SHELL and reuse in sync flows\n// QUOTE(TZ): \"SHELL: Все эффекты изолированы в тонкой оболочке\"\n// REF: user-2026-01-19-sync-rewrite\n// SOURCE: n/a\n// FORMAT THEOREM: forall d: ensureDirectory(d) -> exists(d)\n// PURITY: SHELL\n// EFFECT: Effect<void, SyncError, FileSystemService>\n// INVARIANT: directory exists after successful effect\n// COMPLEXITY: O(1)/O(1)\nexport const ensureDestination = ensureDirectory\n\n// CHANGE: resolve project root for cwd-based matching and destination paths\n// WHY: allow running from sub-packages while targeting the repo root\n// QUOTE(TZ): \"передай root-path на основную папку\"\n// REF: user-2026-01-19-project-root\n// SOURCE: n/a\n// FORMAT THEOREM: forall o: root(o) = resolve(o.projectRoot ?? o.cwd)\n// PURITY: SHELL\n// EFFECT: n/a\n// INVARIANT: resolved root is absolute\n// COMPLEXITY: O(1)/O(1)\nexport const resolveProjectRoot = (\n path: Path.Path,\n options: SyncOptions\n): string => path.resolve(options.projectRoot ?? options.cwd)\n\n// CHANGE: copy filtered files with typed errors and deterministic traversal\n// WHY: reuse shared traversal logic for Qwen/Claude syncs\n// QUOTE(TZ): \"FUNCTIONAL CORE, IMPERATIVE SHELL\"\n// REF: user-2026-01-19-sync-rewrite\n// SOURCE: n/a\n// FORMAT THEOREM: forall f: relevant(f) -> copied(f)\n// PURITY: SHELL\n// EFFECT: Effect<number, SyncError, FileSystemService | Path>\n// INVARIANT: copied count equals length of relevant files\n// COMPLEXITY: O(n)/O(n)\nexport const copyFilteredFiles = (\n sourceRoot: string,\n destinationRoot: string,\n isRelevant: (entry: DirectoryEntry, fullPath: string) => boolean,\n errorReason: string\n): Effect.Effect<number, SyncError, FileSystemService | Path.Path> =>\n pipe(\n Effect.gen(function*(_) {\n const files = yield* _(collectFiles(sourceRoot, (entry) => isRelevant(entry, entry.path)))\n yield* _(\n forEach(files, (filePath) => copyFilePreservingRelativePath(sourceRoot, destinationRoot, filePath))\n )\n return files.length\n }),\n Effect.mapError(() => syncError(sourceRoot, errorReason))\n )\n\n// CHANGE: build a SyncSource using shared filtered copy logic\n// WHY: eliminate repeated source definitions for file-extension based syncs\n// QUOTE(TZ): \"минимальный корректный diff\"\n// REF: user-2026-01-19-sync-rewrite\n// SOURCE: n/a\n// FORMAT THEOREM: forall s: createFilteredSource(s) -> copyFilteredFiles(s)\n// PURITY: SHELL\n// EFFECT: Effect<number, SyncError, R>\n// INVARIANT: copy uses shared filter predicate\n// COMPLEXITY: O(n)/O(n)\nexport const createFilteredSource = <R>(params: {\n readonly name: SyncSource<FilteredSourceEnv<R>>[\"name\"]\n readonly destSubdir: SyncSource<FilteredSourceEnv<R>>[\"destSubdir\"]\n readonly resolveSource: SyncSource<FilteredSourceEnv<R>>[\"resolveSource\"]\n readonly filter: (entry: DirectoryEntry, fullPath: string) => boolean\n readonly errorReason: string\n}): SyncSource<FilteredSourceEnv<R>> => ({\n name: params.name,\n destSubdir: params.destSubdir,\n resolveSource: params.resolveSource,\n copy: (sourceDir, destinationDir) => copyFilteredFiles(sourceDir, destinationDir, params.filter, params.errorReason)\n})\n\n// CHANGE: standardize per-source sync orchestration with skip-on-error logging\n// WHY: keep the shell thin and consistent for all sources\n// QUOTE(TZ): \"SHELL → CORE (but not наоборот)\"\n// REF: user-2026-01-19-sync-rewrite\n// SOURCE: n/a\n// FORMAT THEOREM: forall s: runSyncSource(s) -> logs(s)\n// PURITY: SHELL\n// EFFECT: Effect<void, never, FileSystemService | Path>\n// INVARIANT: source==destination implies no copy\n// COMPLEXITY: O(n)/O(n)\nexport const runSyncSource = <R>(\n source: SyncSource<R>,\n options: SyncOptions\n): Effect.Effect<void, never, R | FileSystemService | Path.Path> =>\n pipe(\n Effect.gen(function*(_) {\n const path = yield* _(Path.Path)\n const resolvedSource = yield* _(source.resolveSource(options))\n const destination = path.join(\n resolveProjectRoot(path, options),\n \".knowledge\",\n source.destSubdir\n )\n\n if (path.resolve(resolvedSource) === path.resolve(destination)) {\n yield* _(\n Console.log(\n `${source.name}: source equals destination; skipping copy to avoid duplicates`\n )\n )\n return\n }\n\n yield* _(ensureDirectory(destination))\n const copied = yield* _(source.copy(resolvedSource, destination, options))\n yield* _(\n Console.log(\n `${source.name}: copied ${copied} files from ${resolvedSource} to ${destination}`\n )\n )\n }),\n Effect.matchEffect({\n onFailure: (error: SyncError) =>\n Console.log(\n `${source.name}: source not found; skipped syncing (${error.reason})`\n ),\n onSuccess: () => Effect.void\n })\n )\n","import * as Path from \"@effect/platform/Path\"\nimport { Effect } from \"effect\"\n\nimport { FileSystemService } from \"../../services/file-system.js\"\nimport { RuntimeEnv } from \"../../services/runtime-env.js\"\nimport { createFilteredSource, resolveProjectRoot, runSyncSource } from \"../shared.js\"\nimport { type SyncError, syncError, type SyncOptions, type SyncSource } from \"../types.js\"\n\ntype ClaudeEnv = RuntimeEnv | FileSystemService | Path.Path\n\nconst slugFromCwd = (cwd: string): string => `-${cwd.replace(/^\\/+/, \"\").replaceAll(\"\\\\\", \"-\").replaceAll(\"/\", \"-\")}`\n\nconst resolveClaudeProjectDir = (\n options: SyncOptions\n): Effect.Effect<string, SyncError, ClaudeEnv> =>\n Effect.gen(function*(_) {\n const env = yield* _(RuntimeEnv)\n const homeDir = yield* _(env.homedir)\n const path = yield* _(Path.Path)\n const base = options.claudeProjectsRoot ??\n path.join(homeDir, \".claude\", \"projects\")\n const candidate = path.join(base, slugFromCwd(resolveProjectRoot(path, options)))\n const fs = yield* _(FileSystemService)\n const exists = yield* _(fs.exists(candidate))\n if (!exists) {\n return yield* _(\n Effect.fail(syncError(\".claude\", \"Claude project directory is missing\"))\n )\n }\n\n return candidate\n })\n\nconst claudeSource: SyncSource<ClaudeEnv> = createFilteredSource({\n name: \"Claude\",\n destSubdir: \".claude\",\n resolveSource: resolveClaudeProjectDir,\n filter: (entry, fullPath) => entry.kind === \"file\" && fullPath.endsWith(\".jsonl\"),\n errorReason: \"Cannot traverse Claude project\"\n})\n\n// CHANGE: sync Claude dialog files through shared sync runner\n// WHY: keep Claude-specific path resolution isolated from other sources\n// QUOTE(TZ): \"SHELL: Все эффекты (IO, сеть, БД, env/process) изолированы\"\n// REF: user-2026-01-19-sync-rewrite\n// SOURCE: n/a\n// FORMAT THEOREM: forall f: jsonl(f) -> copied(f)\n// PURITY: SHELL\n// EFFECT: Effect<void, never, FileSystemService | RuntimeEnv | Path>\n// INVARIANT: only .jsonl files are copied\n// COMPLEXITY: O(n)/O(n)\nexport const syncClaude = (\n options: SyncOptions\n): Effect.Effect<void, never, ClaudeEnv> => runSyncSource(claudeSource, options)\n","import { Option, pipe } from \"effect\"\n\nexport type JsonPrimitive = string | number | boolean | null\nexport type JsonValue = JsonPrimitive | ReadonlyArray<JsonValue> | JsonRecord\nexport interface JsonRecord {\n readonly [key: string]: JsonValue\n}\n\nexport interface ProjectLocator {\n readonly normalizedCwd: string\n readonly isWithinRoot: (candidate: string) => boolean\n}\n\ninterface RecordMetadata {\n readonly cwd: Option.Option<string>\n}\n\nconst isJsonRecord = (value: JsonValue): value is JsonRecord =>\n typeof value === \"object\" && value !== null && !Array.isArray(value)\n\nconst pickString = (record: JsonRecord, key: string): Option.Option<string> => {\n const candidate = record[key]\n return Option.fromNullable(typeof candidate === \"string\" ? candidate : null)\n}\n\nconst pickRecord = (record: JsonRecord, key: string): Option.Option<JsonRecord> =>\n pipe(\n record[key],\n Option.fromNullable,\n Option.filter((value) => isJsonRecord(value))\n )\n\nconst extractCwd = (record: JsonRecord): Option.Option<string> =>\n pipe(\n pickString(record, \"cwd\"),\n Option.orElse(() =>\n pipe(\n pickRecord(record, \"payload\"),\n Option.flatMap((payload) => pickString(payload, \"cwd\"))\n )\n )\n )\n\nconst toMetadata = (value: JsonValue): RecordMetadata => {\n if (!isJsonRecord(value)) {\n return { cwd: Option.none() }\n }\n\n return {\n cwd: extractCwd(value)\n }\n}\n\nconst cwdMatches = (metadata: RecordMetadata, locator: ProjectLocator): boolean =>\n Option.exists(metadata.cwd, (cwdValue) => locator.isWithinRoot(cwdValue))\n\nconst metadataMatches = (\n metadata: RecordMetadata,\n locator: ProjectLocator\n): boolean => cwdMatches(metadata, locator)\n\n/**\n * Builds a locator for matching project-scoped metadata.\n *\n * @param normalizedCwd - Pre-normalized cwd of the project root.\n * @param isWithinRoot - Pure predicate for checking candidate cwd membership.\n * @returns Locator values for project comparisons.\n *\n * @pure true\n * @invariant normalizedCwd is absolute and stable for equal inputs\n * @complexity O(1) time / O(1) space\n */\n// CHANGE: bundle normalized root and pure membership predicate in a locator\n// WHY: keep matching invariants in CORE and leave path normalization in SHELL\n// QUOTE(TZ): \"FUNCTIONAL CORE, IMPERATIVE SHELL\"\n// REF: user-2026-01-19-sync-rewrite\n// SOURCE: n/a\n// FORMAT THEOREM: forall c: locator(c) -> membership(c)\n// PURITY: CORE\n// EFFECT: n/a\n// INVARIANT: normalizedCwd is absolute and stable for equal inputs\n// COMPLEXITY: O(1)/O(1)\nexport const buildProjectLocator = (\n normalizedCwd: string,\n isWithinRoot: (candidate: string) => boolean\n): ProjectLocator => ({\n normalizedCwd,\n isWithinRoot\n})\n\n/**\n * Checks whether a parsed JSON value contains project metadata.\n *\n * @param value - Parsed JSON value from a .jsonl line.\n * @param locator - Normalized project locator.\n * @returns True when cwd matches the project root.\n *\n * @pure true\n * @invariant valueMatchesProject implies metadataMatches for extracted metadata\n * @complexity O(k) where k = number of metadata fields read\n */\n// CHANGE: restrict project matching to cwd-only semantics\n// WHY: align with project-local path matching requirement\n// QUOTE(TZ): \"каждая функция — теорема\"\n// REF: user-2026-01-19-sync-rewrite\n// SOURCE: n/a\n// FORMAT THEOREM: forall v: JsonValue -> matches(v, locator) <-> metadataMatches(v)\n// PURITY: CORE\n// EFFECT: n/a\n// INVARIANT: metadataMatches uses cwd evidence only\n// COMPLEXITY: O(k)/O(1)\nexport const valueMatchesProject = (\n value: JsonValue,\n locator: ProjectLocator\n): boolean => metadataMatches(toMetadata(value), locator)\n","import * as Path from \"@effect/platform/Path\"\nimport * as Schema from \"@effect/schema/Schema\"\nimport { Console, Effect, Option, pipe } from \"effect\"\n\nimport type { JsonValue, ProjectLocator } from \"../../../core/knowledge.js\"\nimport { buildProjectLocator, valueMatchesProject } from \"../../../core/knowledge.js\"\nimport { FileSystemService } from \"../../services/file-system.js\"\nimport { RuntimeEnv } from \"../../services/runtime-env.js\"\nimport {\n collectFiles,\n copyFilePreservingRelativePath,\n ensureDestination,\n findFirstMatching,\n resolveProjectRoot\n} from \"../shared.js\"\nimport { type SyncError, syncError, type SyncOptions } from \"../types.js\"\n\ntype CodexEnv = RuntimeEnv | FileSystemService | Path.Path\ntype CodexFsEnv = FileSystemService | Path.Path\n\nconst some = Option.some\nconst forEach = Effect.forEach\n\nconst JsonValueSchema: Schema.Schema<JsonValue> = Schema.suspend(() =>\n Schema.Union(\n Schema.String,\n Schema.Number,\n Schema.Boolean,\n Schema.Null,\n Schema.Array(JsonValueSchema),\n Schema.Record({ key: Schema.String, value: JsonValueSchema })\n )\n)\n\nconst parseJsonLine = (\n line: string\n): Effect.Effect<Option.Option<JsonValue>> =>\n pipe(\n Schema.decode(Schema.parseJson(JsonValueSchema))(line),\n Effect.match({\n onFailure: () => Option.none(),\n onSuccess: (value) => some(value)\n })\n )\n\nconst resolveEnvValue = (envValue: Option.Option<string>): string | undefined => Option.getOrUndefined(envValue)\n\nconst buildLocator = (path: Path.Path, projectRoot: string): ProjectLocator => {\n const normalizedRoot = path.resolve(projectRoot)\n const isWithinRoot = (candidate: string): boolean => {\n const normalizedCandidate = path.resolve(candidate)\n const relative = path.relative(normalizedRoot, normalizedCandidate)\n return relative === \"\" || (!relative.startsWith(\"..\") && !path.isAbsolute(relative))\n }\n return buildProjectLocator(normalizedRoot, isWithinRoot)\n}\n\nconst containsJsonl = (root: string): Effect.Effect<boolean, SyncError, FileSystemService> =>\n Effect.gen(function*(_) {\n const fs = yield* _(FileSystemService)\n const entries = yield* _(fs.readDirectory(root))\n for (const entry of entries) {\n if (entry.kind === \"file\" && entry.path.endsWith(\".jsonl\")) {\n return true\n }\n if (entry.kind === \"directory\") {\n const found = yield* _(containsJsonl(entry.path))\n if (found) {\n return true\n }\n }\n }\n return false\n })\n\nconst hasJsonlInCandidate = (\n candidate: string\n): Effect.Effect<boolean, SyncError, FileSystemService> =>\n Effect.gen(function*(_) {\n const fs = yield* _(FileSystemService)\n const exists = yield* _(fs.exists(candidate))\n if (!exists) {\n return false\n }\n return yield* _(containsJsonl(candidate))\n })\n\nconst findFirstExistingWithJsonl = (\n candidates: ReadonlyArray<string>\n): Effect.Effect<string | undefined, SyncError, FileSystemService> => findFirstMatching(candidates, hasJsonlInCandidate)\n\nconst resolveSourceDir = (\n options: SyncOptions\n): Effect.Effect<string, SyncError, CodexEnv> =>\n Effect.gen(function*(_) {\n const env = yield* _(RuntimeEnv)\n const path = yield* _(Path.Path)\n const envSource = resolveEnvValue(yield* _(env.envVar(\"CODEX_SOURCE_DIR\")))\n const homeDir = yield* _(env.homedir)\n const projectRoot = resolveProjectRoot(path, options)\n let metaCandidate: string | undefined\n if (options.metaRoot !== undefined) {\n metaCandidate = options.metaRoot.endsWith(\".codex\")\n ? options.metaRoot\n : path.join(options.metaRoot, \".codex\")\n }\n const localSource = path.join(projectRoot, \".codex\")\n const localKnowledge = path.join(projectRoot, \".knowledge\", \".codex\")\n const homeSource = path.join(homeDir, \".codex\")\n const homeKnowledge = path.join(homeDir, \".knowledge\", \".codex\")\n\n const candidates = [\n options.sourceDir,\n envSource,\n metaCandidate,\n localSource,\n homeSource,\n localKnowledge,\n homeKnowledge\n ].filter((candidate): candidate is string => candidate !== undefined)\n\n const existing = yield* _(findFirstExistingWithJsonl(candidates))\n if (existing === undefined) {\n return yield* _(\n Effect.fail(\n syncError(\n \".codex\",\n `No .jsonl files found in .codex candidates; checked: ${candidates.join(\", \")}`\n )\n )\n )\n }\n\n return existing\n })\n\nconst resolveLocator = (\n options: SyncOptions\n): Effect.Effect<ProjectLocator, never, Path.Path> =>\n Effect.gen(function*(_) {\n const path = yield* _(Path.Path)\n const projectRoot = resolveProjectRoot(path, options)\n return buildLocator(path, projectRoot)\n })\n\nconst lineMatchesProject = (\n line: string,\n locator: ProjectLocator\n): Effect.Effect<boolean> =>\n pipe(\n parseJsonLine(line),\n Effect.map((parsed) => Option.exists(parsed, (value) => valueMatchesProject(value, locator)))\n )\n\nconst fileMatchesProject = (\n filePath: string,\n locator: ProjectLocator\n): Effect.Effect<boolean, SyncError, FileSystemService> =>\n Effect.gen(function*(_) {\n const fs = yield* _(FileSystemService)\n const content = yield* _(fs.readFileString(filePath))\n const lines = content.split(\"\\n\")\n const matches = yield* _(\n forEach(lines, (line) => {\n const trimmed = line.trim()\n return trimmed.length === 0\n ? Effect.succeed(false)\n : lineMatchesProject(trimmed, locator)\n })\n )\n return matches.some(Boolean)\n })\n\nconst selectRelevantFiles = (\n files: ReadonlyArray<string>,\n locator: ProjectLocator\n): Effect.Effect<ReadonlyArray<string>, SyncError, FileSystemService> =>\n pipe(\n forEach(files, (filePath) =>\n pipe(\n fileMatchesProject(filePath, locator),\n Effect.map((matches) => ({ filePath, matches }))\n )),\n Effect.map((results) =>\n results\n .filter((result) => result.matches)\n .map((result) => result.filePath)\n )\n )\n\nconst copyCodexFiles = (\n sourceDir: string,\n destinationDir: string,\n locator: ProjectLocator\n): Effect.Effect<void, SyncError, CodexFsEnv> =>\n Effect.gen(function*(_) {\n yield* _(ensureDestination(destinationDir))\n const allJsonlFiles = yield* _(\n collectFiles(sourceDir, (entry) => entry.kind === \"file\" && entry.path.endsWith(\".jsonl\"))\n )\n const relevantFiles = yield* _(selectRelevantFiles(allJsonlFiles, locator))\n yield* _(\n forEach(relevantFiles, (filePath) => copyFilePreservingRelativePath(sourceDir, destinationDir, filePath))\n )\n yield* _(\n Console.log(\n `Codex: copied ${relevantFiles.length} files from ${sourceDir} to ${destinationDir}`\n )\n )\n })\n\n// CHANGE: extract Codex dialog sync into dedicated module\n// WHY: keep Codex-specific shell effects isolated from other sources\n// QUOTE(TZ): \"FUNCTIONAL CORE, IMPERATIVE SHELL\"\n// REF: user-2026-01-19-sync-rewrite\n// SOURCE: n/a\n// FORMAT THEOREM: forall f: relevant(f, locator) -> copied(f)\n// PURITY: SHELL\n// EFFECT: Effect<void, never, FileSystemService | RuntimeEnv | Path>\n// INVARIANT: copied files contain at least one project-matching line by projectRoot\n// COMPLEXITY: O(n)/O(n)\nexport const syncCodex = (\n options: SyncOptions\n): Effect.Effect<void, never, CodexEnv> =>\n Effect.gen(function*(_) {\n const locator = yield* _(resolveLocator(options))\n const sourceDir = yield* _(resolveSourceDir(options))\n const path = yield* _(Path.Path)\n const destinationDir = options.destinationDir ??\n path.join(resolveProjectRoot(path, options), \".knowledge\", \".codex\")\n\n if (path.resolve(sourceDir) === path.resolve(destinationDir)) {\n yield* _(\n Console.log(\n \"Codex source equals destination; skipping copy to avoid duplicates\"\n )\n )\n return\n }\n\n yield* _(copyCodexFiles(sourceDir, destinationDir, locator))\n }).pipe(\n Effect.matchEffect({\n onFailure: (error: SyncError) =>\n Console.log(\n `Codex source not found; skipped syncing Codex dialog files (${error.reason})`\n ),\n onSuccess: () => Effect.void\n })\n )\n\n// CHANGE: expose DirectoryEntry type for Codex traversal helpers\n// WHY: reuse typed filesystem entries without leaking Node types\n// QUOTE(TZ): \"CORE never calls SHELL\"\n// REF: user-2026-01-19-sync-rewrite\n// SOURCE: n/a\n// FORMAT THEOREM: forall e: DirectoryEntry -> shellOnly(e)\n// PURITY: SHELL\n// EFFECT: n/a\n// INVARIANT: entry.kind is one of file|directory|other\n// COMPLEXITY: O(1)/O(1)\n","import * as Path from \"@effect/platform/Path\"\nimport { Effect, Option, pipe } from \"effect\"\n\nimport { CryptoService } from \"../../services/crypto.js\"\nimport { FileSystemService } from \"../../services/file-system.js\"\nimport { RuntimeEnv } from \"../../services/runtime-env.js\"\nimport { createFilteredSource, findFirstMatching, resolveProjectRoot, runSyncSource } from \"../shared.js\"\nimport { type SyncError, syncError, type SyncOptions, type SyncSource } from \"../types.js\"\n\ntype QwenEnv = RuntimeEnv | CryptoService | FileSystemService | Path.Path\n\nconst resolveEnvValue = (envValue: Option.Option<string>): string | undefined => Option.getOrUndefined(envValue)\n\nconst findFirstExisting = (\n candidates: ReadonlyArray<string>\n): Effect.Effect<string | undefined, SyncError, FileSystemService> =>\n findFirstMatching(candidates, (candidate) =>\n Effect.gen(function*(_) {\n const fs = yield* _(FileSystemService)\n return yield* _(fs.exists(candidate))\n }))\n\nconst resolveQwenSourceDir = (\n options: SyncOptions\n): Effect.Effect<string, SyncError, QwenEnv> =>\n Effect.gen(function*(_) {\n const env = yield* _(RuntimeEnv)\n const crypto = yield* _(CryptoService)\n const path = yield* _(Path.Path)\n const projectRoot = resolveProjectRoot(path, options)\n const hash = yield* _(\n pipe(\n crypto.sha256(projectRoot),\n Effect.mapError((error) => syncError(\".qwen\", error.reason))\n )\n )\n const envSource = resolveEnvValue(yield* _(env.envVar(\"QWEN_SOURCE_DIR\")))\n const homeDir = yield* _(env.homedir)\n let baseFromMeta: string | undefined\n if (options.metaRoot !== undefined) {\n baseFromMeta = options.metaRoot.endsWith(\".qwen\")\n ? options.metaRoot\n : path.join(options.metaRoot, \".qwen\")\n }\n const metaKnowledge = options.metaRoot === undefined\n ? undefined\n : path.join(options.metaRoot, \".knowledge\", \".qwen\")\n const homeBase = path.join(homeDir, \".qwen\")\n const homeKnowledge = path.join(homeDir, \".knowledge\", \".qwen\")\n\n const candidates = [\n options.qwenSourceDir,\n envSource,\n baseFromMeta ? path.join(baseFromMeta, \"tmp\", hash) : undefined,\n path.join(projectRoot, \".qwen\", \"tmp\", hash),\n path.join(projectRoot, \".knowledge\", \".qwen\", \"tmp\", hash),\n metaKnowledge ? path.join(metaKnowledge, \"tmp\", hash) : undefined,\n path.join(homeBase, \"tmp\", hash),\n path.join(homeKnowledge, \"tmp\", hash)\n ].filter((candidate): candidate is string => candidate !== undefined)\n\n const found = yield* _(findFirstExisting(candidates))\n if (found === undefined) {\n return yield* _(\n Effect.fail(\n syncError(\n \".qwen\",\n `Qwen source directory is missing for hash ${hash}`\n )\n )\n )\n }\n\n return found\n })\n\nconst qwenSource: SyncSource<QwenEnv> = createFilteredSource({\n name: \"Qwen\",\n destSubdir: \".qwen\",\n resolveSource: resolveQwenSourceDir,\n filter: (entry, fullPath) => entry.kind === \"file\" && fullPath.endsWith(\".json\"),\n errorReason: \"Cannot traverse Qwen directory\"\n})\n\n// CHANGE: sync Qwen dialog files through shared sync runner\n// WHY: keep source-specific resolution isolated and reuse copy/traversal logic\n// QUOTE(TZ): \"SHELL: Все эффекты (IO, сеть, БД, env/process) изолированы\"\n// REF: user-2026-01-19-sync-rewrite\n// SOURCE: n/a\n// FORMAT THEOREM: forall f: json(f) -> copied(f)\n// PURITY: SHELL\n// EFFECT: Effect<void, never, FileSystemService | RuntimeEnv | CryptoService | Path>\n// INVARIANT: only .json files are copied\n// COMPLEXITY: O(n)/O(n)\nexport const syncQwen = (\n options: SyncOptions\n): Effect.Effect<void, never, QwenEnv> => runSyncSource(qwenSource, options)\n","import type * as Path from \"@effect/platform/Path\"\nimport { Effect } from \"effect\"\n\nimport type { CryptoService } from \"../services/crypto.js\"\nimport type { FileSystemService } from \"../services/file-system.js\"\nimport type { RuntimeEnv } from \"../services/runtime-env.js\"\nimport { syncClaude } from \"./sources/claude.js\"\nimport { syncCodex } from \"./sources/codex.js\"\nimport { syncQwen } from \"./sources/qwen.js\"\nimport type { SyncOptions } from \"./types.js\"\n\ntype SyncProgramEnv = RuntimeEnv | FileSystemService | CryptoService | Path.Path\n\n// CHANGE: compose multi-source sync into a single Effect program\n// WHY: centralize orchestration while keeping each source isolated\n// QUOTE(TZ): \"монодическая композиция\"\n// REF: user-2026-01-19-sync-rewrite\n// SOURCE: n/a\n// FORMAT THEOREM: forall s in Sources: run(s) -> synced(s)\n// PURITY: SHELL\n// EFFECT: Effect<void, never, FileSystemService | RuntimeEnv | CryptoService | Path>\n// INVARIANT: sources run sequentially in fixed order\n// COMPLEXITY: O(n)/O(n)\nexport const buildSyncProgram = (\n options: SyncOptions\n): Effect.Effect<\n void,\n never,\n SyncProgramEnv\n> =>\n Effect.gen(function*(_) {\n yield* _(syncClaude(options))\n yield* _(syncCodex(options))\n yield* _(syncQwen(options))\n })\n","import { Effect, pipe } from \"effect\"\n\nimport { readSyncOptions } from \"../shell/cli.js\"\nimport { buildSyncProgram } from \"../shell/sync/index.js\"\n\n/**\n * Compose the knowledge sync CLI as a single effect.\n *\n * @returns Effect that runs multi-source sync in sequence.\n *\n * @pure false - reads argv and performs filesystem IO\n * @effect RuntimeEnv, FileSystemService, CryptoService, Path\n * @invariant forall opts: buildSyncProgram(opts) runs each source exactly once\n * @precondition true\n * @postcondition sources are synced or skipped with logs\n * @complexity O(n) where n = number of files scanned\n * @throws Never - all errors are typed in the Effect error channel\n */\n// CHANGE: rewire program to knowledge-sync orchestration\n// WHY: replace greeting demo with the fully effectful sync pipeline\n// QUOTE(TZ): \"Возьми прошлый ... код и перепиши его полностью\"\n// REF: user-2026-01-19-sync-rewrite\n// SOURCE: n/a\n// FORMAT THEOREM: forall a: parse(a) -> run(sync(a))\n// PURITY: SHELL\n// EFFECT: Effect<void, never, RuntimeEnv | FileSystemService | CryptoService | Path>\n// INVARIANT: sync sources run in deterministic order\n// COMPLEXITY: O(n)/O(n)\nexport const program = pipe(\n readSyncOptions,\n Effect.flatMap((options) => buildSyncProgram(options))\n)\n","import { NodeContext, NodeRuntime } from \"@effect/platform-node\"\nimport { Effect, Layer, pipe } from \"effect\"\n\nimport { CryptoServiceLive } from \"../shell/services/crypto.js\"\nimport { FileSystemLive } from \"../shell/services/file-system.js\"\nimport { RuntimeEnvLive } from \"../shell/services/runtime-env.js\"\nimport { program } from \"./program.js\"\n\n// CHANGE: run the sync program through the Node runtime with all live layers\n// WHY: provide platform services and shell dependencies in one place\n// QUOTE(TZ): \"SHELL: Все эффекты изолированы\"\n// REF: user-2026-01-19-sync-rewrite\n// SOURCE: n/a\n// FORMAT THEOREM: forall env: provide(env) -> runMain(program)\n// PURITY: SHELL\n// EFFECT: Effect<void, never, RuntimeEnv | FileSystemService | CryptoService | Path>\n// INVARIANT: program executed with NodeContext + live services\n// COMPLEXITY: O(1)/O(1)\nconst main = pipe(\n program,\n Effect.provide(\n Layer.provideMerge(\n Layer.mergeAll(RuntimeEnvLive, FileSystemLive, CryptoServiceLive),\n NodeContext.layer\n )\n )\n)\n\nNodeRuntime.runMain(main)\n"],"names":["forEach","resolveEnvValue"],"mappings":"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"}
package/package.json CHANGED
@@ -1,11 +1,16 @@
1
1
  {
2
2
  "name": "@prover-coder-ai/context-doc",
3
- "version": "1.0.18",
3
+ "version": "1.0.19",
4
4
  "description": "Minimal Vite-powered TypeScript console starter using Effect",
5
5
  "main": "dist/main.js",
6
6
  "bin": {
7
7
  "context-doc": "bin/context-doc.js"
8
8
  },
9
+ "files": [
10
+ "dist",
11
+ "bin",
12
+ "README.md"
13
+ ],
9
14
  "directories": {
10
15
  "doc": "doc"
11
16
  },
package/.jscpd.json DELETED
@@ -1,16 +0,0 @@
1
- {
2
- "threshold": 0,
3
- "minTokens": 30,
4
- "minLines": 5,
5
- "ignore": [
6
- "**/node_modules/**",
7
- "**/build/**",
8
- "**/dist/**",
9
- "**/*.min.js",
10
- "**/reports/**"
11
- ],
12
- "skipComments": true,
13
- "ignorePattern": [
14
- "private readonly \\w+: \\w+;\\s*private readonly \\w+: \\w+;\\s*private \\w+: \\w+ \\| null = null;\\s*private \\w+: \\w+ \\| null = null;"
15
- ]
16
- }
package/CHANGELOG.md DELETED
@@ -1,43 +0,0 @@
1
- # @prover-coder-ai/context-doc
2
-
3
- ## 1.0.18
4
-
5
- ### Patch Changes
6
-
7
- - chore: automated version bump
8
-
9
- ## 1.0.17
10
-
11
- ### Patch Changes
12
-
13
- - chore: automated version bump
14
-
15
- ## 1.0.16
16
-
17
- ### Patch Changes
18
-
19
- - chore: automated version bump
20
-
21
- ## 1.0.15
22
-
23
- ### Patch Changes
24
-
25
- - chore: automated version bump
26
-
27
- ## 1.0.14
28
-
29
- ### Patch Changes
30
-
31
- - chore: automated version bump
32
-
33
- ## 1.0.13
34
-
35
- ### Patch Changes
36
-
37
- - chore: automated version bump
38
-
39
- ## 1.0.1
40
-
41
- ### Patch Changes
42
-
43
- - chore: automated version bump
package/biome.json DELETED
@@ -1,37 +0,0 @@
1
- {
2
- "vcs": {
3
- "enabled": false,
4
- "clientKind": "git",
5
- "useIgnoreFile": false
6
- },
7
- "files": {
8
- "ignoreUnknown": false
9
- },
10
- "formatter": {
11
- "enabled": false,
12
- "indentStyle": "tab"
13
- },
14
- "assist": {
15
- "actions": {
16
- "source": {
17
- "organizeImports": "off"
18
- }
19
- }
20
- },
21
- "linter": {
22
- "enabled": false,
23
- "rules": {
24
- "recommended": false,
25
- "suspicious": {
26
- "noExplicitAny": "off"
27
- }
28
- }
29
- },
30
- "javascript": {
31
- "formatter": {
32
- "enabled": false,
33
- "quoteStyle": "double",
34
- "semicolons": "asNeeded"
35
- }
36
- }
37
- }
package/eslint.config.mts DELETED
@@ -1,305 +0,0 @@
1
- // eslint.config.mjs
2
- // @ts-check
3
- import eslint from '@eslint/js';
4
- import { defineConfig } from 'eslint/config';
5
- import tseslint from 'typescript-eslint';
6
- import vitest from "@vitest/eslint-plugin";
7
- import suggestMembers from "@prover-coder-ai/eslint-plugin-suggest-members";
8
- import sonarjs from "eslint-plugin-sonarjs";
9
- import unicorn from "eslint-plugin-unicorn";
10
- import * as effectEslint from "@effect/eslint-plugin";
11
- import { fixupPluginRules } from "@eslint/compat";
12
- import codegen from "eslint-plugin-codegen";
13
- import importPlugin from "eslint-plugin-import";
14
- import simpleImportSort from "eslint-plugin-simple-import-sort";
15
- import sortDestructureKeys from "eslint-plugin-sort-destructure-keys";
16
- import globals from "globals";
17
- import eslintCommentsConfigs from "@eslint-community/eslint-plugin-eslint-comments/configs";
18
-
19
- const codegenPlugin = fixupPluginRules(
20
- codegen as unknown as Parameters<typeof fixupPluginRules>[0],
21
- );
22
-
23
- const noFetchExample = [
24
- "Пример:",
25
- " import { FetchHttpClient, HttpClient } from \"@effect/platform\"",
26
- " import { Effect } from \"effect\"",
27
- " const program = Effect.gen(function* () {",
28
- " const client = yield* HttpClient.HttpClient",
29
- " return yield* client.get(`${api}/robots`)",
30
- " }).pipe(",
31
- " Effect.scoped,",
32
- " Effect.provide(FetchHttpClient.layer)",
33
- " )",
34
- ].join("\n");
35
-
36
- export default defineConfig(
37
- eslint.configs.recommended,
38
- tseslint.configs.strictTypeChecked,
39
- effectEslint.configs.dprint,
40
- suggestMembers.configs.recommended,
41
- eslintCommentsConfigs.recommended,
42
- {
43
- name: "analyzers",
44
- languageOptions: {
45
- parser: tseslint.parser,
46
- globals: { ...globals.node, ...globals.browser },
47
- parserOptions: {
48
- projectService: true,
49
- tsconfigRootDir: import.meta.dirname,
50
- },
51
- },
52
- plugins: {
53
- sonarjs,
54
- unicorn,
55
- import: fixupPluginRules(importPlugin),
56
- "sort-destructure-keys": sortDestructureKeys,
57
- "simple-import-sort": simpleImportSort,
58
- codegen: codegenPlugin,
59
- },
60
- files: ["**/*.ts", '**/*.{test,spec}.{ts,tsx}', '**/tests/**', '**/__tests__/**'],
61
- settings: {
62
- "import/parsers": {
63
- "@typescript-eslint/parser": [".ts", ".tsx"],
64
- },
65
- "import/resolver": {
66
- typescript: {
67
- alwaysTryTypes: true,
68
- },
69
- },
70
- },
71
- rules: {
72
- ...sonarjs.configs.recommended.rules,
73
- ...unicorn.configs.recommended.rules,
74
- "no-restricted-imports": ["error", {
75
- paths: [
76
- {
77
- name: "ts-pattern",
78
- message: "Use Effect.Match instead of ts-pattern.",
79
- },
80
- {
81
- name: "zod",
82
- message: "Use @effect/schema for schemas and validation.",
83
- },
84
- ],
85
- }],
86
- "codegen/codegen": "error",
87
- "import/first": "error",
88
- "import/newline-after-import": "error",
89
- "import/no-duplicates": "error",
90
- "import/no-unresolved": "off",
91
- "import/order": "off",
92
- "simple-import-sort/imports": "off",
93
- "sort-destructure-keys/sort-destructure-keys": "error",
94
- "no-fallthrough": "off",
95
- "no-irregular-whitespace": "off",
96
- "object-shorthand": "error",
97
- "prefer-destructuring": "off",
98
- "sort-imports": "off",
99
- "no-unused-vars": "off",
100
- "prefer-rest-params": "off",
101
- "prefer-spread": "off",
102
- "unicorn/prefer-top-level-await": "off",
103
- "unicorn/prevent-abbreviations": "off",
104
- "unicorn/no-null": "off",
105
- complexity: ["error", 8],
106
- "max-lines-per-function": [
107
- "error",
108
- { max: 50, skipBlankLines: true, skipComments: true },
109
- ],
110
- "max-params": ["error", 5],
111
- "max-depth": ["error", 4],
112
- "max-lines": [
113
- "error",
114
- { max: 300, skipBlankLines: true, skipComments: true },
115
- ],
116
-
117
- "@typescript-eslint/restrict-template-expressions": ["error", {
118
- allowNumber: true,
119
- allowBoolean: true,
120
- allowNullish: false,
121
- allowAny: false,
122
- allowRegExp: false
123
- }],
124
- "@eslint-community/eslint-comments/no-use": "error",
125
- "@eslint-community/eslint-comments/no-unlimited-disable": "error",
126
- "@eslint-community/eslint-comments/disable-enable-pair": "error",
127
- "@eslint-community/eslint-comments/no-unused-disable": "error",
128
- "no-restricted-syntax": [
129
- "error",
130
- {
131
- selector: "TSUnknownKeyword",
132
- message: "Запрещено 'unknown'.",
133
- },
134
- // CHANGE: запрет прямого fetch в коде
135
- // WHY: enforce Effect-TS httpClient as единственный источник сетевых эффектов
136
- // QUOTE(ТЗ): "Вместо fetch должно быть всегда написано httpClient от библиотеки Effect-TS"
137
- // REF: user-msg-1
138
- // SOURCE: n/a
139
- // FORMAT THEOREM: ∀call ∈ Calls: callee(call)=fetch → lint_error(call)
140
- // PURITY: SHELL
141
- // EFFECT: Effect<never, never, never>
142
- // INVARIANT: direct fetch calls are forbidden
143
- // COMPLEXITY: O(1)
144
- {
145
- selector: "CallExpression[callee.name='fetch']",
146
- message: `Запрещён fetch — используй HttpClient (Effect-TS).\n${noFetchExample}`,
147
- },
148
- {
149
- selector:
150
- "CallExpression[callee.object.name='window'][callee.property.name='fetch']",
151
- message: `Запрещён window.fetch — используй HttpClient (Effect-TS).\n${noFetchExample}`,
152
- },
153
- {
154
- selector:
155
- "CallExpression[callee.object.name='globalThis'][callee.property.name='fetch']",
156
- message: `Запрещён globalThis.fetch — используй HttpClient (Effect-TS).\n${noFetchExample}`,
157
- },
158
- {
159
- selector:
160
- "CallExpression[callee.object.name='self'][callee.property.name='fetch']",
161
- message: `Запрещён self.fetch — используй HttpClient (Effect-TS).\n${noFetchExample}`,
162
- },
163
- {
164
- selector:
165
- "CallExpression[callee.object.name='global'][callee.property.name='fetch']",
166
- message: `Запрещён global.fetch — используй HttpClient (Effect-TS).\n${noFetchExample}`,
167
- },
168
- {
169
- selector: "TryStatement",
170
- message: "Используй Effect.try / catchAll вместо try/catch в core/app/domain.",
171
- },
172
- {
173
- selector: "SwitchStatement",
174
- message: [
175
- "Switch statements are forbidden in functional programming paradigm.",
176
- "How to fix: Use Effect.Match instead.",
177
- "Example:",
178
- " import { Match } from 'effect';",
179
- " type Item = { type: 'this' } | { type: 'that' };",
180
- " const result = Match.value(item).pipe(",
181
- " Match.when({ type: 'this' }, (it) => processThis(it)),",
182
- " Match.when({ type: 'that' }, (it) => processThat(it)),",
183
- " Match.exhaustive,",
184
- " );",
185
- ].join("\n"),
186
- },
187
- {
188
- selector: 'CallExpression[callee.name="require"]',
189
- message: "Avoid using require(). Use ES6 imports instead.",
190
- },
191
- {
192
- selector: "ThrowStatement > Literal:not([value=/^\\w+Error:/])",
193
- message:
194
- 'Do not throw string literals or non-Error objects. Throw new Error("...") instead.',
195
- },
196
- {
197
- selector:
198
- "FunctionDeclaration[async=true], FunctionExpression[async=true], ArrowFunctionExpression[async=true]",
199
- message:
200
- "Запрещён async/await — используй Effect.gen / Effect.tryPromise.",
201
- },
202
- {
203
- selector: "NewExpression[callee.name='Promise']",
204
- message:
205
- "Запрещён new Promise — используй Effect.async / Effect.tryPromise.",
206
- },
207
- {
208
- selector: "CallExpression[callee.object.name='Promise']",
209
- message:
210
- "Запрещены Promise.* — используй комбинаторы Effect (all, forEach, etc.).",
211
- },
212
- {
213
- selector: "CallExpression[callee.property.name='push'] > SpreadElement.arguments",
214
- message: "Do not use spread arguments in Array.push",
215
- },
216
- ],
217
- "no-throw-literal": "error",
218
- "@typescript-eslint/no-restricted-types": [
219
- "error",
220
- {
221
- types: {
222
- unknown: {
223
- message:
224
- "Не используем 'unknown'. Уточни тип или наведи порядок в источнике данных.",
225
- },
226
- Promise: {
227
- message: "Запрещён Promise — используй Effect.Effect<A, E, R>.",
228
- suggest: ["Effect.Effect"],
229
- },
230
- "Promise<*>": {
231
- message:
232
- "Запрещён Promise<T> — используй Effect.Effect<T, E, R>.",
233
- suggest: ["Effect.Effect<T, E, R>"],
234
- },
235
- },
236
- },
237
- ],
238
- "@typescript-eslint/use-unknown-in-catch-callback-variable": "off",
239
- // "no-throw-literal": "off",
240
- "@typescript-eslint/only-throw-error": [
241
- "error",
242
- { allowThrowingUnknown: false, allowThrowingAny: false },
243
- ],
244
- "@typescript-eslint/array-type": ["warn", {
245
- default: "generic",
246
- readonly: "generic"
247
- }],
248
- "@typescript-eslint/member-delimiter-style": 0,
249
- "@typescript-eslint/no-non-null-assertion": "off",
250
- "@typescript-eslint/ban-types": "off",
251
- "@typescript-eslint/no-explicit-any": "off",
252
- "@typescript-eslint/no-empty-interface": "off",
253
- "@typescript-eslint/consistent-type-imports": "warn",
254
- "@typescript-eslint/no-unused-vars": ["error", {
255
- argsIgnorePattern: "^_",
256
- varsIgnorePattern: "^_"
257
- }],
258
- "@typescript-eslint/ban-ts-comment": "off",
259
- "@typescript-eslint/camelcase": "off",
260
- "@typescript-eslint/explicit-function-return-type": "off",
261
- "@typescript-eslint/explicit-module-boundary-types": "off",
262
- "@typescript-eslint/interface-name-prefix": "off",
263
- "@typescript-eslint/no-array-constructor": "off",
264
- "@typescript-eslint/no-use-before-define": "off",
265
- "@typescript-eslint/no-namespace": "off",
266
- "@effect/dprint": ["error", {
267
- config: {
268
- indentWidth: 2,
269
- lineWidth: 120,
270
- semiColons: "asi",
271
- quoteStyle: "alwaysDouble",
272
- trailingCommas: "never",
273
- operatorPosition: "maintain",
274
- "arrowFunction.useParentheses": "force"
275
- }
276
- }]
277
- }
278
- },
279
- {
280
- files: ['**/*.{test,spec}.{ts,tsx}', 'tests/**', '**/__tests__/**'],
281
- ...vitest.configs.all,
282
- languageOptions: {
283
- globals: {
284
- ...vitest.environments.env.globals,
285
- },
286
- },
287
- rules: {
288
- // Allow eslint-disable/enable comments in test files for fine-grained control
289
- '@eslint-community/eslint-comments/no-use': 'off',
290
- // Disable line count limit for E2E tests that contain multiple test cases
291
- 'max-lines-per-function': 'off',
292
- // `it.effect` is not recognized by sonar rule; disable to avoid false positives
293
- 'sonarjs/no-empty-test-file': 'off',
294
- },
295
- },
296
-
297
- // 3) Для JS-файлов отключим типо-зависимые проверки
298
- {
299
- files: ['**/*.{js,cjs,mjs}'],
300
- extends: [tseslint.configs.disableTypeChecked],
301
- },
302
-
303
- // 4) Глобальные игноры
304
- { ignores: ['dist/**', 'build/**', 'coverage/**', '**/dist/**'] },
305
- );