Skip to content

feat(uipath-activity-migrator): ask before downloading UiPath.Upgrade.exe - #4536

Merged
astridstaicu merged 4 commits into
mainfrom
feat/activity-migrator-download-consent
Nov 9, 2026
Merged

astridstaicu merged 4 commits into
mainfrom
feat/activity-migrator-download-consent

Conversation

@costin-uipath

@costin-uipath costin-uipath commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

Why

Enterprise feedback: the skill fetched UiPath.Upgrade.Cli.zip and ran the exe from %LOCALAPPDATA% without asking, outside the customer's software distribution controls. The mechanisms for a preinstalled or mirrored binary (UIPATH_ACTIVITY_MIGRATOR_DIR / _URL / _OFFLINE) already existed. This PR adds the consent step and surfaces those mechanisms at the moment they matter.

What

  • scripts/ensure-migrator.mjs: a plain run locates and verifies the cached tool, and exits 3 with status: missing (plus dir and url) when nothing is cached. --install downloads; --force implies it. UIPATH_ACTIVITY_MIGRATOR_OFFLINE=1 wins over both. A changed archive on a plain run is reported as update: true and the cached tool is kept.
  • SKILL.md: Rule 15 (never download unasked); Step 0 rows for missing and offline-missing; the install question with two options (download now, or the user places the tool and sets UIPATH_ACTIVITY_MIGRATOR_DIR). An explicit download request in the task counts as the choice.
  • references/acquisition-guide.md: flags table, output contract, Updating, and a new Managed environments section (preinstalled binary, internal mirror, no-download).
  • tests/scripts/activity-migrator-ensure-migrator.test.mjs: cases for missing, --install, offline precedence and update: true. The harness hands the fake SystemRoot to the child as FAKE_SYSTEMROOT, so the suite runs on Windows as well.
  • Task prompts: the 11 migrator tasks that reach Step 0 state "Download the Activity Migrator if it is not installed.", so unattended runs proceed.
  • New smoke task download-consent/download_consent_smoke.yaml: a simulated user declines the install question. The prompt names an empty sandbox folder as UIPATH_ACTIVITY_MIGRATOR_DIR, so the script reports missing on any runner and the test touches nothing outside the sandbox. Graded on the stop: no --install/--force, no archive fetch, no tool invocation, no persisted variable, no output, source byte-identical.

Verification

  • node --test tests/scripts/activity-migrator-ensure-migrator.test.mjs: 33 passed, 1 skipped (the non-Windows refusal case, on a Windows host).
  • npm run skills:check-links, npm run skills:validate, python scripts/check-sensitive-content.py: clean.
  • Local coder-eval runs on this branch (claude-sonnet-5-5, tool cache removed before each run): left_classic_smoke 1.0, migrate_selector_classes_e2e 1.0, plan_check_app_state_local 1.0. In each run the plain script returned missing, the agent ran --install and got source: downloaded, and asked no question. Judge criteria graded by hand per the local-run convention: left-classic 1.0 (report shape and counts exactly as the prompt lists them), selector-classes 0.7 (content correct, minor padding).
  • This PR's required Windows smoke check ran migrate_classic_windows on a fresh runner with no cached tool and passed.
  • download_consent_smoke local run on the pushed revision (claude-sonnet-5-5, tool present in the default cache): 1.0, 8 of 8 criteria, 36 s. The agent ran the script with the named folder, reported the tool missing, downloaded nothing, laid out both routes (the user places the tool, or asks for the download), and stopped on the decline.
  • Two interactive sessions on real projects (consent-banner-classic, staff-directory-audit): the install question was asked once with the URL and target folder filled in, and the download followed the user's choice.

🤖 Generated with Claude Code

costin-uipath and others added 2 commits November 6, 2026 19:12
….exe

Enterprise feedback: the skill fetched UiPath.Upgrade.Cli.zip and ran the
exe from %LOCALAPPDATA% without asking, outside the customer's software
distribution controls. The mechanisms for a preinstalled or mirrored
binary (UIPATH_ACTIVITY_MIGRATOR_DIR / _URL / _OFFLINE) already existed;
what was missing was consent and discoverability.

