<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Krystian Safjan's Blog</title><link>https://www.safjan.com/</link><description>Data Scientist and Team Leader writing about Machine Learning, MLOps, and Python</description><atom:link href="https://www.safjan.com/feeds/all.rss.xml" rel="self"/><lastBuildDate>Thu, 09 Apr 2026 00:00:00 +0200</lastBuildDate><item><title>The Real Cost of Model Migration - What Swapping LLMs Actually Requires</title><link>https://www.safjan.com/the-real-cost-of-model-migration-what-swapping-llms-actually-requires/?utm_source=rss&amp;utm_medium=feed&amp;utm_campaign=safjan-blog</link><description>&lt;p&gt;Model deprecations are routine. What they expose underneath - unmeasured quality, model-coupled prompts, unversioned behavior - rarely is. Here's what a migration actually requires, from evaluation to prompt portability to rollout, based on doing this a few times the hard way.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Krystian Safjan</dc:creator><pubDate>Thu, 09 Apr 2026 00:00:00 +0200</pubDate><guid>tag:www.safjan.com,2026-04-09:/the-real-cost-of-model-migration-what-swapping-llms-actually-requires/</guid><category>Machine Learning</category><category>llm-migration</category><category>model-deprecation</category><category>rag-systems</category><category>prompt-engineering</category><category>production-ai</category><category>ai-evaluation</category><category>llmops</category><category>reasoning-models</category><category>dspy</category><category>prompt-optimization</category><category>ai-architecture</category><category>retrieval-augmented-generation</category><category>ai-reliability</category><category>gpt-4o-mini</category><category>model-versioning</category><category>ai-observability</category><category>progressive-rollout</category><category>faithfulness-evaluation</category><category>technical-debt</category><category>ai-engineering</category></item><item><title>The illusion of control in AI-assisted engineering</title><link>https://www.safjan.com/the-illusion-of-control-in-ai-assisted-engineering/?utm_source=rss&amp;utm_medium=feed&amp;utm_campaign=safjan-blog</link><description>&lt;h2 id="the-illusion-of-control-in-ai-assisted-engineering"&gt;The illusion of control in AI-assisted engineering&lt;/h2&gt;
&lt;p&gt;Dashboards are green. Reviews complete on time. Audits pass. And the organization is slowly losing track of what its own systems actually do.&lt;/p&gt;
&lt;p&gt;I keep running into this in teams that use AI-assisted engineering a …&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Krystian Safjan</dc:creator><pubDate>Tue, 03 Mar 2026 00:00:00 +0100</pubDate><guid>tag:www.safjan.com,2026-03-03:/the-illusion-of-control-in-ai-assisted-engineering/</guid><category>Machine Learning</category></item><item><title>Version Your Vectors - Index Versioning as the Missing Layer in RAG Observability and Compliance</title><link>https://www.safjan.com/version-your-vectors-index-versioning-as-the-missing-layer-in-rag/?utm_source=rss&amp;utm_medium=feed&amp;utm_campaign=safjan-blog</link><description>&lt;p&gt;Your RAG answered correctly yesterday. Today, it contradicts itself. Nothing obvious changed — except the index. Retrieval drift is silent, cumulative, and rarely audited. This piece explains how to make it observable and reproducible - what must be versioned beyond vectors, how to enable point-in-time reconstruction, and when lightweight metadata is enough. Includes practical tracing patterns, replay strategies, and a risk-based decision guide for production systems.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Krystian Safjan</dc:creator><pubDate>Thu, 26 Feb 2026 00:00:00 +0100</pubDate><guid>tag:www.safjan.com,2026-02-26:/version-your-vectors-index-versioning-as-the-missing-layer-in-rag/</guid><category>Machine Learning</category><category>rag</category><category>observability</category><category>explainability</category><category>versioning</category><category>eu-ai-act</category><category>vector-database</category><category>data-drift</category><category>compliance</category><category>audit</category></item><item><title>Publishing a Python CLI Tool to Homebrew</title><link>https://www.safjan.com/publishing-python-cli-tool-to-homebrew/?utm_source=rss&amp;utm_medium=feed&amp;utm_campaign=safjan-blog</link><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;Homebrew distribution lets users install your Python CLI with &lt;code&gt;brew install your-tool&lt;/code&gt;. The process: create a GitHub "tap" repository, generate a Ruby formula file, test it, and publish.&lt;/p&gt;
&lt;h2 id="prerequisites"&gt;Prerequisites&lt;/h2&gt;
&lt;p&gt;Your package must be on PyPI with an &lt;code&gt;sdist&lt;/code&gt; (source distribution), not …&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Krystian Safjan</dc:creator><pubDate>Thu, 05 Feb 2026 00:00:00 +0100</pubDate><guid>tag:www.safjan.com,2026-02-05:/publishing-python-cli-tool-to-homebrew/</guid><category>note</category><category>python</category><category>homebrew</category><category>cli</category><category>packaging</category><category>distribution</category><category>macos</category></item><item><title>The limiting factor at work isn't writing code anymore</title><link>https://www.safjan.com/the-limiting-factor-at-work-isnt-writing-code-anymore/?utm_source=rss&amp;utm_medium=feed&amp;utm_campaign=safjan-blog</link><description>&lt;p&gt;In a Hacker News &lt;a href="https://news.ycombinator.com/item?id=46782811"&gt;discussion&lt;/a&gt; on the article &lt;a href="https://www.oneusefulthing.org/p/management-as-ai-superpower"&gt;Management as AI Superpower&lt;/a&gt; by Ethan Mollick, I came across a comment that resonated strongly with a realization I’ve had recently while coding with a factory.ai droid:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The limiting factor at work …&lt;/p&gt;&lt;/blockquote&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Krystian Safjan</dc:creator><pubDate>Wed, 28 Jan 2026 00:00:00 +0100</pubDate><guid>tag:www.safjan.com,2026-01-28:/the-limiting-factor-at-work-isnt-writing-code-anymore/</guid><category>note</category><category>agentic-coding</category><category>vibe-coding</category><category>software-development</category><category>software-project</category></item><item><title>Using MLflow-RAGAS Integration Without Tracing</title><link>https://www.safjan.com/using-mlflowragas-integration-without-tracing/?utm_source=rss&amp;utm_medium=feed&amp;utm_campaign=safjan-blog</link><description>&lt;ul&gt;
&lt;li&gt;&lt;a href="#option-1-static-data-approach-recommended"&gt;Option 1: Static Data Approach (Recommended)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#key-points"&gt;Key Points&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#option-2-simple-predict_fn-no-tracing-decorator"&gt;Option 2: Simple predict_fn (No Tracing Decorator)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#comparison-when-to-use-each-approach"&gt;Comparison: When to Use Each Approach&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#complete-working-example"&gt;Complete Working Example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#recommendation"&gt;Recommendation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can use MLflow's RAGAS integration to calculate evaluation scores and log them to experiments &lt;strong&gt;without&lt;/strong&gt; implementing …&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Krystian Safjan</dc:creator><pubDate>Sun, 11 Jan 2026 00:00:00 +0100</pubDate><guid>tag:www.safjan.com,2026-01-11:/using-mlflowragas-integration-without-tracing/</guid><category>note</category><category>mlflow</category><category>ragas</category><category>RAG-evaluation</category><category>rag-optimization</category><category>rag</category></item><item><title>RAG Evaluation with RAGAS and MLflow - A Practical Guide</title><link>https://www.safjan.com/ragas-mlflow-rag-evaluation-tutorial/?utm_source=rss&amp;utm_medium=feed&amp;utm_campaign=safjan-blog</link><description>&lt;p&gt;A comprehensive tutorial demonstrating RAG evaluation using RAGAS metrics through MLflow integration. Learn to build a minimal RAG pipeline with LangChain, create golden evaluation datasets, and systematically assess retrieval quality using Faithfulness, Context Precision, Context Recall, and Factual Correctness metrics. Supports OpenAI, Azure OpenAI, and Ollama backends.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Krystian Safjan</dc:creator><pubDate>Thu, 08 Jan 2026 00:00:00 +0100</pubDate><guid>tag:www.safjan.com,2026-01-08:/ragas-mlflow-rag-evaluation-tutorial/</guid><category>Data Science</category><category>python</category><category>mlflow</category><category>ragas</category><category>rag</category><category>llm</category><category>evaluation</category><category>langchain</category><category>tutorial</category></item><item><title>Working Faster with Git Worktrees and AI-Based Multi-Workflow Development</title><link>https://www.safjan.com/git-worktrees-ai-multi-workflows/?utm_source=rss&amp;utm_medium=feed&amp;utm_campaign=safjan-blog</link><description>&lt;p&gt;A practical, hands-on guide to turning a single codebase into a multi-workflow environment using Git worktrees, VS Code, and AI coding assistants. The tutorial shows how to isolate experiments, compare results, and speed up refactoring work with agents and Copilot.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Krystian Safjan</dc:creator><pubDate>Fri, 28 Nov 2025 00:00:00 +0100</pubDate><guid>tag:www.safjan.com,2025-11-28:/git-worktrees-ai-multi-workflows/</guid><category>note</category><category>git</category><category>worktrees</category><category>ai-coding</category><category>refactoring</category><category>workflows</category><category>vscode</category><category>productivity</category></item><item><title>Using Git Worktrees as Clean Rooms for AI-Assisted Coding</title><link>https://www.safjan.com/git-worktrees-for-ai-coding/?utm_source=rss&amp;utm_medium=feed&amp;utm_campaign=safjan-blog</link><description>&lt;p&gt;Learn how Git worktrees create isolated environments for AI-assisted coding, allowing you to keep your main development line clean while experimenting with AI suggestions in dedicated branches.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Krystian Safjan</dc:creator><pubDate>Fri, 28 Nov 2025 00:00:00 +0100</pubDate><guid>tag:www.safjan.com,2025-11-28:/git-worktrees-for-ai-coding/</guid><category>note</category><category>git</category><category>workflows</category><category>agents</category><category>ai</category><category>refactoring</category></item><item><title>Avoiding Homebrew Upgrades That Require Sudo on macOS</title><link>https://www.safjan.com/avoid-homebrew-sudo-upgrades/?utm_source=rss&amp;utm_medium=feed&amp;utm_campaign=safjan-blog</link><description>&lt;p&gt;Learn how to manage Homebrew upgrades on macOS to avoid sudo prompts, by differentiating between formulae and casks and using specific commands like &lt;code&gt;--formula&lt;/code&gt;, &lt;code&gt;--cask&lt;/code&gt;, and pinning problematic packages.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Krystian Safjan</dc:creator><pubDate>Fri, 31 Oct 2025 00:00:00 +0100</pubDate><guid>tag:www.safjan.com,2025-10-31:/avoid-homebrew-sudo-upgrades/</guid><category>note</category><category>homebrew</category><category>macos</category><category>automation</category><category>dev-tools</category></item><item><title>Understanding Python Protocols - Structural Subtyping in Practice</title><link>https://www.safjan.com/python-protocols-structural-subtyping/?utm_source=rss&amp;utm_medium=feed&amp;utm_campaign=safjan-blog</link><description>&lt;p&gt;Learn how Python protocols using structural subtyping in PEP 544 allow for flexible, decoupled code by defining shapes through method signatures rather than class inheritance. Explore examples of implementing read-only attributes and optional methods within protocols.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Krystian Safjan</dc:creator><pubDate>Wed, 29 Oct 2025 00:00:00 +0100</pubDate><guid>tag:www.safjan.com,2025-10-29:/python-protocols-structural-subtyping/</guid><category>note</category><category>python</category><category>typing</category><category>protocols</category><category>static-typing</category><category>pep544</category></item><item><title>Evolution of Type Hints in Python — From Comments to Inline Typing and Beyond</title><link>https://www.safjan.com/evolution-of-type-hints-in-python/?utm_source=rss&amp;utm_medium=feed&amp;utm_campaign=safjan-blog</link><description>&lt;p&gt;Learn about the evolution of type hints in Python, from initial comments to modern inline typing and key features introduced in each major version, enabling powerful static type checking with tools like mypy and pyright.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Krystian Safjan</dc:creator><pubDate>Fri, 24 Oct 2025 00:00:00 +0200</pubDate><guid>tag:www.safjan.com,2025-10-24:/evolution-of-type-hints-in-python/</guid><category>note</category><category>python</category><category>typing</category><category>pep484</category><category>static-typing</category><category>mypy</category></item><item><title>Keeping performance results in a separate Git branch using `git checkout --orphan`</title><link>https://www.safjan.com/git-checkout-orphan-gh-pages-performance-results/?utm_source=rss&amp;utm_medium=feed&amp;utm_campaign=safjan-blog</link><description>&lt;p&gt;Learn how to use &lt;code&gt;git checkout --orphan&lt;/code&gt; to create a separate Git branch with no history, ideal for storing performance results or other generated content independently from your codebase. Discover the process and benefits of using orphan branches, including an example GitHub Actions workflow for publishing test results.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Krystian Safjan</dc:creator><pubDate>Fri, 24 Oct 2025 00:00:00 +0200</pubDate><guid>tag:www.safjan.com,2025-10-24:/git-checkout-orphan-gh-pages-performance-results/</guid><category>note</category><category>git</category><category>github-actions</category><category>ci</category><category>deployment</category><category>performance</category></item><item><title>Understanding the Language Server Protocol through a Minimal Working Example</title><link>https://www.safjan.com/language-server-protocol-minimal-example/?utm_source=rss&amp;utm_medium=feed&amp;utm_campaign=safjan-blog</link><description>&lt;p&gt;Learn how the Language Server Protocol standardizes communication between code editors and language servers, enabling editors like VS Code to request features such as diagnostics and completions from a single server, simplifying development workflows.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Krystian Safjan</dc:creator><pubDate>Thu, 16 Oct 2025 00:00:00 +0200</pubDate><guid>tag:www.safjan.com,2025-10-16:/language-server-protocol-minimal-example/</guid><category>note</category><category>language-server-protocol</category><category>vscode</category><category>lsp</category><category>developer-tools</category><category>editors</category><category>programming</category></item><item><title>Using CSS Variables for Dynamic and Reusable Styling</title><link>https://www.safjan.com/css-variables-dynamic-reusable-styling/?utm_source=rss&amp;utm_medium=feed&amp;utm_campaign=safjan-blog</link><description>&lt;p&gt;Learn how to use CSS variables for dynamic and reusable styling, enabling features like interactive UIs, easy theming, and design consistency across components. Discover practical usage examples and best practices while understanding limitations and browser support issues.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Krystian Safjan</dc:creator><pubDate>Tue, 14 Oct 2025 00:00:00 +0200</pubDate><guid>tag:www.safjan.com,2025-10-14:/css-variables-dynamic-reusable-styling/</guid><category>note</category><category>css</category><category>web-development</category><category>front-end</category></item><item><title>Bare Asterisk in Python Function Signatures - Keyword Only Arguments</title><link>https://www.safjan.com/bare-asterisk-in-python-function-signatures/?utm_source=rss&amp;utm_medium=feed&amp;utm_campaign=safjan-blog</link><description>&lt;p&gt;Learn how to use the bare asterisk in Python function signatures to enforce keyword-only arguments, enhancing clarity and preventing argument order bugs in your code.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Krystian Safjan</dc:creator><pubDate>Fri, 10 Oct 2025 00:00:00 +0200</pubDate><guid>tag:www.safjan.com,2025-10-10:/bare-asterisk-in-python-function-signatures/</guid><category>note</category><category>python</category><category>api</category><category>pep</category><category>keyword-arguments</category><category>future-proofing</category></item><item><title>Six Weeks, Real Progress - Exploring Shape Up for Product Work</title><link>https://www.safjan.com/six-weeks-real-progress-exploring-shape-up-for-product-work/?utm_source=rss&amp;utm_medium=feed&amp;utm_campaign=safjan-blog</link><description>&lt;p&gt;Shape Up replaces two-week sprints with six-week cycles, kills the backlog, and lets small teams decide how to build things. Here is when it works, when it doesn't, and what I think about it after digging in.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Krystian Safjan</dc:creator><pubDate>Mon, 06 Oct 2025 00:00:00 +0200</pubDate><guid>tag:www.safjan.com,2025-10-06:/six-weeks-real-progress-exploring-shape-up-for-product-work/</guid><category>Software Development</category><category>agile</category><category>scrum</category><category>shape-up</category><category>basecamp</category><category>37-signals</category><category>shape-up-method</category><category>six-week-cycles</category><category>product-development-process</category><category>agile-alternatives</category><category>autonomous-teams</category><category>shaping-phase</category><category>delivery-rhythm</category><category>software-process-design</category><category>software-development</category></item><item><title>Simpler Parallelism with concurrent.futures</title><link>https://www.safjan.com/concurrent-futures-simpler-parallelism/?utm_source=rss&amp;utm_medium=feed&amp;utm_campaign=safjan-blog</link><description>&lt;p&gt;Learn how to simplify parallel and concurrent programming in Python using &lt;code&gt;concurrent.futures&lt;/code&gt;, including executors for managing threads and processes, and futures for handling task results.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Krystian Safjan</dc:creator><pubDate>Sun, 21 Sep 2025 00:00:00 +0200</pubDate><guid>tag:www.safjan.com,2025-09-21:/concurrent-futures-simpler-parallelism/</guid><category>note</category><category>python</category><category>concurrency</category><category>parallelism</category><category>threading</category><category>multiprocessing</category><category>performance</category></item><item><title>Threading vs Multiprocessing in Python - GIL Implications and Choosing the Right Tool</title><link>https://www.safjan.com/threading-vs-multiprocessing-gil-implications/?utm_source=rss&amp;utm_medium=feed&amp;utm_campaign=safjan-blog</link><description>&lt;p&gt;Learn about the Global Interpreter Lock (GIL) and how threading and multiprocessing in Python differ, with examples showing that multiprocessing is better for CPU-bound tasks due to GIL limitations.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Krystian Safjan</dc:creator><pubDate>Wed, 10 Sep 2025 00:00:00 +0200</pubDate><guid>tag:www.safjan.com,2025-09-10:/threading-vs-multiprocessing-gil-implications/</guid><category>note</category><category>python</category><category>threading</category><category>multiprocessing</category><category>gil</category><category>concurrency</category><category>parallelism</category><category>performance</category></item><item><title>asyncio Basics - async/await and When to Actually Use Them</title><link>https://www.safjan.com/asyncio-basics-async-await-when-to-use/?utm_source=rss&amp;utm_medium=feed&amp;utm_campaign=safjan-blog</link><description>&lt;p&gt;Learn how &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; enables efficient concurrent programming by handling I/O waits without blocking, and discover various ways to run tasks concurrently, manage context managers, and handle timeouts.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Krystian Safjan</dc:creator><pubDate>Tue, 09 Sep 2025 00:00:00 +0200</pubDate><guid>tag:www.safjan.com,2025-09-09:/asyncio-basics-async-await-when-to-use/</guid><category>note</category><category>python</category><category>asyncio</category><category>concurrency</category><category>async-await</category><category>io-bound</category><category>performance</category></item><item><title>Replacing Makefile with Invoke for Cross-Platform Python Tasks</title><link>https://www.safjan.com/replacing-makefile-with-invoke-for-crossplatform-python-tasks/?utm_source=rss&amp;utm_medium=feed&amp;utm_campaign=safjan-blog</link><description>&lt;p&gt;Learn how switching from Make to Invoke improves cross-platform compatibility for Python project tasks, ensuring consistent behavior across macOS, Linux, and Windows.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Krystian Safjan</dc:creator><pubDate>Thu, 14 Aug 2025 00:00:00 +0200</pubDate><guid>tag:www.safjan.com,2025-08-14:/replacing-makefile-with-invoke-for-crossplatform-python-tasks/</guid><category>note</category><category>makefile</category><category>cross-platform-build</category><category>python</category><category>invoke</category><category>task-automation</category><category>developer-experience</category><category>windows</category><category>macos</category><category>linux</category><category>team-collaboration</category><category>build-tools</category><category>portable-scripts</category></item><item><title>Using OpenAI Python SDK with Local Ollama Models (and When to Opt for Alternatives)</title><link>https://www.safjan.com/openai-python-sdk-with-local-ollama-models-and-alternatives/?utm_source=rss&amp;utm_medium=feed&amp;utm_campaign=safjan-blog</link><description>&lt;p&gt;Learn how to use the official &lt;code&gt;openai&lt;/code&gt; Python package with local Ollama models and when it's better to opt for LiteLLM as a more unified alternative.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Krystian Safjan</dc:creator><pubDate>Tue, 29 Jul 2025 00:00:00 +0200</pubDate><guid>tag:www.safjan.com,2025-07-29:/openai-python-sdk-with-local-ollama-models-and-alternatives/</guid><category>note</category><category>openai</category><category>openai-sdk</category><category>ollama</category><category>litellm</category><category>langchain</category><category>llama-index</category><category>guidance</category><category>instructor</category></item><item><title>Building a Multi-Notebook Report with Quarto</title><link>https://www.safjan.com/building-a-multinotebook-report-with-quarto/?utm_source=rss&amp;utm_medium=feed&amp;utm_campaign=safjan-blog</link><description>&lt;p&gt;Learn how to split a large Jupyter notebook into multiple notebooks and combine them into a cohesive report using Quarto's book project functionality for HTML, PDF, or EPUB formats.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Krystian Safjan</dc:creator><pubDate>Wed, 23 Jul 2025 00:00:00 +0200</pubDate><guid>tag:www.safjan.com,2025-07-23:/building-a-multinotebook-report-with-quarto/</guid><category>note</category><category>quarto</category><category>jupyter-notebooks</category><category>nbconvert</category><category>reporting</category><category>experiment-management</category><category>research</category><category>research-report</category></item><item><title>Downgrade or Upgrade Your Python Version with uv</title><link>https://www.safjan.com/downgrade-or-upgrade-your-python-version-with-uv/?utm_source=rss&amp;utm_medium=feed&amp;utm_campaign=safjan-blog</link><description>&lt;p&gt;Learn how to downgrade or upgrade your project’s Python version using the &lt;code&gt;uv&lt;/code&gt; tool, including steps for installing, pinning, and recreating your virtual environment.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Krystian Safjan</dc:creator><pubDate>Thu, 26 Jun 2025 00:00:00 +0200</pubDate><guid>tag:www.safjan.com,2025-06-26:/downgrade-or-upgrade-your-python-version-with-uv/</guid><category>note</category><category>uv</category><category>python-version</category><category>python-dependencies</category><category>python-upgrade</category><category>python-downgrade</category><category>python-version</category></item><item><title>Beyond Coverage - Building Truly Complete Test Suites with GitHub Copilot</title><link>https://www.safjan.com/beyond-coverage-building-truly-complete-test-suites-with-github-copilot/?utm_source=rss&amp;utm_medium=feed&amp;utm_campaign=safjan-blog</link><description>&lt;p&gt;This article explores how to move beyond simplistic code coverage metrics to build truly comprehensive test suites using GitHub Copilot. Drawing from practical experience, I demonstrate how AI-assisted testing can identify behavioral gaps, validate API contracts, generate maintainable tests, and address flaky tests - ultimately creating a sustainable quality assurance strategy focused on behaviors rather than coverage percentages. Learn specific techniques for behavioral auditing, integration testing, and continuous quality monitoring that have transformed our approach to software reliability.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Krystian Safjan</dc:creator><pubDate>Sun, 15 Jun 2025 00:00:00 +0200</pubDate><guid>tag:www.safjan.com,2025-06-15:/beyond-coverage-building-truly-complete-test-suites-with-github-copilot/</guid><category>Software Development</category><category>github-copilot</category><category>test-coverage</category><category>test-automation</category><category>code-quality</category><category>automated-testing</category><category>integration-testing</category><category>flaky-tests</category><category>ci-cd</category><category>quality-assurance</category><category>behavior-driven-testing</category></item><item><title>Understanding Python's `copy` vs `deepcopy` - When to Use Each</title><link>https://www.safjan.com/understanding-pythons-copy-vs-deepcopy-when-to-use-each/?utm_source=rss&amp;utm_medium=feed&amp;utm_campaign=safjan-blog</link><description>&lt;p&gt;Learn when to use &lt;code&gt;copy.copy()&lt;/code&gt; for shallow copying and &lt;code&gt;copy.deepcopy()&lt;/code&gt; for deep copying in Python, understanding their differences and typical use cases.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Krystian Safjan</dc:creator><pubDate>Thu, 20 Mar 2025 00:00:00 +0100</pubDate><guid>tag:www.safjan.com,2025-03-20:/understanding-pythons-copy-vs-deepcopy-when-to-use-each/</guid><category>note</category><category>python</category><category>python-copy</category><category>deepcopy</category><category>mutable</category><category>immutable</category><category>nested-objects</category></item><item><title>Tracking Down zsh Alias Plugin Sources</title><link>https://www.safjan.com/tracking-down-zsh-alias-plugin-sources/?utm_source=rss&amp;utm_medium=feed&amp;utm_campaign=safjan-blog</link><description>&lt;p&gt;Learn how to trace and identify the source of zsh aliases defined by plugins using verbose tracing and grep, enabling you to pinpoint exactly where custom aliases are created.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Krystian Safjan</dc:creator><pubDate>Fri, 28 Feb 2025 00:00:00 +0100</pubDate><guid>tag:www.safjan.com,2025-02-28:/tracking-down-zsh-alias-plugin-sources/</guid><category>note</category><category>til</category><category>zsh</category><category>zsh-alias</category><category>alias</category></item><item><title>Guide to Managing VS Code Keyboard Shortcuts</title><link>https://www.safjan.com/managing-vs-code-keyboard-shortcuts-a-complete-guide/?utm_source=rss&amp;utm_medium=feed&amp;utm_campaign=safjan-blog</link><description>&lt;p&gt;Learn how VS Code handles context-dependent keyboard shortcuts, resolve conflicts using the Keyboard Shortcuts editor, and customize them for efficient coding.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Krystian Safjan</dc:creator><pubDate>Tue, 11 Feb 2025 00:00:00 +0100</pubDate><guid>tag:www.safjan.com,2025-02-11:/managing-vs-code-keyboard-shortcuts-a-complete-guide/</guid><category>note</category><category>vscode</category><category>keybindings</category><category>personalization</category><category>customization</category></item><item><title>Simple In-Memory Knowledge Graphs for Quick Graph Querying</title><link>https://www.safjan.com/simple-inmemory-knowledge-graphs-for-quick-graph-querying/?utm_source=rss&amp;utm_medium=feed&amp;utm_campaign=safjan-blog</link><description>&lt;p&gt;As developers, we often reach for full-scale graph databases when simpler solutions would suffice. When your knowledge graph is modest in size, keeping it in memory can be both efficient and practical. Let's explore some powerful tools that make this approach work beautifully.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Krystian Safjan</dc:creator><pubDate>Thu, 16 Jan 2025 00:00:00 +0100</pubDate><guid>tag:www.safjan.com,2025-01-16:/simple-inmemory-knowledge-graphs-for-quick-graph-querying/</guid><category>Howto</category><category>graph</category><category>knowledge-graph</category><category>query</category><category>networkx</category><category>neo4j</category><category>rdflib</category><category>SPARQL</category></item><item><title>Quick Ways to Disable GitHub Actions Workflows Without Deletion</title><link>https://www.safjan.com/quick-ways-to-disable-github-actions-workflows-without-deletion/?utm_source=rss&amp;utm_medium=feed&amp;utm_campaign=safjan-blog</link><description>&lt;p&gt;Learn three quick methods to temporarily disable GitHub Actions workflows without deleting them, including commenting out code, using manual triggers, and adding conditional logic.&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Krystian Safjan</dc:creator><pubDate>Thu, 03 Oct 2024 00:00:00 +0200</pubDate><guid>tag:www.safjan.com,2024-10-03:/quick-ways-to-disable-github-actions-workflows-without-deletion/</guid><category>note</category><category>github</category><category>github-actions</category><category>workflow</category><category>ci</category><category>yaml</category></item></channel></rss>