[spark-compete] fix(os): tolerate TCC-protected (unreadable) ~/Desktop in discover_repo_paths#619
Closed
banse wants to merge 1 commit into
Closed
Conversation
discover_repo_paths in system_map.py checked desktop.exists() then iterated desktop.iterdir() with no error handling. On macOS the default ~/Desktop is TCC-protected: .exists() returns True but .iterdir() raises PermissionError ([Errno 1] Operation not permitted). That uncaught error crashed `spark os capabilities|compile|authority|trace|memory` with a raw traceback (exit 1). A missing Desktop was already handled gracefully; an unreadable one now is too. Merged PR vibeforge1111#603 hardened the sibling filesystem walkers in this file against PermissionError but missed discover_repo_paths. This completes that coverage with the same narrow OSError handling pattern. Fix: snapshot desktop.iterdir() inside try/except OSError -> [] before iterating, mirroring the surrounding narrow-exception style. Adds a regression test that drives discover_repo_paths with a desktop whose iterdir() raises PermissionError plus a non-empty installed dict, asserting it returns the installed paths without raising. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Spark Compete Packet
{ "schema": "spark-compete-hotfix-v1", "event": "spark-compete-first-event", "submission_mode": "public_repo_pr", "submission_target_url": "https://github.com/vibeforge1111/spark-cli/pull/619", "team": { "name": "The Dudes", "members": [ "His Dudeness", "El Duderino", "Duder" ], "llm_device_holder": "His Dudeness", "device_holder_github": "banse", "github_accounts": [ "banse" ] }, "target_repo": { "id": "vibeforge1111/spark-cli", "source": "https://github.com/vibeforge1111/spark-cli", "owner_surface": "spark-cli" }, "issue": { "type": "bug", "severity": "high", "title": "spark os subcommands crash with PermissionError on TCC-protected macOS ~/Desktop", "actual_behavior": "discover_repo_paths() in src/spark_cli/system_map.py guards on desktop.exists() but then calls desktop.iterdir() with no error handling. On a default macOS account the ~/Desktop directory is TCC-protected: .exists() returns True while .iterdir() raises PermissionError ([Errno 1] Operation not permitted). The error is uncaught, so `spark os capabilities` (and compile/authority/trace/memory, which all walk the desktop for repo discovery) crash with a raw Python traceback and exit 1.", "expected_behavior": "An unreadable Desktop should be tolerated the same way a missing Desktop already is: skip Desktop-based repo discovery, fall back to installed-module paths, and exit 0 with normal output. No traceback.", "repro_steps": [ "On a default macOS account where the terminal/agent has not been granted Files-and-Folders / Full Disk Access, ~/Desktop is TCC-protected.", "From an installed Spark or a spark-cli checkout run: spark os capabilities (equivalently python -m spark_cli.cli os capabilities).", "Observe a PermissionError traceback originating in discover_repo_paths (system_map.py, the `for child in desktop.iterdir()` line); process exits 1.", "The same crash affects spark os compile, spark os authority, spark os trace, and spark os memory." ], "affected_workflow": "spark os capabilities|compile|authority|trace|memory and the onboarding system-map it backs" }, "evidence": { "safe_links_only": true, "before_after_proof": "BEFORE: `spark os capabilities` on the installed CLI exits 1 with a redacted, bounded traceback ending in `PermissionError: [Errno 1] Operation not permitted: '<HOME>/Desktop'` raised at system_map.py discover_repo_paths. A new regression test reproduces the same PermissionError before the fix. AFTER: the regression test passes and `spark os capabilities` exits 0 with clean output and empty stderr. Full suite delta: baseline 36 failed / 660 passed vs with-fix 36 failed / 661 passed (the +1 is the new passing test; the 36 pre-existing failures are an unrelated unittest.mock import quirk present on clean main).", "links": [ "https://github.com/vibeforge1111/spark-cli/blob/master/src/spark_cli/system_map.py", "https://github.com/vibeforge1111/spark-cli/pull/619" ], "forbidden": [ "pdf", "zip", "exe", "unknown downloads", "tokens", "raw logs", "private repo maps", "secrets", "wallet material" ] }, "proposed_fix": { "approach": "Snapshot desktop.iterdir() inside a narrow try/except OSError (children = [] on failure) before iterating, matching the narrow-exception style merged in PR #603 for the sibling walkers in this same file. Smallest possible change; behavior for a readable or missing Desktop is unchanged, and an unreadable Desktop now degrades gracefully to the installed-module fallback paths.", "files_expected": [ "src/spark_cli/system_map.py", "tests/test_system_map.py" ], "tests_or_smoke": "python -m pytest tests/test_system_map.py::SparkSystemMapTests::test_discover_repo_paths_tolerates_unreadable_desktop -v (fails with PermissionError before the fix, passes after). Smoke: `spark os capabilities` exits 0 after the fix." }, "pr": { "branch": "fix/cli-os-desktop-permissionerror", "title_prefix": "[spark-compete]", "author_github": "banse", "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": "https://github.com/vibeforge1111/spark-cli/pull/619" }, "review_claim": { "impact_claim": "high", "evidence_types": [ "failing_test", "passing_test", "redacted_terminal_excerpt" ], "duplicate_notes": "Direct relationship to merged PR #603 ('Adopt narrow health and system-map exception handling'), which hardened the sibling filesystem walkers in this same file against PermissionError but MISSED discover_repo_paths. This PR completes that exact coverage with the same OSError pattern. Open PRs #475/#530/#314/#306 touch spark os / desktop discovery for unrelated concerns (JSON ok-field/exit-code, WSL desktop path, source-path resolution) and do not guard discover_repo_paths against PermissionError; closed PRs #536/#532/#534 narrow bare-excepts elsewhere in the file. Open PR #60 ('Handle os compile output permission failures') handles a PermissionError when WRITING the compiled system-map.json output in cmd_os_compile (cli.py); it does not touch system_map.py discover_repo_paths and does not prevent this read-side crash \u2014 `spark os capabilities` still crashes during ~/Desktop discovery even with #60 applied. Distinct root cause (read/scan of an unreadable ~/Desktop vs write of the output file). None fix this macOS TCC Desktop discovery crash. Re-checked against master immediately before submission.", "risk_notes": "Low risk. Change is confined to one helper and only adds a narrow OSError guard around a directory scan; it never broadens behavior, touches no secrets/credentials/installer/CI, and falls back to the already-supported installed-module path set. No security-sensitive surface; not a prompt-injection or network path.", "review_state_requested": "pr_review" } }Repro
Actual behavior: discover_repo_paths() in src/spark_cli/system_map.py guards on desktop.exists() but then calls desktop.iterdir() with no error handling. On a default macOS account the ~/Desktop directory is TCC-protected: .exists() returns True while .iterdir() raises PermissionError ([Errno 1] Operation not permitted). The error is uncaught, so
spark os capabilities(and compile/authority/trace/memory, which all walk the desktop for repo discovery) crash with a raw Python traceback and exit 1.Expected behavior: An unreadable Desktop should be tolerated the same way a missing Desktop already is: skip Desktop-based repo discovery, fall back to installed-module paths, and exit 0 with normal output. No traceback.
Steps a reviewer can follow:
for child in desktop.iterdir()line); process exits 1.Safe Evidence
Before / after proof: BEFORE:
spark os capabilitieson the installed CLI exits 1 with a redacted, bounded traceback ending inPermissionError: [Errno 1] Operation not permitted: '<HOME>/Desktop'raised at system_map.py discover_repo_paths. A new regression test reproduces the same PermissionError before the fix. AFTER: the regression test passes andspark os capabilitiesexits 0 with clean output and empty stderr. Full suite delta: baseline 36 failed / 660 passed vs with-fix 36 failed / 661 passed (the +1 is the new passing test; the 36 pre-existing failures are an unrelated unittest.mock import quirk present on clean main).Tests or smoke command:
python -m pytest tests/test_system_map.py::SparkSystemMapTests::test_discover_repo_paths_tolerates_unreadable_desktop -v (fails with PermissionError before the fix, passes after). Smoke:spark os capabilitiesexits 0 after the fix.Scope And Risk
fix/cli-os-desktop-permissionerror.Duplicate Search
spark os capabilitiesstill crashes during ~/Desktop discovery even with Handle os compile output permission failures #60 applied. Distinct root cause (read/scan of an unreadable ~/Desktop vs write of the output file). None fix this macOS TCC Desktop discovery crash. Re-checked against master immediately before submission.Contributor Checklist
status: pass).