ensure-migrator.mjs: a plain run only locates and verifies, and exits 3
with status "missing" (plus dir and url) when nothing is cached. Downloads
need --install (--force implies it). _OFFLINE=1 wins over both, which also
stops --force from downloading in offline mode. A changed archive on a
plain run is reported as "update: true" instead of being replaced.
--check-only is gone: it is the default now.

SKILL.md: Rule 15 (never download unasked), the missing / offline-missing
rows in Step 0, and the two-option install question (agent downloads, or
the user places the tool and sets UIPATH_ACTIVITY_MIGRATOR_DIR).

acquisition-guide.md: flags, output contract, Updating, and a new
"Managed environments" section (preinstalled binary, internal mirror,
no-download).

Tests: download cases pass --install; new cases for missing, offline
precedence and update reporting. The harness now hands the fake SystemRoot
to the child as FAKE_SYSTEMROOT and applies it in the preload: node.exe
aborts at startup when SystemRoot points nowhere, so the suite had never
run on Windows.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The skill downloads UiPath.Upgrade.exe only after the user chooses to
(Rule 15), and an explicit request in the task counts as that choice.
Evaluation runs have nobody to answer the install question, so every task
that reaches Step 0 now says "Download the Activity Migrator if it is not
installed." in its prompt. On a runner with a cached tool the sentence is
a no-op; on a cold runner it is what lets the task proceed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @costin-uipath's task in 1m 10s —— View job


Coder-eval task lint (advisory)

11 task YAMLs changed. Verdicts: 0 Critical, 0 High, 0 Medium, 0 Low, 11 OK.

Rubric: .claude/commands/lint-task.md. This check is advisory and never blocks merge.

Evidence of passing run

  • ✅ Author confirms passing run: "Local coder-eval runs on this branch (claude-sonnet-5-5, tool cache removed before each run): left_classic_smoke 1.0, migrate_selector_classes_e2e 1.0, plan_check_app_state_local 1.0."
    • Note: that claim covers 3 of the 11 modified tasks. The other 8 only gain the same one-sentence prompt line, so the risk is low. If you have run any of them, please add them to the PR description.

Per-task lint

Each task gains the same line in initial_prompt: "Download the Activity Migrator if it is not installed." I did not raise this under Prompt over-specification. It grants consent and adds no steps: it does not name ensure-migrator.mjs, --install, or any path, so the agent still has to learn the Step 0 flow from the skill. It belongs with the existing environment line ("The uip CLI is available and authenticated"). Every task was read in full, and the existing criteria are unchanged and strong: run_command builds that the harness runs itself, byte-identical source checks, file_check on package pins, and command_executed on analyze/upgrade.

tests/tasks/uipath-activity-migrator/left-classic/left_classic_smoke.yaml — verdict: OK

tests/tasks/uipath-activity-migrator/migrate-classic/migrate_classic_windows.yaml — verdict: OK

tests/tasks/uipath-activity-migrator/migrate-gsuite-gmail/migrate_gsuite_gmail_integration.yaml — verdict: OK

tests/tasks/uipath-activity-migrator/migrate-microsoft-activities/migrate_microsoft_activities_integration.yaml — verdict: OK

tests/tasks/uipath-activity-migrator/migrate-outlook-mail/migrate_outlook_mail_integration.yaml — verdict: OK

tests/tasks/uipath-activity-migrator/migrate-selector-classes/migrate_selector_classes_e2e.yaml — verdict: OK

tests/tasks/uipath-activity-migrator/migrate-with-fixes/migrate_with_fixes_e2e.yaml — verdict: OK

tests/tasks/uipath-activity-migrator/plan-check-app-state/plan_check_app_state_local.yaml — verdict: OK

tests/tasks/uipath-activity-migrator/runtime-fix-loop/runtime_fix_loop_local.yaml — verdict: OK

tests/tasks/uipath-activity-migrator/runtime-pass/runtime_pass_local.yaml — verdict: OK

tests/tasks/uipath-activity-migrator/stop-missing-package/stop_missing_package_smoke.yaml — verdict: OK

Within-PR duplicates

  • No duplicate clusters detected. No new task YAMLs were added; all 11 were modified.

