yandecode 0.1.1 → 0.2.0

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.
Files changed (226) hide show
  1. package/dist/bin.js +14 -8
  2. package/dist/bin.js.map +7 -1
  3. package/dist/chunks/chunk-23DG7PZZ.js +58 -0
  4. package/dist/chunks/chunk-23DG7PZZ.js.map +7 -0
  5. package/dist/chunks/chunk-2S6B3DDQ.js +1769 -0
  6. package/dist/chunks/chunk-2S6B3DDQ.js.map +7 -0
  7. package/dist/chunks/chunk-6J5CZVCJ.js +120 -0
  8. package/dist/chunks/chunk-6J5CZVCJ.js.map +7 -0
  9. package/dist/chunks/chunk-7L6DD2VD.js +768 -0
  10. package/dist/chunks/chunk-7L6DD2VD.js.map +7 -0
  11. package/dist/chunks/chunk-DWD37AI2.js +39 -0
  12. package/dist/chunks/chunk-DWD37AI2.js.map +7 -0
  13. package/dist/chunks/chunk-KPDBXQ62.js +62 -0
  14. package/dist/chunks/chunk-KPDBXQ62.js.map +7 -0
  15. package/dist/chunks/chunk-KVBKQXTU.js +351 -0
  16. package/dist/chunks/chunk-KVBKQXTU.js.map +7 -0
  17. package/dist/chunks/chunk-L2DDIZPI.js +53 -0
  18. package/dist/chunks/chunk-L2DDIZPI.js.map +7 -0
  19. package/dist/chunks/chunk-OIAMKDTQ.js +27 -0
  20. package/dist/chunks/chunk-OIAMKDTQ.js.map +7 -0
  21. package/dist/chunks/chunk-PUWSEWX3.js +61 -0
  22. package/dist/chunks/chunk-PUWSEWX3.js.map +7 -0
  23. package/dist/chunks/chunk-QCQC73WX.js +122 -0
  24. package/dist/chunks/chunk-QCQC73WX.js.map +7 -0
  25. package/dist/chunks/chunk-TYLH4NIC.js +39 -0
  26. package/dist/chunks/chunk-TYLH4NIC.js.map +7 -0
  27. package/dist/chunks/chunk-VKVJGBNJ.js +72 -0
  28. package/dist/chunks/chunk-VKVJGBNJ.js.map +7 -0
  29. package/dist/chunks/chunk-Y2MIXROU.js +20072 -0
  30. package/dist/chunks/chunk-Y2MIXROU.js.map +7 -0
  31. package/dist/chunks/cli-V6PJTDLM.js +3464 -0
  32. package/dist/chunks/cli-V6PJTDLM.js.map +7 -0
  33. package/dist/chunks/doctor-LLDVEPWL.js +184 -0
  34. package/dist/chunks/doctor-LLDVEPWL.js.map +7 -0
  35. package/dist/chunks/entry-YAOEX3EB.js +187 -0
  36. package/dist/chunks/entry-YAOEX3EB.js.map +7 -0
  37. package/dist/chunks/init-4ZJFCKIJ.js +46 -0
  38. package/dist/chunks/init-4ZJFCKIJ.js.map +7 -0
  39. package/dist/chunks/mcp-serve-KWKMUGWZ.js +22575 -0
  40. package/dist/chunks/mcp-serve-KWKMUGWZ.js.map +7 -0
  41. package/dist/chunks/modules-CJB5IKUJ.js +121 -0
  42. package/dist/chunks/modules-CJB5IKUJ.js.map +7 -0
  43. package/dist/chunks/runtime-3E4NIFAL.js +208 -0
  44. package/dist/chunks/runtime-3E4NIFAL.js.map +7 -0
  45. package/dist/chunks/runtime-7CRR63B5.js +395 -0
  46. package/dist/chunks/runtime-7CRR63B5.js.map +7 -0
  47. package/dist/chunks/runtime-CKMVHAU4.js +64 -0
  48. package/dist/chunks/runtime-CKMVHAU4.js.map +7 -0
  49. package/dist/chunks/runtime-CVZMWIJO.js +318 -0
  50. package/dist/chunks/runtime-CVZMWIJO.js.map +7 -0
  51. package/dist/chunks/runtime-DBNXBOAL.js +295 -0
  52. package/dist/chunks/runtime-DBNXBOAL.js.map +7 -0
  53. package/dist/chunks/runtime-EKHO2JXB.js +197 -0
  54. package/dist/chunks/runtime-EKHO2JXB.js.map +7 -0
  55. package/dist/chunks/runtime-EY6SVZYP.js +539 -0
  56. package/dist/chunks/runtime-EY6SVZYP.js.map +7 -0
  57. package/dist/chunks/runtime-UB2O2HUN.js +212 -0
  58. package/dist/chunks/runtime-UB2O2HUN.js.map +7 -0
  59. package/dist/chunks/runtime-WAFQWW4M.js +755 -0
  60. package/dist/chunks/runtime-WAFQWW4M.js.map +7 -0
  61. package/dist/chunks/runtime-ZGGF6RVA.js +271 -0
  62. package/dist/chunks/runtime-ZGGF6RVA.js.map +7 -0
  63. package/dist/chunks/status-SPIESL4F.js +38 -0
  64. package/dist/chunks/status-SPIESL4F.js.map +7 -0
  65. package/dist/chunks/uninstall-J2OWCX4A.js +54 -0
  66. package/dist/chunks/uninstall-J2OWCX4A.js.map +7 -0
  67. package/dist/chunks/update-OX5MZYQY.js +34 -0
  68. package/dist/chunks/update-OX5MZYQY.js.map +7 -0
  69. package/dist/content/agents/yandecode-reviewer.md +22 -0
  70. package/dist/content/agents/yandecode-security-reviewer.md +23 -0
  71. package/dist/content/skills/NOTICE.md +29 -0
  72. package/dist/content/skills/yandecode-code-review/SKILL.md +37 -0
  73. package/dist/content/skills/yandecode-debugging/SKILL.md +33 -0
  74. package/dist/content/skills/yandecode-instructions/SKILL.md +26 -0
  75. package/dist/content/skills/yandecode-memory/SKILL.md +36 -0
  76. package/dist/content/skills/yandecode-security-review/SKILL.md +24 -0
  77. package/dist/content/skills/yandecode-tdd/SKILL.md +38 -0
  78. package/dist/content/skills/yandecode-verification/SKILL.md +29 -0
  79. package/dist/content/skills/yandecode-workflow/SKILL.md +50 -0
  80. package/package.json +25 -19
  81. package/dist/bin.d.ts +0 -3
  82. package/dist/bin.d.ts.map +0 -1
  83. package/dist/claude-bin.d.ts +0 -2
  84. package/dist/claude-bin.d.ts.map +0 -1
  85. package/dist/claude-bin.js +0 -4
  86. package/dist/claude-bin.js.map +0 -1
  87. package/dist/cli.d.ts +0 -6
  88. package/dist/cli.d.ts.map +0 -1
  89. package/dist/cli.js +0 -21
  90. package/dist/cli.js.map +0 -1
  91. package/dist/commands/doctor.d.ts +0 -2
  92. package/dist/commands/doctor.d.ts.map +0 -1
  93. package/dist/commands/doctor.js +0 -19
  94. package/dist/commands/doctor.js.map +0 -1
  95. package/dist/commands/hook.d.ts +0 -2
  96. package/dist/commands/hook.d.ts.map +0 -1
  97. package/dist/commands/hook.js +0 -23
  98. package/dist/commands/hook.js.map +0 -1
  99. package/dist/commands/index-cmd.d.ts +0 -2
  100. package/dist/commands/index-cmd.d.ts.map +0 -1
  101. package/dist/commands/index-cmd.js +0 -47
  102. package/dist/commands/index-cmd.js.map +0 -1
  103. package/dist/commands/index.d.ts +0 -13
  104. package/dist/commands/index.d.ts.map +0 -1
  105. package/dist/commands/index.js +0 -15
  106. package/dist/commands/index.js.map +0 -1
  107. package/dist/commands/init.d.ts +0 -2
  108. package/dist/commands/init.d.ts.map +0 -1
  109. package/dist/commands/init.js +0 -22
  110. package/dist/commands/init.js.map +0 -1
  111. package/dist/commands/mcp.d.ts +0 -2
  112. package/dist/commands/mcp.d.ts.map +0 -1
  113. package/dist/commands/mcp.js +0 -71
  114. package/dist/commands/mcp.js.map +0 -1
  115. package/dist/commands/rag.d.ts +0 -2
  116. package/dist/commands/rag.d.ts.map +0 -1
  117. package/dist/commands/rag.js +0 -27
  118. package/dist/commands/rag.js.map +0 -1
  119. package/dist/commands/start.d.ts +0 -5
  120. package/dist/commands/start.d.ts.map +0 -1
  121. package/dist/commands/start.js +0 -74
  122. package/dist/commands/start.js.map +0 -1
  123. package/dist/commands/status.d.ts +0 -2
  124. package/dist/commands/status.d.ts.map +0 -1
  125. package/dist/commands/status.js +0 -29
  126. package/dist/commands/status.js.map +0 -1
  127. package/dist/commands/statusline.d.ts +0 -2
  128. package/dist/commands/statusline.d.ts.map +0 -1
  129. package/dist/commands/statusline.js +0 -90
  130. package/dist/commands/statusline.js.map +0 -1
  131. package/dist/commands/swarm.d.ts +0 -4
  132. package/dist/commands/swarm.d.ts.map +0 -1
  133. package/dist/commands/swarm.js +0 -48
  134. package/dist/commands/swarm.js.map +0 -1
  135. package/dist/commands/uninstall.d.ts +0 -2
  136. package/dist/commands/uninstall.d.ts.map +0 -1
  137. package/dist/commands/uninstall.js +0 -16
  138. package/dist/commands/uninstall.js.map +0 -1
  139. package/dist/context.d.ts +0 -13
  140. package/dist/context.d.ts.map +0 -1
  141. package/dist/context.js +0 -31
  142. package/dist/context.js.map +0 -1
  143. package/dist/doctor/checks.d.ts +0 -18
  144. package/dist/doctor/checks.d.ts.map +0 -1
  145. package/dist/doctor/checks.js +0 -270
  146. package/dist/doctor/checks.js.map +0 -1
  147. package/dist/hooks/handlers.d.ts +0 -21
  148. package/dist/hooks/handlers.d.ts.map +0 -1
  149. package/dist/hooks/handlers.js +0 -191
  150. package/dist/hooks/handlers.js.map +0 -1
  151. package/dist/index.d.ts +0 -10
  152. package/dist/index.d.ts.map +0 -1
  153. package/dist/index.js +0 -10
  154. package/dist/index.js.map +0 -1
  155. package/dist/integration/claude-md.d.ts +0 -6
  156. package/dist/integration/claude-md.d.ts.map +0 -1
  157. package/dist/integration/claude-md.js +0 -30
  158. package/dist/integration/claude-md.js.map +0 -1
  159. package/dist/integration/gitignore.d.ts +0 -3
  160. package/dist/integration/gitignore.d.ts.map +0 -1
  161. package/dist/integration/gitignore.js +0 -13
  162. package/dist/integration/gitignore.js.map +0 -1
  163. package/dist/integration/init.d.ts +0 -17
  164. package/dist/integration/init.d.ts.map +0 -1
  165. package/dist/integration/init.js +0 -86
  166. package/dist/integration/init.js.map +0 -1
  167. package/dist/integration/json-utils.d.ts +0 -13
  168. package/dist/integration/json-utils.d.ts.map +0 -1
  169. package/dist/integration/json-utils.js +0 -33
  170. package/dist/integration/json-utils.js.map +0 -1
  171. package/dist/integration/manifest.d.ts +0 -17
  172. package/dist/integration/manifest.d.ts.map +0 -1
  173. package/dist/integration/manifest.js +0 -26
  174. package/dist/integration/manifest.js.map +0 -1
  175. package/dist/integration/materialize.d.ts +0 -9
  176. package/dist/integration/materialize.d.ts.map +0 -1
  177. package/dist/integration/materialize.js +0 -21
  178. package/dist/integration/materialize.js.map +0 -1
  179. package/dist/integration/mcp-config.d.ts +0 -4
  180. package/dist/integration/mcp-config.d.ts.map +0 -1
  181. package/dist/integration/mcp-config.js +0 -11
  182. package/dist/integration/mcp-config.js.map +0 -1
  183. package/dist/integration/settings.d.ts +0 -7
  184. package/dist/integration/settings.d.ts.map +0 -1
  185. package/dist/integration/settings.js +0 -70
  186. package/dist/integration/settings.js.map +0 -1
  187. package/dist/integration/uninstall.d.ts +0 -10
  188. package/dist/integration/uninstall.d.ts.map +0 -1
  189. package/dist/integration/uninstall.js +0 -71
  190. package/dist/integration/uninstall.js.map +0 -1
  191. package/dist/launcher.d.ts +0 -8
  192. package/dist/launcher.d.ts.map +0 -1
  193. package/dist/launcher.js +0 -18
  194. package/dist/launcher.js.map +0 -1
  195. package/dist/mcp/server.d.ts +0 -27
  196. package/dist/mcp/server.d.ts.map +0 -1
  197. package/dist/mcp/server.js +0 -311
  198. package/dist/mcp/server.js.map +0 -1
  199. package/dist/plugin-content.d.ts +0 -21
  200. package/dist/plugin-content.d.ts.map +0 -1
  201. package/dist/plugin-content.js +0 -67
  202. package/dist/plugin-content.js.map +0 -1
  203. package/dist/rag/format.d.ts +0 -3
  204. package/dist/rag/format.d.ts.map +0 -1
  205. package/dist/rag/format.js +0 -12
  206. package/dist/rag/format.js.map +0 -1
  207. package/dist/retrieval-runtime.d.ts +0 -21
  208. package/dist/retrieval-runtime.d.ts.map +0 -1
  209. package/dist/retrieval-runtime.js +0 -47
  210. package/dist/retrieval-runtime.js.map +0 -1
  211. package/dist/status-line/git.d.ts +0 -3
  212. package/dist/status-line/git.d.ts.map +0 -1
  213. package/dist/status-line/git.js +0 -34
  214. package/dist/status-line/git.js.map +0 -1
  215. package/dist/status-line/render.d.ts +0 -29
  216. package/dist/status-line/render.d.ts.map +0 -1
  217. package/dist/status-line/render.js +0 -72
  218. package/dist/status-line/render.js.map +0 -1
  219. package/dist/swarm-runtime.d.ts +0 -11
  220. package/dist/swarm-runtime.d.ts.map +0 -1
  221. package/dist/swarm-runtime.js +0 -76
  222. package/dist/swarm-runtime.js.map +0 -1
  223. package/dist/version.d.ts +0 -2
  224. package/dist/version.d.ts.map +0 -1
  225. package/dist/version.js +0 -5
  226. package/dist/version.js.map +0 -1
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/modules/code/runtime.ts", "../../src/shared/once.ts", "../../src/modules/code/nudge.ts"],
4
+ "sourcesContent": ["import { join } from 'node:path';\nimport { CodeIndex, type SymbolRow, type TextHit } from '@yandecode/retrieval';\nimport { z } from 'zod';\nimport { fitRows } from '@cli/shared/budget';\nimport type {\n HookInput,\n HookResult,\n ModuleContext,\n ModuleRuntime,\n ToolResult,\n} from '@cli/modules/contract';\nimport { firstTimeInSession } from '@cli/shared/once';\nimport { nudgeFor } from './nudge';\nimport { moduleContext, requireWorkspace } from '@cli/modules/host';\nimport {\n codeModule,\n definitionInput,\n referencesInput,\n repoMapInput,\n searchInput,\n symbolsInput,\n} from './definition';\n\nconst SYNC_INTERVAL_MS = 1_500;\n\ninterface OpenIndex {\n index: CodeIndex;\n lastSync: number;\n}\n\nconst open = new Map<string, OpenIndex>();\n\n/** One index per workspace per process, refreshed at most every SYNC_INTERVAL_MS. */\nasync function freshIndex(ctx: Pick<ModuleContext, 'root' | 'paths'>): Promise<CodeIndex> {\n let entry = open.get(ctx.root);\n if (!entry) {\n entry = {\n index: CodeIndex.open(join(ctx.paths.yandecodeDir, 'code.db'), ctx.root),\n lastSync: 0,\n };\n open.set(ctx.root, entry);\n }\n if (Date.now() - entry.lastSync > SYNC_INTERVAL_MS) {\n await entry.index.sync();\n entry.lastSync = Date.now();\n }\n return entry.index;\n}\n\nconst text = (value: string): ToolResult => ({ text: value });\n\nfunction symbolRow(s: SymbolRow): string {\n return `${s.path}:${s.startLine}-${s.endLine} ${s.kind} ${s.namePath} \u2014 ${s.signature}`;\n}\n\nfunction textRow(h: TextHit): string {\n return `${h.path}:${h.startLine}-${h.endLine}${h.symbol ? ` [${h.symbol}]` : ''} ${h.snippet}`;\n}\n\ntype Mode = 'symbol' | 'path' | 'text';\n\n/** Chooses strategies from the query's shape (ADR-017). */\nfunction routeQuery(query: string): Mode[] {\n const q = query.trim();\n if (/\\s/.test(q)) return ['text'];\n if (/\\.[a-z0-9]{1,5}$/i.test(q) || (q.includes('/') && q.includes('.'))) return ['path'];\n if (q.includes('/')) return ['symbol', 'path'];\n return ['symbol', 'path', 'text'];\n}\n\n/** Exact match first; fall back to substring so partial names still find something. */\nfunction symbolSection(\n index: CodeIndex,\n query: string,\n path: string | undefined,\n limit: number,\n): SymbolRow[] {\n const filter = path ? { path } : {};\n const exact = index.findSymbols(query, { ...filter, limit });\n return exact.length > 0 ? exact : index.findSymbols(query, { ...filter, substring: true, limit });\n}\n\ninterface SearchSections {\n symbols: SymbolRow[];\n paths: string[];\n textHits: TextHit[];\n}\n\n/** Runs the strategies the query shape calls for (ADR-017). */\nfunction gather(\n index: CodeIndex,\n args: z.infer<z.ZodObject<typeof searchInput>>,\n modes: Mode[],\n auto: boolean,\n): SearchSections {\n const limit = args.limit ?? 10;\n const exact = modes.includes('symbol') ? symbolSection(index, args.query, args.path, limit) : [];\n // Natural language: symbols whose names echo the question's words lead the answer.\n const echoed = modes.includes('symbol') ? [] : index.findSymbolsByTerms(args.query, { limit: 3 });\n // An exact identifier hit is precise enough: keep the path list short and skip text search.\n const pathLimit = exact.length > 0 ? Math.min(limit, 3) : limit;\n const wantText = modes.includes('text') && (!auto || exact.length === 0);\n return {\n symbols: [...exact, ...echoed],\n paths: modes.includes('path') ? index.searchPaths(args.query, pathLimit) : [],\n textHits: wantText\n ? index.searchText(args.query, echoed.length > 0 ? Math.min(limit, 6) : limit)\n : [],\n };\n}\n\nfunction section(title: string, rows: string[]): string[] {\n return rows.length > 0 ? [title, ...rows.map((r) => ` ${r}`)] : [];\n}\n\nasync function codeSearch(raw: Record<string, unknown>, ctx: ModuleContext): Promise<ToolResult> {\n const args = z.object(searchInput).parse(raw);\n const index = await freshIndex(ctx);\n const auto = (args.mode ?? 'auto') === 'auto';\n const modes: Mode[] = auto ? routeQuery(args.query) : [args.mode as Mode];\n const found = gather(index, args, modes, auto);\n const rows = [\n ...section('symbols:', found.symbols.map(symbolRow)),\n ...section('files:', found.paths),\n ...section('text:', found.textHits.map(textRow)),\n ];\n if (rows.length === 0) {\n return text(\n `No code matches \"${args.query}\" (strategies: ${modes.join(', ')}). Try other words, a file fragment or mode=text.`,\n );\n }\n return text(\n fitRows(`code_search \"${args.query}\" (${modes.join('+')})`, rows, args.max_chars ?? 4_000),\n );\n}\n\nasync function codeSymbols(raw: Record<string, unknown>, ctx: ModuleContext): Promise<ToolResult> {\n const args = z.object(symbolsInput).parse(raw);\n const index = await freshIndex(ctx);\n const path = args.path.replace(/^\\.\\//, '');\n const outline = index.outline(path);\n if (outline.length === 0) {\n const similar = index.searchPaths(path, 3);\n return text(\n `No symbols indexed for ${path}.${similar.length > 0 ? ` Did you mean: ${similar.join(', ')}?` : ''}`,\n );\n }\n const rows = outline.map(\n (s) =>\n `${' '.repeat(s.namePath.split('/').length - 1)}${s.startLine}-${s.endLine} ${s.kind} ${s.name} \u2014 ${s.signature}`,\n );\n return text(fitRows(`${path} (${outline.length} symbols)`, rows, args.max_chars ?? 4_000));\n}\n\nasync function codeDefinition(\n raw: Record<string, unknown>,\n ctx: ModuleContext,\n): Promise<ToolResult> {\n const args = z.object(definitionInput).parse(raw);\n const index = await freshIndex(ctx);\n const found = index.definition(args.name_path, args.path);\n if (!found) {\n const near = index.findSymbols(args.name_path.split('/').pop()!, { substring: true, limit: 5 });\n return text(\n `Symbol \"${args.name_path}\" not found.${near.length > 0 ? ` Close matches: ${near.map((s) => s.namePath).join(', ')}` : ''}`,\n );\n }\n const others = index.findSymbols(args.name_path, { limit: 6 }).length - 1;\n const ambiguity =\n others > 0 ? ` (${others} other symbol(s) share this name; pass path= to choose)` : '';\n const header = `${found.path}:${found.startLine}-${found.endLine} ${found.kind} ${found.namePath}${ambiguity}`;\n const numbered = found.body.split('\\n').map((line, i) => `${found.startLine + i}\\t${line}`);\n return text(fitRows(header, numbered, args.max_chars ?? 8_000));\n}\n\nasync function codeReferences(\n raw: Record<string, unknown>,\n ctx: ModuleContext,\n): Promise<ToolResult> {\n const args = z.object(referencesInput).parse(raw);\n const index = await freshIndex(ctx);\n const refs = index.references(args.name_path, 200);\n const definition = index.findSymbols(args.name_path, { limit: 1 })[0];\n const rows = refs.map((r) => `${r.path}:${r.line} ${r.text}`);\n const importers = definition ? index.importersOf(definition.path) : [];\n if (definition && importers.length > 0) {\n rows.push(`importers of ${definition.path}: ${importers.join(', ')}`);\n }\n if (rows.length === 0) return text(`No references to \"${args.name_path}\" found.`);\n return text(\n fitRows(\n `references to ${args.name_path} (${refs.length} lines, lexical)`,\n rows,\n args.max_chars ?? 4_000,\n ),\n );\n}\n\nasync function repoMap(raw: Record<string, unknown>, ctx: ModuleContext): Promise<ToolResult> {\n const args = z.object(repoMapInput).parse(raw);\n const index = await freshIndex(ctx);\n const focus = args.focus?.replace(/^\\.\\//, '');\n const map = index.repoMap({ maxChars: args.max_chars ?? 6_000, ...(focus ? { focus } : {}) });\n return text(map.length > 0 ? map : `No indexed files${focus ? ` under ${focus}` : ''}.`);\n}\n\n/** Points at code_search / code_symbols when the agent reaches for grep, find, cat or a big Read. */\nfunction preToolUse(input: HookInput, ctx: ModuleContext): Promise<HookResult> {\n const nudge = nudgeFor(input.tool_name ?? '', input.tool_input ?? {}, ctx.root);\n if (\n !nudge ||\n !firstTimeInSession(ctx.paths.yandecodeDir, input.session_id ?? 'unknown', nudge.kind)\n ) {\n return Promise.resolve({ kind: 'none' });\n }\n ctx.log('nudge', { kind: nudge.kind, tool: input.tool_name });\n return Promise.resolve({ kind: 'context', text: nudge.text });\n}\n\nexport const runtime: ModuleRuntime = {\n hooks: { PreToolUse: preToolUse },\n tools: {\n code_search: codeSearch,\n code_symbols: codeSymbols,\n code_definition: codeDefinition,\n code_references: codeReferences,\n repo_map: repoMap,\n },\n doctor: async (ctx) => {\n const index = await freshIndex(ctx);\n const stats = index.stats();\n return [\n {\n name: 'code index',\n status: stats.files > 0 ? 'ok' : 'warn',\n detail: `${stats.files} files, ${stats.symbols} symbols, ${stats.chunks} chunks`,\n ...(stats.files > 0 ? {} : { fix: 'no source files found; check .gitignore' }),\n },\n ];\n },\n dispose: () => {\n for (const entry of open.values()) entry.index.close();\n open.clear();\n return Promise.resolve();\n },\n};\n\nexport async function runIndexCommand(cwd: string): Promise<void> {\n const ws = requireWorkspace(cwd);\n const index = await freshIndex(moduleContext(ws, codeModule));\n const report = await index.sync();\n const stats = index.stats();\n process.stdout.write(\n `code index: ${stats.files} files, ${stats.symbols} symbols (+${report.added} ~${report.changed} -${report.removed}) in ${report.durationMs} ms\\n`,\n );\n}\n\nexport async function runSearchCommand(cwd: string, query: string): Promise<void> {\n const ws = requireWorkspace(cwd);\n const result = await codeSearch({ query }, moduleContext(ws, codeModule));\n process.stdout.write(`${result.text}\\n`);\n}\n", "import { mkdirSync, openSync, closeSync } from 'node:fs';\nimport { join } from 'node:path';\n\n/**\n * True the first time `kind` is asked for in a session (a marker file under .yandecode/hints),\n * so a hint is shown once without every hook process opening a database.\n */\nexport function firstTimeInSession(yandecodeDir: string, sessionId: string, kind: string): boolean {\n const dir = join(yandecodeDir, 'hints');\n mkdirSync(dir, { recursive: true });\n const safe = `${sessionId}.${kind}`.replace(/[^\\w.-]/g, '_');\n try {\n closeSync(openSync(join(dir, safe), 'wx'));\n return true;\n } catch {\n return false;\n }\n}\n", "import { statSync } from 'node:fs';\nimport { extname, isAbsolute, join } from 'node:path';\n\nexport interface Nudge {\n /** One hint per kind per session. */\n kind: 'search' | 'read';\n text: string;\n}\n\nconst CODE_EXTENSIONS = new Set([\n '.ts',\n '.tsx',\n '.js',\n '.jsx',\n '.mjs',\n '.cjs',\n '.py',\n '.rs',\n '.go',\n '.java',\n '.kt',\n '.c',\n '.h',\n '.cc',\n '.cpp',\n '.hpp',\n '.cs',\n '.rb',\n '.php',\n '.swift',\n '.scala',\n]);\n/** Files above this size are worth outlining first (~300 lines of code). */\nconst LARGE_FILE_BYTES = 12_000;\n\nconst SEARCH: Nudge = {\n kind: 'search',\n text: 'yandecode: to find where code is defined or handled, `code_search(query)` returns path:line rows with signatures (identifiers, `Class/method`, file fragments or plain words), and `code_references(name)` lists usages \u2014 cheaper than grep/find over source files.',\n};\nconst READ: Nudge = {\n kind: 'read',\n text: 'yandecode: `code_symbols(path)` lists a file\u2019s functions and types with line ranges, and `code_definition(name)` returns just one of them \u2014 read or cat whole source files only when you will edit most of them.',\n};\n\nconst isCode = (path: string): boolean => CODE_EXTENSIONS.has(extname(path).toLowerCase());\n\nfunction segments(command: string): string[] {\n return command\n .replace(/'[^']*'|\"(?:\\\\.|[^\"\\\\])*\"/g, \"''\")\n .split(/&&|\\|\\||;|\\|/)\n .map((s) => s.trim());\n}\n\nfunction bashNudge(command: string): Nudge | null {\n const parts = segments(command);\n if (\n parts.some(\n (s) =>\n /^(grep|egrep|rg|ag|ack|git grep)\\b/.test(s) || /^find\\b.*-(name|path|iname)\\b/.test(s),\n )\n ) {\n return SEARCH;\n }\n // Reading source through the shell: cat/head/tail/sed -n on a code file (arguments are quoted-stripped, so\n // look at the raw command for the file name).\n const reads = /^(cat|head|tail|sed -n|nl|less|more)\\b/;\n if (\n parts.some((s) => reads.test(s)) &&\n [...command.matchAll(/[\\w./-]+\\.\\w+/g)].some((m) => isCode(m[0]))\n ) {\n return READ;\n }\n return null;\n}\n\nfunction readNudge(input: Record<string, unknown>, root: string): Nudge | null {\n const path = input.file_path;\n if (\n typeof path !== 'string' ||\n !isCode(path) ||\n input.offset !== undefined ||\n input.limit !== undefined\n )\n return null;\n const size =\n statSync(isAbsolute(path) ? path : join(root, path), { throwIfNoEntry: false })?.size ?? 0;\n return size > LARGE_FILE_BYTES ? READ : null;\n}\n\n/** The hint for a built-in tool call that a yandecode code tool does better, if any. */\nexport function nudgeFor(tool: string, input: Record<string, unknown>, root: string): Nudge | null {\n if (tool === 'Grep' || tool === 'Glob') return SEARCH;\n if (tool === 'Bash' && typeof input.command === 'string') return bashNudge(input.command);\n if (tool === 'Read') return readNudge(input, root);\n return null;\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["join", "join", "join"]
7
+ }
@@ -0,0 +1,197 @@
1
+ import { createRequire as __yandecodeCreateRequire } from 'node:module';
2
+ const require = __yandecodeCreateRequire(import.meta.url);
3
+ import {
4
+ digest,
5
+ execShell
6
+ } from "./chunk-6J5CZVCJ.js";
7
+ import {
8
+ parseSettings
9
+ } from "./chunk-QCQC73WX.js";
10
+ import {
11
+ checkInput,
12
+ detectChecks,
13
+ qualitySettings
14
+ } from "./chunk-7L6DD2VD.js";
15
+ import {
16
+ external_exports,
17
+ openModuleDb
18
+ } from "./chunk-Y2MIXROU.js";
19
+
20
+ // packages/cli/src/modules/quality/runtime.ts
21
+ import { mkdirSync } from "node:fs";
22
+ import { join, relative } from "node:path";
23
+
24
+ // packages/cli/src/modules/quality/patterns.ts
25
+ import { extname } from "node:path";
26
+ var ext = (...exts) => (path) => exts.includes(extname(path).toLowerCase());
27
+ var JS = ext(".js", ".jsx", ".ts", ".tsx", ".mjs", ".cjs", ".mts", ".cts", ".vue", ".svelte");
28
+ var PY = ext(".py", ".pyi");
29
+ var CODE = (path) => JS(path) || PY(path) || ext(".rb", ".php", ".go", ".java", ".kt", ".rs")(path);
30
+ var PATTERNS = [
31
+ {
32
+ rule: "actions-injection",
33
+ applies: (p) => /(^|\/)\.github\/workflows\/.+\.ya?ml$/.test(p),
34
+ pattern: /run:.*\$\{\{\s*github\.event\.(issue|pull_request|comment|review|review_comment|head_commit|commits|pages)\./,
35
+ advice: 'untrusted GitHub event data interpolated into a run: step allows command injection; pass it through env: and quote "$VAR"'
36
+ },
37
+ {
38
+ rule: "eval",
39
+ applies: CODE,
40
+ pattern: /(^|[^\w.])(eval|new Function)\s*\(/,
41
+ advice: "dynamic code evaluation executes whatever the input contains; parse the data instead"
42
+ },
43
+ {
44
+ rule: "shell-injection",
45
+ applies: CODE,
46
+ pattern: /\b(exec|execSync)\s*\(\s*`[^`]*\$\{|shell\s*=\s*True|os\.system\s*\(\s*f?["']|child_process.*\bshell:\s*true/,
47
+ advice: "building a shell command from variables allows injection; use execFile/spawn with an argument array (subprocess.run([...]) in Python)"
48
+ },
49
+ {
50
+ rule: "html-injection",
51
+ applies: JS,
52
+ pattern: /\.innerHTML\s*=|\.outerHTML\s*=|dangerouslySetInnerHTML|document\.write\s*\(/,
53
+ advice: "raw HTML insertion enables XSS; render text, or sanitize with a vetted library first"
54
+ },
55
+ {
56
+ rule: "sql-injection",
57
+ applies: CODE,
58
+ pattern: /`\s*(SELECT|INSERT|UPDATE|DELETE)\b[^`]*\$\{|["'](SELECT|INSERT|UPDATE|DELETE)\b[^"']*["']\s*(\+|%|\.format\()/i,
59
+ advice: "SQL built by string concatenation/interpolation is injectable; use parameters/placeholders"
60
+ },
61
+ {
62
+ rule: "unsafe-deserialization",
63
+ applies: PY,
64
+ pattern: /pickle\.loads?\s*\(|yaml\.unsafe_load\s*\(|yaml\.load\s*\((?![^)]*SafeLoader)|torch\.load\s*\((?![^)]*weights_only\s*=\s*True)/,
65
+ advice: "this deserializer can execute arbitrary code from its input; use json / yaml.safe_load / weights_only=True"
66
+ },
67
+ {
68
+ rule: "tls-disabled",
69
+ applies: CODE,
70
+ pattern: /rejectUnauthorized\s*:\s*false|NODE_TLS_REJECT_UNAUTHORIZED\s*=\s*['"]?0|verify\s*=\s*False|InsecureSkipVerify\s*:\s*true/,
71
+ advice: "certificate verification is disabled, allowing man-in-the-middle attacks; configure the CA instead"
72
+ },
73
+ {
74
+ rule: "weak-hash",
75
+ applies: CODE,
76
+ pattern: /createHash\(\s*['"](md5|sha1)['"]\s*\)|hashlib\.(md5|sha1)\s*\(/,
77
+ advice: "MD5/SHA-1 are broken for security use; use SHA-256+ (or scrypt/argon2 for passwords)"
78
+ }
79
+ ];
80
+ function scanEdit(path, content) {
81
+ const posix = path.replace(/\\/g, "/");
82
+ return PATTERNS.filter((p) => p.applies(posix) && p.pattern.test(content)).map((p) => ({
83
+ rule: p.rule,
84
+ advice: p.advice
85
+ }));
86
+ }
87
+
88
+ // packages/cli/src/modules/quality/runtime.ts
89
+ var PER_FAILURE_CHARS = 1500;
90
+ var MIGRATIONS = [
91
+ "CREATE TABLE warned (session_id TEXT NOT NULL, path TEXT NOT NULL, rule TEXT NOT NULL, PRIMARY KEY (session_id, path, rule));"
92
+ ];
93
+ var dbs = /* @__PURE__ */ new Map();
94
+ function dbFor(ctx) {
95
+ let db = dbs.get(ctx.root);
96
+ if (!db) {
97
+ mkdirSync(ctx.paths.yandecodeDir, { recursive: true });
98
+ db = openModuleDb(join(ctx.paths.yandecodeDir, "quality.db"), MIGRATIONS);
99
+ dbs.set(ctx.root, db);
100
+ }
101
+ return db;
102
+ }
103
+ async function qualityCheck(raw, ctx) {
104
+ const args = external_exports.object(checkInput).parse(raw);
105
+ const settings = parseSettings("quality", qualitySettings, ctx.settings);
106
+ const checks = detectChecks(ctx.root, settings.commands).filter(
107
+ (c) => !args.steps || args.steps.includes(c.step)
108
+ );
109
+ if (checks.length === 0) {
110
+ return {
111
+ text: 'quality_check: no checks found. Add scripts (typecheck/lint/test) to package.json or set yandecode.json quality.commands, e.g. {"test": "make test"}.'
112
+ };
113
+ }
114
+ const lines = [];
115
+ let failed = 0;
116
+ for (const check of checks) {
117
+ const result = await execShell(check.command, {
118
+ cwd: ctx.root,
119
+ timeoutMs: (args.timeout_s ?? 600) * 1e3,
120
+ maxBytes: 20 * 1048576
121
+ });
122
+ const seconds = (result.durationMs / 1e3).toFixed(1);
123
+ if (result.exitCode === 0 && !result.timedOut) {
124
+ lines.push(`\u2713 ${check.step} (${check.command}) ${seconds} s`);
125
+ continue;
126
+ }
127
+ failed++;
128
+ const why = result.timedOut ? "timed out" : `exit ${result.exitCode ?? "signal"}`;
129
+ lines.push(`\u2717 ${check.step} (${check.command}) ${why}, ${seconds} s`);
130
+ lines.push(
131
+ digest(result.output.trimEnd(), { maxChars: PER_FAILURE_CHARS }).text.replace(/^/gm, " ")
132
+ );
133
+ }
134
+ return {
135
+ text: [`quality_check: ${checks.length - failed} passed, ${failed} failed`, ...lines].join(
136
+ "\n"
137
+ )
138
+ };
139
+ }
140
+ function onEdit(input, ctx) {
141
+ const settings = parseSettings("quality", qualitySettings, ctx.settings);
142
+ const toolInput = input.tool_input ?? {};
143
+ const path = toolInput.file_path ?? toolInput.notebook_path;
144
+ if (!settings.editWarnings || typeof path !== "string") return Promise.resolve({ kind: "none" });
145
+ const edits = Array.isArray(toolInput.edits) ? toolInput.edits : [];
146
+ const content = [
147
+ toolInput.content,
148
+ toolInput.new_string,
149
+ toolInput.new_source,
150
+ ...edits.map((e) => e.new_string)
151
+ ].filter((v) => typeof v === "string").join("\n");
152
+ const rel = relative(ctx.root, path) || path;
153
+ const insert = dbFor(ctx).prepare(
154
+ "INSERT OR IGNORE INTO warned (session_id, path, rule) VALUES (?, ?, ?)"
155
+ );
156
+ const fresh = scanEdit(rel, content).filter(
157
+ (f) => insert.run(input.session_id ?? "unknown", rel, f.rule).changes === 1
158
+ );
159
+ if (fresh.length === 0) return Promise.resolve({ kind: "none" });
160
+ ctx.log("edit_warning", { path: rel, rules: fresh.map((f) => f.rule) });
161
+ return Promise.resolve({
162
+ kind: "context",
163
+ text: [
164
+ `yandecode quality \u2014 review ${rel}:`,
165
+ ...fresh.map((f) => `- ${f.rule}: ${f.advice}`)
166
+ ].join("\n")
167
+ });
168
+ }
169
+ var runtime = {
170
+ tools: { quality_check: qualityCheck },
171
+ hooks: { PostToolUse: onEdit },
172
+ doctor: (ctx) => {
173
+ const settings = parseSettings("quality", qualitySettings, ctx.settings);
174
+ const checks = detectChecks(ctx.root, settings.commands);
175
+ return Promise.resolve([
176
+ checks.length > 0 ? {
177
+ name: "checks",
178
+ status: "ok",
179
+ detail: checks.map((c) => `${c.step}: ${c.command}`).join("; ")
180
+ } : {
181
+ name: "checks",
182
+ status: "warn",
183
+ detail: "none detected",
184
+ fix: "set quality.commands in yandecode.json"
185
+ }
186
+ ]);
187
+ },
188
+ dispose: () => {
189
+ for (const db of dbs.values()) db.close();
190
+ dbs.clear();
191
+ return Promise.resolve();
192
+ }
193
+ };
194
+ export {
195
+ runtime
196
+ };
197
+ //# sourceMappingURL=runtime-EKHO2JXB.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/modules/quality/runtime.ts", "../../src/modules/quality/patterns.ts"],
4
+ "sourcesContent": ["import { mkdirSync } from 'node:fs';\nimport { join, relative } from 'node:path';\nimport { openModuleDb, type Database } from '@yandecode/core';\nimport { z } from 'zod';\nimport type {\n HookInput,\n HookResult,\n ModuleContext,\n ModuleRuntime,\n ToolResult,\n} from '@cli/modules/contract';\nimport { parseSettings } from '@cli/modules/host';\nimport { digest } from '@cli/shared/digest';\nimport { execShell } from '@cli/shared/exec';\nimport { detectChecks } from '@cli/shared/project-checks';\nimport { checkInput, qualitySettings } from './definition';\nimport { scanEdit } from './patterns';\n\nconst PER_FAILURE_CHARS = 1_500;\nconst MIGRATIONS = [\n 'CREATE TABLE warned (session_id TEXT NOT NULL, path TEXT NOT NULL, rule TEXT NOT NULL, PRIMARY KEY (session_id, path, rule));',\n];\nconst dbs = new Map<string, Database>();\n\nfunction dbFor(ctx: ModuleContext): Database {\n let db = dbs.get(ctx.root);\n if (!db) {\n mkdirSync(ctx.paths.yandecodeDir, { recursive: true });\n db = openModuleDb(join(ctx.paths.yandecodeDir, 'quality.db'), MIGRATIONS);\n dbs.set(ctx.root, db);\n }\n return db;\n}\n\nasync function qualityCheck(raw: Record<string, unknown>, ctx: ModuleContext): Promise<ToolResult> {\n const args = z.object(checkInput).parse(raw);\n const settings = parseSettings('quality', qualitySettings, ctx.settings);\n const checks = detectChecks(ctx.root, settings.commands).filter(\n (c) => !args.steps || args.steps.includes(c.step),\n );\n if (checks.length === 0) {\n return {\n text: 'quality_check: no checks found. Add scripts (typecheck/lint/test) to package.json or set yandecode.json quality.commands, e.g. {\"test\": \"make test\"}.',\n };\n }\n const lines: string[] = [];\n let failed = 0;\n for (const check of checks) {\n const result = await execShell(check.command, {\n cwd: ctx.root,\n timeoutMs: (args.timeout_s ?? 600) * 1000,\n maxBytes: 20 * 1_048_576,\n });\n const seconds = (result.durationMs / 1000).toFixed(1);\n if (result.exitCode === 0 && !result.timedOut) {\n lines.push(`\u2713 ${check.step} (${check.command}) ${seconds} s`);\n continue;\n }\n failed++;\n const why = result.timedOut ? 'timed out' : `exit ${result.exitCode ?? 'signal'}`;\n lines.push(`\u2717 ${check.step} (${check.command}) ${why}, ${seconds} s`);\n lines.push(\n digest(result.output.trimEnd(), { maxChars: PER_FAILURE_CHARS }).text.replace(/^/gm, ' '),\n );\n }\n return {\n text: [`quality_check: ${checks.length - failed} passed, ${failed} failed`, ...lines].join(\n '\\n',\n ),\n };\n}\n\nfunction onEdit(input: HookInput, ctx: ModuleContext): Promise<HookResult> {\n const settings = parseSettings('quality', qualitySettings, ctx.settings);\n const toolInput = input.tool_input ?? {};\n const path = toolInput.file_path ?? toolInput.notebook_path;\n if (!settings.editWarnings || typeof path !== 'string') return Promise.resolve({ kind: 'none' });\n const edits = Array.isArray(toolInput.edits)\n ? (toolInput.edits as { new_string?: unknown }[])\n : [];\n const content = [\n toolInput.content,\n toolInput.new_string,\n toolInput.new_source,\n ...edits.map((e) => e.new_string),\n ]\n .filter((v): v is string => typeof v === 'string')\n .join('\\n');\n const rel = relative(ctx.root, path) || path;\n const insert = dbFor(ctx).prepare(\n 'INSERT OR IGNORE INTO warned (session_id, path, rule) VALUES (?, ?, ?)',\n );\n const fresh = scanEdit(rel, content).filter(\n (f) => insert.run(input.session_id ?? 'unknown', rel, f.rule).changes === 1,\n );\n if (fresh.length === 0) return Promise.resolve({ kind: 'none' });\n ctx.log('edit_warning', { path: rel, rules: fresh.map((f) => f.rule) });\n return Promise.resolve({\n kind: 'context',\n text: [\n `yandecode quality \u2014 review ${rel}:`,\n ...fresh.map((f) => `- ${f.rule}: ${f.advice}`),\n ].join('\\n'),\n });\n}\n\nexport const runtime: ModuleRuntime = {\n tools: { quality_check: qualityCheck },\n hooks: { PostToolUse: onEdit },\n doctor: (ctx) => {\n const settings = parseSettings('quality', qualitySettings, ctx.settings);\n const checks = detectChecks(ctx.root, settings.commands);\n return Promise.resolve([\n checks.length > 0\n ? {\n name: 'checks',\n status: 'ok',\n detail: checks.map((c) => `${c.step}: ${c.command}`).join('; '),\n }\n : {\n name: 'checks',\n status: 'warn',\n detail: 'none detected',\n fix: 'set quality.commands in yandecode.json',\n },\n ]);\n },\n dispose: () => {\n for (const db of dbs.values()) db.close();\n dbs.clear();\n return Promise.resolve();\n },\n};\n", "import { extname } from 'node:path';\n\nexport interface Finding {\n rule: string;\n advice: string;\n}\n\ninterface Pattern {\n rule: string;\n /** File extensions (lowercase, with dot) or a path test. */\n applies: (path: string) => boolean;\n pattern: RegExp;\n advice: string;\n}\n\nconst ext =\n (...exts: string[]) =>\n (path: string): boolean =>\n exts.includes(extname(path).toLowerCase());\nconst JS = ext('.js', '.jsx', '.ts', '.tsx', '.mjs', '.cjs', '.mts', '.cts', '.vue', '.svelte');\nconst PY = ext('.py', '.pyi');\nconst CODE = (path: string): boolean =>\n JS(path) || PY(path) || ext('.rb', '.php', '.go', '.java', '.kt', '.rs')(path);\n\n/**\n * Risky constructs worth a second look right after an edit (ADR-023). Only new content is\n * scanned, and each hit is advice for the agent, not a block.\n */\nconst PATTERNS: readonly Pattern[] = [\n {\n rule: 'actions-injection',\n applies: (p) => /(^|\\/)\\.github\\/workflows\\/.+\\.ya?ml$/.test(p),\n pattern:\n /run:.*\\$\\{\\{\\s*github\\.event\\.(issue|pull_request|comment|review|review_comment|head_commit|commits|pages)\\./,\n advice:\n 'untrusted GitHub event data interpolated into a run: step allows command injection; pass it through env: and quote \"$VAR\"',\n },\n {\n rule: 'eval',\n applies: CODE,\n pattern: /(^|[^\\w.])(eval|new Function)\\s*\\(/,\n advice: 'dynamic code evaluation executes whatever the input contains; parse the data instead',\n },\n {\n rule: 'shell-injection',\n applies: CODE,\n pattern:\n /\\b(exec|execSync)\\s*\\(\\s*`[^`]*\\$\\{|shell\\s*=\\s*True|os\\.system\\s*\\(\\s*f?[\"']|child_process.*\\bshell:\\s*true/,\n advice:\n 'building a shell command from variables allows injection; use execFile/spawn with an argument array (subprocess.run([...]) in Python)',\n },\n {\n rule: 'html-injection',\n applies: JS,\n pattern: /\\.innerHTML\\s*=|\\.outerHTML\\s*=|dangerouslySetInnerHTML|document\\.write\\s*\\(/,\n advice: 'raw HTML insertion enables XSS; render text, or sanitize with a vetted library first',\n },\n {\n rule: 'sql-injection',\n applies: CODE,\n pattern:\n /`\\s*(SELECT|INSERT|UPDATE|DELETE)\\b[^`]*\\$\\{|[\"'](SELECT|INSERT|UPDATE|DELETE)\\b[^\"']*[\"']\\s*(\\+|%|\\.format\\()/i,\n advice:\n 'SQL built by string concatenation/interpolation is injectable; use parameters/placeholders',\n },\n {\n rule: 'unsafe-deserialization',\n applies: PY,\n pattern:\n /pickle\\.loads?\\s*\\(|yaml\\.unsafe_load\\s*\\(|yaml\\.load\\s*\\((?![^)]*SafeLoader)|torch\\.load\\s*\\((?![^)]*weights_only\\s*=\\s*True)/,\n advice:\n 'this deserializer can execute arbitrary code from its input; use json / yaml.safe_load / weights_only=True',\n },\n {\n rule: 'tls-disabled',\n applies: CODE,\n pattern:\n /rejectUnauthorized\\s*:\\s*false|NODE_TLS_REJECT_UNAUTHORIZED\\s*=\\s*['\"]?0|verify\\s*=\\s*False|InsecureSkipVerify\\s*:\\s*true/,\n advice:\n 'certificate verification is disabled, allowing man-in-the-middle attacks; configure the CA instead',\n },\n {\n rule: 'weak-hash',\n applies: CODE,\n pattern: /createHash\\(\\s*['\"](md5|sha1)['\"]\\s*\\)|hashlib\\.(md5|sha1)\\s*\\(/,\n advice: 'MD5/SHA-1 are broken for security use; use SHA-256+ (or scrypt/argon2 for passwords)',\n },\n];\n\nexport function scanEdit(path: string, content: string): Finding[] {\n const posix = path.replace(/\\\\/g, '/');\n return PATTERNS.filter((p) => p.applies(posix) && p.pattern.test(content)).map((p) => ({\n rule: p.rule,\n advice: p.advice,\n }));\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }