Skip to content

fix(cli): preserve uninstall feedback when a named target hits empty registry#1439

Open
4gjnbzb4zf-sudo wants to merge 1 commit into
vibeforge1111:masterfrom
4gjnbzb4zf-sudo:sentinel/ux-friction/uninstall-named-target-silent-fallback
Open

fix(cli): preserve uninstall feedback when a named target hits empty registry#1439
4gjnbzb4zf-sudo wants to merge 1 commit into
vibeforge1111:masterfrom
4gjnbzb4zf-sudo:sentinel/ux-friction/uninstall-named-target-silent-fallback

Conversation

@4gjnbzb4zf-sudo

@4gjnbzb4zf-sudo 4gjnbzb4zf-sudo commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

{
"schema": "spark-compete-hotfix-v1",
"event": "spark-compete-first-event",
"submission_mode": "public_repo_pr",
"submission_target_url": "#1439",
"team": {
"name": "SparkThisUp",
"members": [
"ValHallaBuilder",
"Baz707",
"DanFireDash"
],
"github_accounts": [
"4gjnbzb4zf-sudo"
],
"llm_device_holder": "ValHallaBuilder",
"device_holder_github": "4gjnbzb4zf-sudo"
},
"target_repo": {
"id": "vibeforge1111/spark-cli",
"source": "https://github.com/vibeforge1111/spark-cli",
"owner_surface": "spark-cli"
},
"issue": {
"type": "usage_friction",
"severity": "low",
"title": "spark uninstall silently exits 0 on an empty registry instead of naming the unmatched target",
"actual_behavior": "spark uninstall <name> against an empty registry (no installed modules) prints the generic 'No installed Spark modules recorded.' and exits 0, swallowing the named target the operator typed. They cannot tell whether their typo went somewhere or whether the registry is just empty.",
"expected_behavior": "On an empty registry, spark uninstall <name> echoes the unmatched target and the empty-registry condition, then exits non-zero so scripts and operators distinguish a real no-op from a silently-swallowed typo. Pure-success path (registry has the named module) is byte-identical.",
"repro_steps": [
"gh pr checkout ",
"Ensure no Spark modules installed locally (empty registry).",
"Run spark uninstall typo-name -> BEFORE: 'No installed Spark modules recorded.' + exit 0. AFTER: message includes the unmatched 'typo-name' + empty-registry context + exit != 0.",
"Run spark uninstall <real-installed-name> (after installing one) -> success path unchanged."
],
"affected_workflow": "Operators running uninstall against a fresh box / cleared state. The silent-success previously let them think their typo had been processed when nothing happened. The new path surfaces the typo + exit code so the operator self-recovers."
},
"evidence": {
"safe_links_only": true,
"before_after_proof": "Single-file change: src/spark_cli/cli.py, +7 / -1 in the uninstall empty-registry branch. The function now echoes the unmatched target and the empty-registry condition + exits non-zero. The 'registry has the module' branch returns the same uninstall result as before.",
"links": [
"https://github.com//pull/1439"
],
"forbidden": [
"pdf",
"zip",
"exe",
"unknown downloads",
"shortened links",
"archives",
"binaries",
"tokens",
"browser cookies",
"wallet material",
"raw logs",
"raw conversations",
"raw memory",
"raw patches",
"private repo maps",
"private scoring details"
]
},
"proposed_fix": {
"approach": "In the uninstall command's empty-registry branch, expand the message to echo the unmatched target argument and add the empty-registry context. Change the exit code from 0 to non-zero for the named-target-not-found case. The 'recognized name' branch is unchanged.",
"files_expected": [
"src/spark_cli/cli.py"
],
"tests_or_smoke": "python3 -m py_compile src/spark_cli/cli.py -> clean. Manual: spark uninstall typo-name on a clean registry now echoes the typo + exits non-zero. spark uninstall <real-installed-name> still succeeds."
},
"pr": {
"branch": "sentinel/ux-friction/uninstall-named-target-silent-fallback",
"title_prefix": "[spark-compete]",
"author_github": "4gjnbzb4zf-sudo",
"body_must_include": [
"packet",
"team",
"pr_author",
"repo",
"actual_behavior",
"expected_behavior",
"repro_steps",
"before_after_proof",
"tests_or_smoke",
"duplicate_notes",
"risk_notes",
"review_claim"
],
"url": "#1439"
},
"review_claim": {
"impact_claim": "low",
"evidence_types": [
"redacted_terminal_excerpt"
],
"duplicate_notes": "Pre-flight check returned siblings on this surface: PR #1162 (TOCTOU on uninstall path -- different concern), #1351 (--force hint -- different flag suggestion), #1352 (known-module suggestion -- different message path). None target the empty-registry named-target branch's silent exit 0.",
"risk_notes": "Local scope: one branch in the uninstall command's empty-registry path. Pure-success branch byte-identical. No new package. The exit-code change (0 -> non-zero) only fires when the named target was not found AND the registry was empty -- both previously silent success conditions.",
"review_state_requested": "pr_review"
}
}

…registry

When the operator runs `spark uninstall <name>` on a machine with no
installed modules, the command silently swallowed the named target and
printed the generic "No installed Spark modules recorded." with exit 0.
That hides a typo or stale-state condition behind a success surface.

Preserve the named target in the message and return a non-zero exit so
the operator sees that the requested module was not found. The `--all`
path keeps its current message and exit code.
@4gjnbzb4zf-sudo

Copy link
Copy Markdown
Contributor Author

TL;DR: spark uninstall <name> silently absorbs a typo'd or stale target when the registry has no installed modules. The operator sees "No installed Spark modules recorded." and an exit code of 0, with no acknowledgement of the name they typed. That hides a real friction case (fresh machine, post-purge retries, slightly wrong module name) behind a success surface.

Walkthrough:

  • I ran spark uninstall spark-bot on a clean machine. Real target name is spark-telegram-bot. Got the generic empty-registry message and exit 0. Re-ran the install steps before realizing the previous "success" never matched anything.
  • Tracing cmd_uninstall: resolve_installed_target_modules returns [] whenever the registry is empty -- regardless of whether a name was passed. The if not modules: branch then prints the generic message and returns 0 (unless an autostart failure was already recorded).
  • --all legitimately means "anything that's there"; on an empty registry, exit 0 is the correct outcome. A named target should not collapse into the same path.

Fix shape: when args.target is set (and --all is not), surface the named target ("Unknown installed module: . No modules are installed; run spark install first.") and return 1. --all and the autostart-only path keep their existing behavior. Wording matches the existing unknown_installed_module_message helper for the populated-registry case, so the operator sees a consistent shape across the two states.

Scope guard: one branch in cmd_uninstall, ~7 lines. No new imports, no helper changes, no behavior change to --all, --purge-home, --remove-user-path, or --remove-autostart. python3 -m py_compile src/spark_cli/cli.py clean.

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.

1 participant