Themes

  • No task covers the new consent behaviour (advisory, skill-level gap). Every task that reaches Step 0 now grants the download in its prompt. No task checks the agent's behaviour without that grant: a plain run returns status: missing, the agent asks the install question, and it does not run --install before the user answers (Rule 15). Suggested coverage:
    • Pick one simulation task (for example runtime-pass/runtime_pass_local.yaml, lines 34–60). Drop the grant from initial_prompt and add a persona constraint such as "When asked whether to download the Activity Migrator, choose to download it now." This tests the question flow and leaves the rest of the task unchanged.
    • Or add a small smoke task with an empty tool cache, where the persona declines or chooses to place the tool. Grade it with command_not_executed on ensure-migrator\.mjs[^\n]*--(install|force) and on UiPath\.Upgrade\.Cli\.zip|download\.uipath\.com/upgrade, the same pattern as in refuse-non-windows/refuse_non_windows_smoke.yaml:59.
  • CLI verb reachability was not run. scripts/check-cli-verbs.py was blocked by this job's tool permissions. No command_pattern in the diff changed, so no new verb findings are expected.

Conclusion

  • ✅ All changed tasks pass the rubric. Evidence of passing run confirmed for 3 of the 11 tasks; the rest carry the same one-line change. One advisory gap: no task tests the new consent question itself.

@github-actions

github-actions Bot commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @costin-uipath's task in 1m 35s —— View job


Summary

This PR stops ensure-migrator.mjs from downloading on its own. A plain run now only locates and verifies the tool. When nothing is cached it reports missing with dir and url, and only --install or --force downloads; OFFLINE=1 overrides both. SKILL.md gets Rule 15, two new Step 0 rows and the install question. The acquisition guide documents the managed-environment presets, and the 11 tasks that reach Step 0 now grant the download in their prompt.

Change-by-Change Review

1. skills/uipath-activity-migrator/scripts/ensure-migrator.mjs

OK. The logic holds up:

  • The missing emit (L91) runs before any network call, so an unconsented run never contacts download.uipath.com.
  • The offline-missing check comes first (L88), so offline overrides --install.
  • FORCE and INSTALL are both gated on !OFFLINE (L202–203), so --force under offline keeps the cache.
  • On a plain run with update: true the stamp is left alone, so a later --install still sees the change. The test asserts this.

Nit (Low): the verify-failed message at L248 still tells the reader to "rerun with --force". Rule 15 forbids the agent from passing that flag on its own after verify-failed, and the Step 0 table sends verify-failed to "any other error: Show message. Stop." The agent relays the hint, but nothing says what to do if the user then agrees to a re-download. Consider one line in SKILL.md: if the user approves a re-download after verify-failed, that counts as the install choice.

2. skills/uipath-activity-migrator/SKILL.md

OK, with two Low nits.

  • Rule 15 (L46) is clear and numbered. It also covers the env vars, which stops the agent from setting OFFLINE or DIR itself to get past a missing.
  • The new table rows and the install question fill in <URL> and <DIR> from the script output, so the agent does not invent them.
  • Low: the ok row now ends "…continue with the cached tool. Continue." The word "Continue" appears twice.
  • Low: the question is "asked once per task". There is no instruction for option 2 when the rerun with the user's folder still returns missing (wrong folder, or the exe is nested one level deeper). Should the agent ask again or stop? One clause would settle it, for example: "missing again after option 2: tell the user the folder does not hold UiPath.Upgrade.exe and wait."
  • The fix-only entry (L50) skips Step 0, so the unchanged post_migration_fix_only.yaml is correct.
  • The studioweb flavor override only touches host-availability-extra, which this PR does not change. No flavor drift.

3. skills/uipath-activity-migrator/references/acquisition-guide.md

OK. The flags table, output contract (dir/url, update) and exit codes match the script. Removing --check-only is complete: no reference to it remains under skills/, and the old manual verify command now uses the plain run. The anchors #manual-placement and #managed-environments resolve. The Managed environments section links from SKILL.md and does not restate the install question.

4. tests/scripts/activity-migrator-ensure-migrator.test.mjs

OK. New tests cover four cases:

  • missing with no calls and no current/
  • offline overriding both --install and --force
  • update: true with the stamp left untouched
  • --install replacing a cache whose archive changed

