{
  "part": 17,
  "title": "(Optional / best-effort) Upgrade builder utility",
  "reset": "standard",
  "_comment": "Requires network access from dd-nas1 to the SVN server. Both steps are classified optional (run under --include-optional, per TESTING_automation.md's decision to include this Part in a real pass) but their assertions accept EITHER outcome - a successful build, or a network/connection failure - exactly matching TESTING.md's own framing that a network failure here 'is not a defect in the code being tested'. The generated upgrade.pl is only ever syntax-checked (run_perl_c), never executed - it is designed to overwrite a real sneakernet installation.",
  "steps": [
    { "id": "17.1", "title": "Attempt a build", "classification": "optional",
      "actions": [
        { "do": "run_utility", "script": "buildUpgradeOneShot.pl", "code_dir": "{CODE}",
          "args": [ "--output", "{TMP}/upgrade.pl" ],
          "capture": { "name": "LOG171" } }
      ],
      "assertions": [
        { "type": "regex_present", "var": "LOG171", "pattern": "(?i)Wrote one-shot installer to|svn checkout failed", "message": "either a successful build (revision reported, upgrade.pl written) or a network/connection failure (acceptable - not a defect being tested here)" }
      ]
    },
    { "id": "17.2", "title": "If Step 17.1 succeeded, sanity-check the generated file", "classification": "optional", "depends_on": ["17.1"],
      "actions": [
        { "do": "run_perl_c", "path": "{TMP}/upgrade.pl", "capture": { "name": "PERLC_172" } }
      ],
      "assertions": [
        { "type": "regex_present", "var": "PERLC_172", "pattern": "(?i)syntax OK|No such file or directory|[Cc]an't open", "message": "either upgrade.pl passes perl -c (17.1 succeeded), or it doesn't exist because 17.1 had no network access (also acceptable)" }
      ]
    }
  ]
}
