{
  "version": "https://jsonfeed.org/version/1.1",
  "title": "Tim Stacey — Field notes",
  "description": "Field notes on testing and quality engineering by Tim Stacey.",
  "home_page_url": "https://tim.sillysamoyed.com/blog",
  "feed_url": "https://tim.sillysamoyed.com/feed.json",
  "authors": [
    {
      "name": "Tim Stacey",
      "url": "https://tim.sillysamoyed.com"
    }
  ],
  "items": [
    {
      "id": "https://tim.sillysamoyed.com/blog/internet-runs-on-remote-work",
      "url": "https://tim.sillysamoyed.com/blog/internet-runs-on-remote-work",
      "title": "The Internet Runs on Remote Work. Your CEO Says It Doesn't Work",
      "summary": "The largest engineering projects in history are distributed by design, yet executives keep insisting distributed work fails. What the RTO research, the real estate money trail, and one Australian policy contradiction actually show.",
      "date_published": "2026-07-17T00:00:00.000Z",
      "tags": [
        "RemoteWork",
        "RegionalAustralia",
        "OpenSource",
        "TestAutomation",
        "FutureOfWork"
      ]
    },
    {
      "id": "https://tim.sillysamoyed.com/blog/slack-agentic-e2e-testing-stack",
      "url": "https://tim.sillysamoyed.com/blog/slack-agentic-e2e-testing-stack",
      "title": "Where Slack Put AI Agents in Its E2E Testing Stack",
      "summary": "Slack ran more than 200 end-to-end workflows through AI agents to map where intent-driven tests beat brittle scripts and where the price per run keeps scripts in charge.",
      "date_published": "2026-07-15T00:00:00.000Z",
      "tags": [
        "TestAutomation",
        "Playwright",
        "AgenticTesting",
        "E2ETesting",
        "AI"
      ]
    },
    {
      "id": "https://tim.sillysamoyed.com/blog/cucumber-test-script-costume",
      "url": "https://tim.sillysamoyed.com/blog/cucumber-test-script-costume",
      "title": "Your Cucumber Suite Is a Test Script in a Plain-English Costume",
      "summary": "The value in BDD lives in the conversation before the code, not the .feature file; a Cucumber suite that skips that conversation becomes a brittle test script wearing plain English.",
      "date_published": "2026-07-13T00:00:00.000Z",
      "tags": [
        "TestAutomation",
        "BDD",
        "Cucumber",
        "SDET",
        "QualityEngineering"
      ]
    },
    {
      "id": "https://tim.sillysamoyed.com/blog/k6-closed-vs-open-load-models",
      "url": "https://tim.sillysamoyed.com/blog/k6-closed-vs-open-load-models",
      "title": "Two k6 Load Models Measure Two Different Systems",
      "summary": "A closed-model k6 test eases off the moment the server slows; an open-model test holds the request rate and shows you the tail your users will hit.",
      "date_published": "2026-07-09T00:00:00.000Z",
      "tags": [
        "k6",
        "PerformanceTesting",
        "LoadTesting",
        "Grafana",
        "CoordinatedOmission"
      ]
    },
    {
      "id": "https://tim.sillysamoyed.com/blog/ci-ai-agent-standing-credential",
      "url": "https://tim.sillysamoyed.com/blog/ci-ai-agent-standing-credential",
      "title": "Your CI's AI agent was running on a standing credential",
      "summary": "Running Copilot CLI in GitHub Actions used to need a stored personal access token; the CLI now reads the run built-in GITHUB_TOKEN, a credential that expires with the job.",
      "date_published": "2026-07-07T00:00:00.000Z",
      "tags": [
        "GitHubActions",
        "DevSecOps",
        "CICD",
        "Copilot",
        "DevOps"
      ]
    },
    {
      "id": "https://tim.sillysamoyed.com/blog/flake-rate-metric-quarantine-list",
      "url": "https://tim.sillysamoyed.com/blog/flake-rate-metric-quarantine-list",
      "title": "Let a flake-rate metric build your quarantine list",
      "summary": "A hand-kept flaky-test list goes stale the day you save it. Score each test flake rate in Prometheus and a query keeps the quarantine list current for you.",
      "date_published": "2026-07-05T00:00:00.000Z",
      "tags": [
        "FlakyTests",
        "TestAutomation",
        "CICD",
        "Prometheus",
        "TestObservability"
      ]
    },
    {
      "id": "https://tim.sillysamoyed.com/blog/k6-2-1-feature-flags",
      "url": "https://tim.sillysamoyed.com/blog/k6-2-1-feature-flags",
      "title": "k6 2.1 Ships a Feature-Flag System for Experimental Behavior",
      "summary": "k6 2.1 adds a feature-flag system: opt into experimental behavior with --features, list what exists with k6 features, and switch trend metrics to native Prometheus histograms.",
      "date_published": "2026-07-02T00:00:00.000Z",
      "tags": [
        "k6",
        "PerformanceTesting",
        "LoadTesting",
        "Grafana",
        "Observability"
      ]
    },
    {
      "id": "https://tim.sillysamoyed.com/blog/playwright-1-61-passkey-testing",
      "url": "https://tim.sillysamoyed.com/blog/playwright-1-61-passkey-testing",
      "title": "Playwright 1.61 Tests Passkey Logins Without a Hardware Key",
      "summary": "Playwright 1.61 ships a virtual authenticator that registers passkeys in-test, so the passkey login button gets E2E coverage without a security key.",
      "date_published": "2026-06-30T00:00:00.000Z",
      "tags": [
        "Playwright",
        "TestAutomation",
        "WebAuthn",
        "Passkeys",
        "QA"
      ]
    },
    {
      "id": "https://tim.sillysamoyed.com/blog/checkout-v7-refuses-pwn-request",
      "url": "https://tim.sillysamoyed.com/blog/checkout-v7-refuses-pwn-request",
      "title": "Checkout v7 refuses the pwn request by default",
      "summary": "actions/checkout v7 refuses to fetch fork pull request code under pull_request_target, closing the most copied half of the pwn request attack.",
      "date_published": "2026-06-25T00:00:00.000Z",
      "tags": [
        "GitHubActions",
        "CICD",
        "DevSecOps",
        "SupplyChainSecurity",
        "DevOps"
      ]
    },
    {
      "id": "https://tim.sillysamoyed.com/blog/pr-title-ran-shell-commands",
      "url": "https://tim.sillysamoyed.com/blog/pr-title-ran-shell-commands",
      "title": "A pull request title ran shell commands in Nx's pipeline",
      "summary": "A PR title carried shell commands, a run step echoed it, and the runner obeyed. Bind untrusted input to an env var and quote it.",
      "date_published": "2026-06-25T00:00:00.000Z",
      "tags": [
        "GitHubActions",
        "CICD",
        "DevSecOps",
        "SupplyChainSecurity",
        "DevOps"
      ]
    },
    {
      "id": "https://tim.sillysamoyed.com/blog/drop-postman-http-files",
      "url": "https://tim.sillysamoyed.com/blog/drop-postman-http-files",
      "title": "Your API requests belong in Git, not Postman's cloud",
      "summary": "A private Postman collection does two jobs badly. Send the quick check to cURL and a .http file, the endpoint tests to Playwright, and let git hold both.",
      "date_published": "2026-06-24T00:00:00.000Z",
      "tags": [
        "APITesting",
        "Playwright",
        "DeveloperExperience",
        "cURL",
        "SoftwareDevelopment"
      ]
    },
    {
      "id": "https://tim.sillysamoyed.com/blog/stop-seeding-from-the-login-form",
      "url": "https://tim.sillysamoyed.com/blog/stop-seeding-from-the-login-form",
      "title": "Stop seeding your Playwright suite from the login form",
      "summary": "Drive the login form to seed every test and one selector change reddens the whole suite. Authenticate through the API and keep one test on the form.",
      "date_published": "2026-06-18T00:00:00.000Z",
      "tags": [
        "Playwright",
        "TestAutomation",
        "APITesting",
        "CICD",
        "QA"
      ]
    },
    {
      "id": "https://tim.sillysamoyed.com/blog/coverage-gate-rewards-empty-tests",
      "url": "https://tim.sillysamoyed.com/blog/coverage-gate-rewards-empty-tests",
      "title": "Your coverage gate rewards tests that assert nothing",
      "summary": "Line coverage counts execution, not checking. A test that runs your code and asserts nothing still passes an 85 percent gate.",
      "date_published": "2026-06-16T00:00:00.000Z",
      "tags": [
        "TestAutomation",
        "CodeCoverage",
        "MutationTesting",
        "SoftwareTesting",
        "CICD"
      ]
    },
    {
      "id": "https://tim.sillysamoyed.com/blog/github-merge-queue-five-steps",
      "url": "https://tim.sillysamoyed.com/blog/github-merge-queue-five-steps",
      "title": "Five steps to a GitHub merge queue that does not stall",
      "summary": "A merge queue tests each PR against the ones ahead of it before it lands. Five setup steps keep it moving instead of stalling the day you turn it on.",
      "date_published": "2026-06-14T00:00:00.000Z",
      "tags": [
        "GitHubActions",
        "CICD",
        "MergeQueue",
        "DevOps",
        "DeveloperExperience"
      ]
    },
    {
      "id": "https://tim.sillysamoyed.com/blog/gitlab-native-secrets-manager",
      "url": "https://tim.sillysamoyed.com/blog/gitlab-native-secrets-manager",
      "title": "GitLab 19.0 moves the secrets manager into the pipeline",
      "summary": "GitLab 19.0 bundles OpenBao as a native secrets store, so you stop running a standalone Vault just to feed your pipelines.",
      "date_published": "2026-06-11T00:00:00.000Z",
      "tags": [
        "GitLab",
        "CICD",
        "DevSecOps",
        "SecretsManagement",
        "DevOps"
      ]
    },
    {
      "id": "https://tim.sillysamoyed.com/blog/test-health-ci-logs-vs-observability",
      "url": "https://tim.sillysamoyed.com/blog/test-health-ci-logs-vs-observability",
      "title": "Where Test Health Belongs: CI Logs or an Observability Backend",
      "summary": "Your suite emits pass rate and flake count every run, then buries them in a CI log nobody scrolls; export them over OTLP and a dashboard catches the rot.",
      "date_published": "2026-06-09T00:00:00.000Z",
      "tags": [
        "TestAutomation",
        "OpenTelemetry",
        "TestObservability",
        "CICD",
        "DevOps"
      ]
    },
    {
      "id": "https://tim.sillysamoyed.com/blog/retries-hide-real-bugs",
      "url": "https://tim.sillysamoyed.com/blog/retries-hide-real-bugs",
      "title": "Retrying a flaky test deletes the evidence of a real bug",
      "summary": "A bug that fails one run in four passes CI 99.6 percent of the time under three retries. Quarantine the test instead and keep the signal.",
      "date_published": "2026-06-07T00:00:00.000Z",
      "tags": [
        "TestAutomation",
        "FlakyTests",
        "CICD",
        "SoftwareTesting",
        "DevOps"
      ]
    },
    {
      "id": "https://tim.sillysamoyed.com/blog/github-actions-cache-strategy",
      "url": "https://tim.sillysamoyed.com/blog/github-actions-cache-strategy",
      "title": "Three caching changes that take 80% off a GitHub Actions build",
      "summary": "A cached ~/.npm drops a cold Node install from four minutes to thirty seconds, and two more cache changes take the rest of the pipeline down with it.",
      "date_published": "2026-06-04T00:00:00.000Z",
      "tags": [
        "GitHubActions",
        "CICD",
        "DevOps",
        "SoftwareDevelopment",
        "TestAutomation"
      ]
    },
    {
      "id": "https://tim.sillysamoyed.com/blog/resume-site-behind-460-tests",
      "url": "https://tim.sillysamoyed.com/blog/resume-site-behind-460-tests",
      "title": "My resume site ships behind 460 tests",
      "summary": "I set the direction and Claude Code wrote the code and the tests; 247 unit tests and 213 browser tests are how I trust a site I never hand-wrote.",
      "date_published": "2026-06-04T00:00:00.000Z",
      "tags": [
        "Astro",
        "StaticSite",
        "Playwright",
        "ContinuousIntegration",
        "TestAutomation"
      ]
    },
    {
      "id": "https://tim.sillysamoyed.com/blog/github-actions-parallel-steps",
      "url": "https://tim.sillysamoyed.com/blog/github-actions-parallel-steps",
      "title": "GitHub Actions parallel steps and the matrix jobs you can retire",
      "summary": "Three matrix jobs for lint, type-check, and unit tests pay three runner boots and an artifact handoff for concurrency that parallel steps fold back into one job.",
      "date_published": "2026-06-02T00:00:00.000Z",
      "tags": [
        "GitHubActions",
        "CICD",
        "DevOps",
        "TestAutomation",
        "SoftwareDevelopment"
      ]
    },
    {
      "id": "https://tim.sillysamoyed.com/blog/contract-testing-vs-e2e",
      "url": "https://tim.sillysamoyed.com/blog/contract-testing-vs-e2e",
      "title": "Contract Testing vs End-to-End: Where Integration Bugs Belong",
      "summary": "A contract test catches a renamed field in seconds; a 20-minute E2E suite catches it after booting six services. Put each test where it earns its minutes.",
      "date_published": "2026-06-01T00:00:00.000Z",
      "tags": [
        "ContractTesting",
        "Microservices",
        "APITesting",
        "TestAutomation",
        "CICD"
      ]
    },
    {
      "id": "https://tim.sillysamoyed.com/blog/k6-script-authoring-live-telemetry",
      "url": "https://tim.sillysamoyed.com/blog/k6-script-authoring-live-telemetry",
      "title": "k6 Script Authoring calibrates load tests to live traffic",
      "summary": "Grafana Assistant reads your telemetry, finds endpoints by real RPS and p95, and generates a k6 script that inherits that profile.",
      "date_published": "2026-05-26T00:00:00.000Z",
      "tags": [
        "PerformanceTesting",
        "k6",
        "Grafana",
        "TestAutomation",
        "DevOps"
      ]
    },
    {
      "id": "https://tim.sillysamoyed.com/blog/playwright-ai-test-explosion",
      "url": "https://tim.sillysamoyed.com/blog/playwright-ai-test-explosion",
      "title": "When AI can write every test, what ships to CI is the job",
      "summary": "AI-generated Playwright tests flake under 1.5%. The new problem is test explosion, and coverage intent is still yours to define.",
      "date_published": "2026-05-24T00:00:00.000Z",
      "tags": [
        "Playwright",
        "TestAutomation",
        "SoftwareTesting",
        "AI",
        "CICD"
      ]
    },
    {
      "id": "https://tim.sillysamoyed.com/blog/github-copilot-fixes-failing-ci",
      "url": "https://tim.sillysamoyed.com/blog/github-copilot-fixes-failing-ci",
      "title": "One click to fix a failing GitHub Actions run",
      "summary": "Fix with Copilot puts a cloud agent on the failure: it investigates, pushes a fix, reruns CI, and tags you for review.",
      "date_published": "2026-05-21T00:00:00.000Z",
      "tags": [
        "GitHubActions",
        "CICD",
        "TestAutomation",
        "DevOps",
        "SoftwareDevelopment",
        "Playwright"
      ]
    },
    {
      "id": "https://tim.sillysamoyed.com/blog/ai-cicd-adoption-gap",
      "url": "https://tim.sillysamoyed.com/blog/ai-cicd-adoption-gap",
      "title": "90% use AI in the IDE; the pipeline is another story",
      "summary": "JetBrains data: daily AI in the editor, almost none in CI/CD. The trust gap closes when AI reduces noise instead of adding it.",
      "date_published": "2026-05-19T00:00:00.000Z",
      "tags": [
        "CICD",
        "DevOps",
        "TestAutomation",
        "SoftwareDevelopment",
        "AITesting"
      ]
    },
    {
      "id": "https://tim.sillysamoyed.com/blog/bitbucket-agentic-pipelines",
      "url": "https://tim.sillysamoyed.com/blog/bitbucket-agentic-pipelines",
      "title": "Bitbucket Agentic Pipelines automates the chores",
      "summary": "Define an agent block in bitbucket-pipelines.yml, scope it, tie it to an event. It drafts the docs and the coverage gaps; you review.",
      "date_published": "2026-05-17T00:00:00.000Z",
      "tags": [
        "Bitbucket",
        "DevOps",
        "CICD",
        "TestAutomation",
        "SoftwareDevelopment",
        "Playwright"
      ]
    },
    {
      "id": "https://tim.sillysamoyed.com/blog/playwright-1-59-healer-agent-ci",
      "url": "https://tim.sillysamoyed.com/blog/playwright-1-59-healer-agent-ci",
      "title": "Playwright 1.59 turns failures into reviewable evidence",
      "summary": "The 1.59 agents plus screencast and browser.bind shift your job from chasing selectors to reviewing what the Healer did.",
      "date_published": "2026-05-14T00:00:00.000Z",
      "tags": [
        "Playwright",
        "TestAutomation",
        "AITesting",
        "QA",
        "CI"
      ]
    },
    {
      "id": "https://tim.sillysamoyed.com/blog/k6-2-ai-performance-testing",
      "url": "https://tim.sillysamoyed.com/blog/k6-2-ai-performance-testing",
      "title": "k6 2.0 moves load-test authoring into the CLI",
      "summary": "Grafana previewed k6 2.0 at GrafanaCON 2026: AI authoring in the CLI, an MCP server, and a Playwright-to-k6 converter.",
      "date_published": "2026-05-12T00:00:00.000Z",
      "tags": [
        "PerformanceTesting",
        "TestAutomation",
        "k6",
        "Grafana",
        "AI"
      ]
    },
    {
      "id": "https://tim.sillysamoyed.com/blog/playwright-mcp-locator-tax",
      "url": "https://tim.sillysamoyed.com/blog/playwright-mcp-locator-tax",
      "title": "The locator tax nobody puts in the budget",
      "summary": "Broken-test triage is a staffing decision disguised as a process one. Here is the cost, and where AI self-healing pays it back.",
      "date_published": "2026-05-12T00:00:00.000Z",
      "tags": [
        "EngineeringLeadership",
        "SoftwareEngineering",
        "TestAutomation",
        "DevProductivity",
        "QualityAssurance"
      ]
    },
    {
      "id": "https://tim.sillysamoyed.com/blog/playwright-ai-agents",
      "url": "https://tim.sillysamoyed.com/blog/playwright-ai-agents",
      "title": "Playwright agents and the new QA skills gap",
      "summary": "Playwright v1.56 put a Planner, Generator, and Healer in the test runner. The interesting part is what it asks of the engineers who own the suite.",
      "date_published": "2026-05-10T00:00:00.000Z",
      "tags": [
        "Playwright",
        "SoftwareTesting",
        "AI",
        "TestAutomation",
        "QualityAssurance"
      ]
    }
  ]
}