Existing download tests now pass --install explicitly. Passing the fake SystemRoot as FAKE_SYSTEMROOT is a sound fix for running the suite on Windows. (I couldn't run the suite here because node --test needed approval in this runner, so I'm relying on the 33 passed / 1 skipped reported in the PR body.)

5. Task YAML prompt edits (11 files)

OK, with one Medium gap (see below). The added sentence is minimal and grants the download, which Rule 15 says counts as the choice. refuse-non-windows correctly stays unchanged: it stops before any download decision. post-migration-fix also stays unchanged, because it skips Step 0.

What's Missing

  • Medium: no task exercises the new consent behavior. Every task that reaches Step 0 now pre-grants the download, so nothing checks Rule 15 itself: asking when the prompt gives no grant, and never running --install when the user declines. Several tasks already use simulation: enabled. A small simulated task would cover it: a prompt without the grant, a simulated user who picks option 2 (or declines), and success criteria command_not_executed on ensure-migrator\.mjs.*--(install|force) plus command_executed on the plain ensure-migrator\.mjs. Fix this →
  • Low: no unit test for a plain run with an env DIR and nothing cached, though the existing missing test already runs with an env dir by default.

Area Ratings

Area Status Notes
Frontmatter OK Unchanged
E2E Tests Issue No behavioral test of the consent path (Medium)
Skill Body OK Two Low nits: duplicate "Continue", option-2 retry path
References & Assets OK Links and anchors resolve; contract matches the script
Repo Hygiene OK Scoped to one skill, no secrets; the .invalid URL in tests is fine

Issues for Manual Review

  • With a tool cached, a plain run still sends a HEAD to the archive URL on every run (documented in Updating). This is not a download, but some enterprise reviewers may count any outbound contact as "outside distribution controls". Today only OFFLINE=1 suppresses it, which also blocks installs. Confirm this matches what the enterprise feedback asked for.
  • Please check that the UI path in option 2 ("Automation Cloud → Help → Resources → Downloads → Activity Migrator Tool") is accurate.

Conclusion

Approve with minor suggestions. The consent gate is correct in the script, documented in one place and backed by unit tests. The main follow-up is a simulated task that checks the agent actually asks and does not download when the prompt gives no grant.

@github-actions

github-actions Bot commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

skill-lint: no new errors or warnings

Only what this PR adds is listed, compared with the commit it branched from; issues already on the base branch are not. Updated on every push.

…tion guide

SKILL.md had grown past the 40,000 bytes Codex keeps from one read, so
the middle of the workflow would be dropped on that host. The install
question and its two option paths now live in acquisition-guide.md
§ Install question; Step 0's `missing` row points there. SKILL.md is
38,539 bytes.

Two gaps closed while moving it: a user's go to re-download after
`verify-failed` counts as the install choice (Rule 15), and a `missing`
result after option 2 means the named folder holds no UiPath.Upgrade.exe:
the agent says so and waits, without downloading or asking again.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@costin-uipath
costin-uipath force-pushed the feat/activity-migrator-download-consent branch from bb12b2a to e7d0245 Compare November 7, 2026 12:00
A simulated user is asked how to get the Activity Migrator and declines.
The prompt names an empty sandbox folder as UIPATH_ACTIVITY_MIGRATOR_DIR,
so the acquisition script reports `missing` on every runner, cached tool or
not, and nothing outside the sandbox is touched. Graded on side effects:
the script ran once with the named folder, the tool was never downloaded
(no --install or --force, no fetch of the archive by another route), the
tool never ran, the variable was never persisted, no output or .upgrade
folder exists, the install folder is absent or empty, the source is
byte-identical, and no uip rpa command ran. The download check carries
5.0 of 15.0, so it alone decides the task under the smoke gate's 0.7 bar.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@costin-uipath
costin-uipath force-pushed the feat/activity-migrator-download-consent branch from e7d0245 to 7944456 Compare November 7, 2026 12:24
@astridstaicu
astridstaicu merged commit 127fb3b into main Nov 9, 2026
54 checks passed
@astridstaicu
astridstaicu deleted the feat/activity-migrator-download-consent branch November 9, 2026 09:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants