{"slug": "triage-a-ci-boolean-parsing-failure-with-a-human-runner-and-coding-agent", "title": "Triage a CI boolean parsing failure with a human runner and coding agent", "summary": "A developer demonstrated a workflow for handing a CI boolean-parsing failure to a coding agent, using a local Node 22 fixture where `Boolean(process.env.DRY_RUN)` treats the string \"false\" as truthy and fails to reject invalid input. The writeup pairs a human runner who captures the failing test output and confirms the configuration contract with a coding agent that replaces only the parser, preserving four assertions and requiring a named human reviewer for acceptance.", "body_md": "EDITORIAL HOLD — W-411 / NEEDS REVIEW. This private draft omits the assigned Wagglet promotion because DEV prohibits business promotion in AI-assisted articles and posts primarily intended to build backlinks. Resolve the platform/link requirement before publishing. The tutorial below is ready for technical review.\n\nAn environment variable contains the string `\"false\"`, but the job still enters its dry-run branch. The problem can be one line: `Boolean(process.env.DRY_RUN)`. Any nonempty string is truthy in JavaScript.\n\nThis small example shows how to hand that failure from a human runner to a coding agent without turning a configuration bug into a broad CI rewrite. It is a local Node fixture, not a report of a production incident or a hosted CI run.\n\nUse Node 22 and an empty directory. Save this as `broken.mjs`:\n\n``` js\nexport const readDryRun = value => Boolean(value);\n```\n\nSave this as `config.test.mjs`:\n\n``` python\nimport test from 'node:test';\nimport assert from 'node:assert/strict';\n\nconst { readDryRun } = await import(\n  process.env.CANDIDATE || './broken.mjs'\n);\n\ntest('unset defaults to false', () =>\n  assert.equal(readDryRun(undefined), false));\ntest('true enables dry run', () =>\n  assert.equal(readDryRun('true'), true));\ntest('false disables dry run', () =>\n  assert.equal(readDryRun('false'), false));\ntest('invalid input fails closed', () =>\n  assert.throws(() => readDryRun('maybe'),\n    /DRY_RUN must be true or false/));\n```\n\nRun `node --test config.test.mjs`. In the prepared fixture, using Node 22.23.2, the result was exit code 1. This excerpt removes variable timing details:\n\n```\nok 1 - unset defaults to false\nok 2 - true enables dry run\nnot ok 3 - false disables dry run\nnot ok 4 - invalid input fails closed\n# tests 4\n# pass 2\n# fail 2\n```\n\nThe third test receives `true` where it expects `false`. The fourth reports a missing expected exception. These are two consequences of the same parser: it interprets presence, not the permitted values.\n\nThe human runner owns this first step. They run commands through their own authorized terminal or CI interface, preserve the output, and confirm the intended configuration contract with the project owner. A test cannot decide whether an unset variable should default to false; that is a product or operations decision recorded here as an explicit assumption.\n\nA useful coding agent task management record includes the failure, allowed change, and acceptance evidence together. Here is a copyable task template, filled in for this example:\n\n```\nTask: Parse DRY_RUN as an explicit boolean\n\nOwner / executor: coding agent in its authorized workspace\nPreparer: human runner\nAcceptance reviewer: named human maintainer\n\nObserved failure:\n  node --test config.test.mjs exits 1.\n  \"false\" becomes true; \"maybe\" does not throw.\n\nRequired contract:\n  undefined -> false\n  \"true\" -> true\n  \"false\" -> false\n  anything else -> TypeError(\"DRY_RUN must be true or false\")\n\nScope:\n  Replace the parser only. Preserve the four assertions.\n  No workflow edits, dependency updates, deployment changes,\n  secret access, network calls, or credential changes needed.\n\nDeliver:\n  Parser diff, exact test command, exit code, and test summary.\n  State what was not exercised outside this local fixture.\n\nAcceptance:\n  Reviewer inspects the branch conditions and reruns all four tests.\n  A passing parser test does not establish that a real CI job is fixed.\n```\n\nIn a real repository, replace the fixture filenames with the actual module and test paths. Attach a sanitized failure log rather than a screenshot containing tokens or private job variables. Name the reviewer before execution begins so delivery does not become an unowned message saying “done.”\n\nThe coding agent uses its own authorized tools to implement and verify the change. The runner can supply missing evidence, but neither role needs another person's account or token to execute this fixture.\n\nSave this candidate as `fixed.mjs`:\n\n```\nexport function readDryRun(value) {\n  if (value === undefined || value === 'false') return false;\n  if (value === 'true') return true;\n  throw new TypeError('DRY_RUN must be true or false');\n}\n```\n\nThen run:\n\n```\nCANDIDATE=./fixed.mjs node --test config.test.mjs\n```\n\nThe prepared candidate returned exit code 0 with four passing tests and zero failures. The baseline remains available, so the reviewer can rerun both commands and see that the test distinguishes the broken and corrected implementations.\n\nDo not quietly accept `FALSE`, an empty string, whitespace, or `1` while making this repair. Those values are outside the stated contract. If the real job requires them, agree on that behavior and add corresponding cases before changing the parser.\n\nThe reviewer checks that the parser implements the agreed contract, no assertions were weakened, and the diff stays inside scope. They rerun the candidate command from the same directory and inspect the baseline if the failure is unclear.\n\nFor an actual failing CI job, one more check remains: confirm that the job imports this parser and rerun the relevant job through an authorized account. This fixture exercises configuration parsing only. It does not run a deployment, contact a service, or prove that an unrelated pipeline failure has disappeared.\n\nKeep three artifacts together at handoff: the original failure, the small patch, and the verification output. That lets the human reviewer accept a specific change with visible limits.\n\n*AI assistance disclosure: This tutorial and its demonstration fixture were prepared with AI assistance. The baseline and candidate commands were executed locally. The publishing author should review and understand the explanation before publication.*", "url": "https://wpnews.pro/news/triage-a-ci-boolean-parsing-failure-with-a-human-runner-and-coding-agent", "canonical_source": "https://dev.to/patilrb/needs-review-triage-a-ci-boolean-parsing-failure-with-a-human-runner-and-coding-agent-4jf9", "published_at": "2026-10-15 08:35:50+00:00", "updated_at": "2026-10-15 08:46:02.227826+00:00", "lang": "en", "topics": ["ai-agents", "developer-tools", "mlops"], "entities": ["Node.js"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/triage-a-ci-boolean-parsing-failure-with-a-human-runner-and-coding-agent", "markdown": "https://wpnews.pro/news/triage-a-ci-boolean-parsing-failure-with-a-human-runner-and-coding-agent.md", "text": "https://wpnews.pro/news/triage-a-ci-boolean-parsing-failure-with-a-human-runner-and-coding-agent.txt", "jsonld": "https://wpnews.pro/news/triage-a-ci-boolean-parsing-failure-with-a-human-runner-and-coding-agent.jsonld"}}