<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>Juan Escalada — Dev Log</title><description>A working engineer’s daily log of debugging sessions, feature work and hard-won fixes — building GitProxy in the open.</description><link>https://jescalada.com/</link><language>en</language><item><title>Secrets in argv, and scanners that fail open</title><link>https://jescalada.com/blog/2026-09-03-secrets-in-argv-and-fail-open-scanners/</link><guid isPermaLink="true">https://jescalada.com/blog/2026-09-03-secrets-in-argv-and-fail-open-scanners/</guid><description>A git clone with Authorization on argv is readable from ps, and a scanner that swallows errors is a silent pass. Two fixes from a PR review.</description><pubDate>Thu, 03 Sep 2026 00:00:00 GMT</pubDate><category>security</category><category>git</category><category>GitProxy</category><category>linux</category><category>debugging</category></item><item><title>ENOSPC: System limit for number of file watchers reached</title><link>https://jescalada.com/blog/2026-09-02-enospc-system-limit-file-watchers-reached/</link><guid isPermaLink="true">https://jescalada.com/blog/2026-09-02-enospc-system-limit-file-watchers-reached/</guid><description>ENOSPC: System limit for number of file watchers reached is an inotify limit, not a full disk. Here&apos;s how to find what ate your watchers and raise them.</description><pubDate>Wed, 02 Sep 2026 00:00:00 GMT</pubDate><category>linux</category><category>inotify</category><category>vite</category><category>node</category><category>debugging</category></item><item><title>Exit code 126 in CI: the exec bit git never committed</title><link>https://jescalada.com/blog/2026-09-02-exit-code-126-permission-denied-github-actions/</link><guid isPermaLink="true">https://jescalada.com/blog/2026-09-02-exit-code-126-permission-denied-github-actions/</guid><description>A GitHub Actions step failed with Permission denied and exit code 126. The script was committed as 100644 because core.fileMode was off. Here&apos;s the fix.</description><pubDate>Wed, 02 Sep 2026 00:00:00 GMT</pubDate><category>git</category><category>github-actions</category><category>ci</category><category>bash</category><category>GitProxy</category></item><item><title>Missing files after npm publish: the files allowlist</title><link>https://jescalada.com/blog/2026-09-01-missing-files-after-npm-publish-files-allowlist/</link><guid isPermaLink="true">https://jescalada.com/blog/2026-09-01-missing-files-after-npm-publish-files-allowlist/</guid><description>Files missing from a published npm package: our vite UI build landed outside dist, so the files allowlist dropped it. Here&apos;s how I found and fixed it.</description><pubDate>Tue, 01 Sep 2026 00:00:00 GMT</pubDate><category>npm</category><category>packaging</category><category>vite</category><category>github-actions</category><category>GitProxy</category></item><item><title>Losing this by passing a method as a callback</title><link>https://jescalada.com/blog/2026-08-31-losing-this-passing-method-as-callback/</link><guid isPermaLink="true">https://jescalada.com/blog/2026-08-31-losing-this-passing-method-as-callback/</guid><description>Passing obj.exec into a list strips this, so stateful plugins crash. Bind it, wrap it, or use an arrow field. Here is the GitProxy fix.</description><pubDate>Mon, 31 Aug 2026 00:00:00 GMT</pubDate><category>javascript</category><category>typescript</category><category>this</category><category>GitProxy</category><category>debugging</category></item><item><title>Optional chaining as an accidental deny</title><link>https://jescalada.com/blog/2026-08-30-optional-chaining-accidental-deny/</link><guid isPermaLink="true">https://jescalada.com/blog/2026-08-30-optional-chaining-accidental-deny/</guid><description>p.chains?.includes(name) dropped every plugin that omitted chains. Optional chaining in a filter is an accidental deny; default with ?? instead.</description><pubDate>Sun, 30 Aug 2026 00:00:00 GMT</pubDate><category>javascript</category><category>typescript</category><category>plugins</category><category>GitProxy</category><category>debugging</category></item><item><title>Record&lt;string, T&gt; hid a missing key as defined</title><link>https://jescalada.com/blog/2026-08-29-record-string-t-hides-missing-keys/</link><guid isPermaLink="true">https://jescalada.com/blog/2026-08-29-record-string-t-hides-missing-keys/</guid><description>Record&lt;string, T&gt; types every key as present, so a typo compiled and getChain returned undefined. Thirteen tests failed from one missing key.</description><pubDate>Sat, 29 Aug 2026 00:00:00 GMT</pubDate><category>typescript</category><category>testing</category><category>GitProxy</category><category>debugging</category></item><item><title>How to write a GitProxy plugin: a diff-scanning example</title><link>https://jescalada.com/blog/2026-08-28-how-to-write-gitproxy-plugin-diff-scanning-example/</link><guid isPermaLink="true">https://jescalada.com/blog/2026-08-28-how-to-write-gitproxy-plugin-diff-scanning-example/</guid><description>How to write a GitProxy plugin: a complete diff-scanning example, how to pick the right chain phase, and why a plugin can load and still never run.</description><pubDate>Fri, 28 Aug 2026 00:00:00 GMT</pubDate><category>GitProxy</category><category>plugins</category><category>typescript</category><category>git</category><category>security</category></item><item><title>TypeScript class fields wipe values set in super()</title><link>https://jescalada.com/blog/2026-08-27-typescript-class-fields-wipe-super-assignment/</link><guid isPermaLink="true">https://jescalada.com/blog/2026-08-27-typescript-class-fields-wipe-super-assignment/</guid><description>A subclass field declaration overwrites what the base constructor assigned. useDefineForClassFields is why, and declare is the one-line fix.</description><pubDate>Thu, 27 Aug 2026 00:00:00 GMT</pubDate><category>typescript</category><category>javascript</category><category>classes</category><category>GitProxy</category></item><item><title>Package subpath is not defined by exports</title><link>https://jescalada.com/blog/2026-08-26-package-subpath-not-defined-by-exports/</link><guid isPermaLink="true">https://jescalada.com/blog/2026-08-26-package-subpath-not-defined-by-exports/</guid><description>Package subpath is not defined by exports, plus ts(2307): the file exists, the exports map hides it. Here&apos;s how to import a public type instead.</description><pubDate>Wed, 26 Aug 2026 00:00:00 GMT</pubDate><category>node</category><category>typescript</category><category>npm</category><category>GitProxy</category><category>debugging</category></item><item><title>Cannot find package: ESM bare specifiers in config</title><link>https://jescalada.com/blog/2026-08-25-cannot-find-package-esm-bare-specifier/</link><guid isPermaLink="true">https://jescalada.com/blog/2026-08-25-cannot-find-package-esm-bare-specifier/</guid><description>Cannot find package &apos;plugins&apos; is Node treating a relative path as a package name. Here is the ESM specifier rule, and the one-character fix.</description><pubDate>Tue, 25 Aug 2026 00:00:00 GMT</pubDate><category>node</category><category>esm</category><category>javascript</category><category>GitProxy</category><category>debugging</category></item><item><title>How to design a plugin system for your project</title><link>https://jescalada.com/blog/2026-08-24-how-to-design-plugin-system-your-project/</link><guid isPermaLink="true">https://jescalada.com/blog/2026-08-24-how-to-design-plugin-system-your-project/</guid><description>How to design a plugin system: named phases instead of positions, deny-by-default placement, and the defaults that must live outside your constructor.</description><pubDate>Mon, 24 Aug 2026 00:00:00 GMT</pubDate><category>plugins</category><category>architecture</category><category>typescript</category><category>node</category><category>GitProxy</category></item><item><title>Vitest: vi.mocked(...).mockResolvedValue is not a function</title><link>https://jescalada.com/blog/2026-06-30-vitest-vi-mocked-mockresolvedvalue-not-function/</link><guid isPermaLink="true">https://jescalada.com/blog/2026-06-30-vitest-vi-mocked-mockresolvedvalue-not-function/</guid><description>Vitest 3 test fails with vi.mocked(...).mockResolvedValue is not a function after restoreAllMocks. Here&apos;s how to fix it in one line.</description><pubDate>Tue, 30 Jun 2026 00:00:00 GMT</pubDate><category>vitest</category><category>testing</category><category>mocking</category><category>typescript</category><category>GitProxy</category></item><item><title>Vitest 4 tests pass locally but fail in CI</title><link>https://jescalada.com/blog/2026-06-05-vitest-4-tests-pass-locally-fail-ci/</link><guid isPermaLink="true">https://jescalada.com/blog/2026-06-05-vitest-4-tests-pass-locally-fail-ci/</guid><description>Bumping Vitest from 3 to 4 turned my git-proxy CI red while local stayed green. Stale node_modules, broken class mocks, and port clashes. Here&apos;s how I fixed each.</description><pubDate>Fri, 05 Jun 2026 00:00:00 GMT</pubDate><category>vitest</category><category>testing</category><category>mocking</category><category>ci</category><category>GitProxy</category></item><item><title>AI PR review and security scanning with GitHub Actions</title><link>https://jescalada.com/blog/2026-04-26-ai-pr-review-security-scanning-github-actions/</link><guid isPermaLink="true">https://jescalada.com/blog/2026-04-26-ai-pr-review-security-scanning-github-actions/</guid><description>Build your own GitHub Actions bot that review pull requests with an LLM: PR Description Checker and Security Scanner.</description><pubDate>Sun, 26 Apr 2026 00:00:00 GMT</pubDate><category>github-actions</category><category>ai-code-review</category><category>security</category><category>llm-agents</category><category>GitProxy</category></item><item><title>Auto-triage GitHub issues with an AI agent and Actions</title><link>https://jescalada.com/blog/2026-04-12-auto-triage-github-issues-ai-agent-actions/</link><guid isPermaLink="true">https://jescalada.com/blog/2026-04-12-auto-triage-github-issues-ai-agent-actions/</guid><description>Build a GitHub Actions bot that triages issues and PRs with an LLM: label, dedupe, security-scan, and run it on Claude, GPT, or Gemini. Here&apos;s how I did it.</description><pubDate>Sun, 12 Apr 2026 00:00:00 GMT</pubDate><category>github-actions</category><category>automation</category><category>llm-agents</category><category>litellm</category><category>GitProxy</category></item><item><title>Switching to npm trusted publishers: mind the Node version</title><link>https://jescalada.com/blog/2026-02-01-switching-npm-trusted-publishers-mind-node-version/</link><guid isPermaLink="true">https://jescalada.com/blog/2026-02-01-switching-npm-trusted-publishers-mind-node-version/</guid><description>Moving GitProxy&apos;s npm publish from a token to OIDC trusted publishers took a few lines, except for one thing that kept failing.</description><pubDate>Sun, 01 Feb 2026 00:00:00 GMT</pubDate><category>trusted-publishing</category><category>npm</category><category>github-actions</category><category>oidc</category><category>GitProxy</category></item><item><title>A Vitest toThrow test that misses a JSON.parse error</title><link>https://jescalada.com/blog/2026-01-20-vitest-tothrow-test-misses-json-parse-error/</link><guid isPermaLink="true">https://jescalada.com/blog/2026-01-20-vitest-tothrow-test-misses-json-parse-error/</guid><description>A Vitest test using expect().toThrow() let a JSON.parse SyntaxError escape and fail the run instead of catching it. Here&apos;s why, and the fix.</description><pubDate>Tue, 20 Jan 2026 00:00:00 GMT</pubDate><category>vitest</category><category>testing</category><category>async</category><category>javascript</category><category>GitProxy</category></item><item><title>Moving a Git tag to a newer commit</title><link>https://jescalada.com/blog/2026-01-14-moving-git-tag-newer-commit/</link><guid isPermaLink="true">https://jescalada.com/blog/2026-01-14-moving-git-tag-newer-commit/</guid><description>Moving a Git tag to a newer commit takes a force push, or Git rejects it because the tag already exists. Here&apos;s how, plus the gotcha that bites teammates.</description><pubDate>Wed, 14 Jan 2026 00:00:00 GMT</pubDate><category>git</category><category>git-tag</category><category>git-push</category><category>github</category></item><item><title>Docker EACCES: permission denied, mkdir as a non-root user</title><link>https://jescalada.com/blog/2026-01-09-docker-eacces-permission-denied-mkdir-non-root-user/</link><guid isPermaLink="true">https://jescalada.com/blog/2026-01-09-docker-eacces-permission-denied-mkdir-non-root-user/</guid><description>A containerized Node app failed with EACCES: permission denied, mkdir &apos;./.data&apos; after dropping to a non-root user. Here&apos;s the cause and the fix.</description><pubDate>Fri, 09 Jan 2026 00:00:00 GMT</pubDate><category>docker</category><category>node</category><category>permissions</category><category>GitProxy</category><category>dockerfile</category></item><item><title>Migrating GitProxy&apos;s tests from Mocha and Chai to Vitest</title><link>https://jescalada.com/blog/2025-12-05-migrating-gitproxy-tests-mocha-chai-vitest/</link><guid isPermaLink="true">https://jescalada.com/blog/2025-12-05-migrating-gitproxy-tests-mocha-chai-vitest/</guid><description>How to fix all the ESM mocking errors when moving GitProxy&apos;s test suite from Mocha, Chai, Sinon and proxyquire to Vitest + TypeScript</description><pubDate>Fri, 05 Dec 2025 00:00:00 GMT</pubDate><category>vitest</category><category>mocha</category><category>testing</category><category>typescript</category><category>GitProxy</category></item><item><title>Setting environment variables on Windows npm scripts</title><link>https://jescalada.com/blog/2025-11-05-setting-node-env-npm-scripts-windows/</link><guid isPermaLink="true">https://jescalada.com/blog/2025-11-05-setting-node-env-npm-scripts-windows/</guid><description>Why &quot;NODE_ENV=test&quot; fails on Windows, and the one-line fix with cross-env.</description><pubDate>Wed, 05 Nov 2025 00:00:00 GMT</pubDate><category>debugging</category><category>npm</category><category>Windows</category><category>cross-env</category><category>GitProxy</category><category>open-source</category></item><item><title>From proxyquire to Vitest: fixing &quot;undefined&quot; is not valid JSON</title><link>https://jescalada.com/blog/2025-09-14-proxyquire-vitest-fixing-undefined-not-valid-json/</link><guid isPermaLink="true">https://jescalada.com/blog/2025-09-14-proxyquire-vitest-fixing-undefined-not-valid-json/</guid><description>A git-proxy test failed with &apos;undefined&apos; is not valid JSON after moving from proxyquire to Vitest. Let&apos;s look at the cause and how to fix.</description><pubDate>Sun, 14 Sep 2025 00:00:00 GMT</pubDate><category>vitest</category><category>testing</category><category>async</category><category>javascript</category><category>GitProxy</category></item><item><title>Starting a public debugging log for GitProxy</title><link>https://jescalada.com/blog/2025-09-10-welcome-to-the-log/</link><guid isPermaLink="true">https://jescalada.com/blog/2025-09-10-welcome-to-the-log/</guid><description>I&apos;ve decided to share every debugging session and feature while building GitProxy in the open.</description><pubDate>Wed, 10 Sep 2025 00:00:00 GMT</pubDate><category>meta</category><category>GitProxy</category><category>open-source</category></item></channel></rss>